So senden Sie eine Zeichenfolge in der seriellen Kommunikation in AVR-C

Wie der Titel schon sagt, möchte ich, anstatt jeweils ein Byte an Informationen zu senden, eine ganze Zeichenfolge senden können. Ich habe versucht, die Benutzereingabe in ein Array zu schreiben und jedes Element dieses Arrays zu übertragen. Allerdings konnte ich nur die ersten paar Buchstaben dazu bringen, nicht das gesamte Array zu übertragen, hier ist mein Code:

//tx serial
#include <avr/io.h> 

#define F_CPU 16000000 
#define BUAD 9600 
#define BUAD_RATE_CALC ((F_CPU/16/BUAD) - 1)  


int main(void){  

    char ar[]= "hello";

    //High and low bits
    UBRR0H = (BUAD_RATE_CALC >> 8); 
    UBRR0L = BUAD_RATE_CALC; 
    //////////////// 
    //transimit and recieve enable
    UCSR0B = (1 << TXEN0)| (1 << TXCIE0) | (1 << RXEN0) | (1 << RXCIE0); 
    UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);  //8 bit data format
    ////////////////////////////////////////////////////////////////
    int i = 0;

    while (1){  

    while (( UCSR0A & (1<<UDRE0))  == 0){};
        for (i = 0; i < strlen(ar); i++){ 
            UDR0 = ar[i]; 
        }
    }
}

Was wäre das Problem dabei?

Antworten (3)

Nicht ganz sicher, nur eine schnelle Vermutung. Vielleicht sollten Sie die while(UDRE0 == 0){}Sendezeichen dazwischen setzen. Ich glaube, es ist zu warten, bis ein Zeichen gesendet wurde.

for (i = 0; i < strlen(ar); i++){ 
   while (( UCSR0A & (1<<UDRE0))  == 0){};
   UDR0 = ar[i]; 
}
Du hast Recht. Jedes Mal, wenn Sie das Register „UDR0“ aktualisieren, startet die MCU eine neue Übertragung. Und es liegt am Programmierer, sicherzustellen, dass das Register nicht aktualisiert wird, bis das 'UDR0'-Register leer ist (Zeichen wurde gesendet), andernfalls tritt ein "Datenkollisionsfehler" auf und die MCU sendet keines von beiden.
ok, also meinst du, in meiner for-Schleife sollte ich eine weitere Warteschleife einbauen, um auf das Register zu warten, bevor ich inkrementiere, das macht Sinn, danke, ich werde testen, ob das so schnell wie möglich funktioniert
Also habe ich deinen Code ausprobiert und es funktioniert !! Als ich es jedoch tat, druckte es wie erwartet kontinuierlich Hallo aus, aber ich ließ es Null zurückgeben, damit es Hallo ausdruckte, sobald hier der Code ist
Sie sollten meine andere "Antwort" sehen, die das Problem mit dem kontinuierlichen "Hallo" -Druck behebt. Es gibt Ihnen auch einige bessere Handler/Funktionen zum Senden von Zeichen und zum Einrichten des uart.
Ich möchte darauf hinweisen, dass das while((blockiert und einiges an "CPU-Zeit" verschwenden kann, normalerweise mehr bei niedrigeren Baudraten. Durch die Verwendung von Sendeunterbrechungen können Sie das Schreiben "im Hintergrund" durchführen.

Also habe ich deinen Code ausprobiert und es funktioniert !! Als ich es jedoch tat, druckte es wie erwartet ununterbrochen Hallo aus, aber ich ließ es Null zurückgeben, damit es Hallo ausdruckte, sobald hier der Code ist:

            //data_buffer 

            //tx serial

            #include <avr/io.h> 

            #define F_CPU 16000000 
            #define BUAD 9600 
            #define BUAD_RATE_CALC ((F_CPU/16/BUAD) - 1)  
            #define buffer_size 128
            #define boolen 0
            int main(void){  
                char br;
                char ar[]= "hello";
                char buffer[10]; 
                //High and low bits
                UBRR0H = (BUAD_RATE_CALC >> 8); 
                UBRR0L = BUAD_RATE_CALC; 
                //////////////// 
                //transimit and recieve enable
                UCSR0B = (1 << TXEN0)| (1 << TXCIE0) | (1 << RXEN0) | (1 << RXCIE0); 
                UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);  //8 bit data format
                ////////////////////////////////////////////////////////////////
                int i = 0;

                while (1){  
                /*while( (UCSR0A & (1<<RXC0))  == 0 ){}; 
                    br = UDR0;
                */

                while (( UCSR0A & (1<<UDRE0))  == 0){};

                        for (i = 0; i < strlen(ar); i++){ 
                            while (( UCSR0A & (1<<UDRE0))  == 0){};
                            UDR0 = ar[i]; 
                            if (i == (strlen(ar) - 1)){ 
                                return 0;
                            }
                        } 
                }

            }   

Ich möchte darauf hinweisen, dass einige zufällige Variablen und Dinge definiert sind, die ich nicht einmal verwende, sondern sie einfach ignorieren

Übrigens eine andere Frage, wie würde ich verhindern, dass der Chip kontinuierlich sendet, ohne die Rückgabe 0 zu verwenden; in meinem Code? Da ich versuchen möchte, mehrere Zeichenfolgen gleichzeitig zu senden, oder die Array-Logik in eine Funktion einfügen möchte, die ich dann ausführen kann, nachdem der Benutzer etwas getan hat, z. B. wenn der Benutzer etwas eingibt, sendet der Chip, wann immer er etwas eingibt the array hallo, irgendwelche ideen? Müsste ich die tx-Interrupts verwenden?
Hier ist eine andere Sache, die ich tun möchte. Ich möchte in der Lage sein, den Chip daran zu hindern, Hallo ohne die Rückgabe 0 zu senden; Code. Ich denke über die Verwendung des TXCIEn-Interrupts nach. Aber ich bin etwas verwirrt darüber, dass dieser Interrupt dann ausgelöst wird. Wird er ausgelöst, wenn das Register leer oder wenn es voll ist?
Ich bin mir nicht sicher, aber (auf Arduino, schätze ich), wenn Sie den Hauptbildschirm verlassen, beginnt es mit zufälligem Verhalten.
FYI - Bei meiner WinAVR-Installation (GNU C-Toolchain) musste ich #include <string.h> hinzufügen, weil beim Erstellen eine Warnung auftauchte, die besagte: Warnung: implizite Deklaration der Funktion 'strlen' Warnung: inkompatible implizite Deklaration von eingebaut Funktion 'strlen'

Sie sollten für jede andere Frage, die Sie haben, eine neue Frage stellen ... Aber gut. Der folgende Code (Könnte ein bisschen im Arduino-Stil sein, aber es könnte dem Fragesteller helfen).

Der SetupCode wird nur einmal zu Beginn Ihres Programms ausgeführt. Großartig, um Peripheriegeräte zu initialisieren und / oder eine Hallo-Nachricht / Startroutine zu senden. Der LoopCode läuft ständig, normalerweise enthält dieser ein Programm wie blinkende LEDs ... oder das Sicherheitssystem eines Atomkraftwerks. Es ist jedoch nicht für die Rückgabe konzipiert, sondern für die Ewigkeit. Obwohl mein Code Sie in einer Weile (für immer) fangen wird; wenn du davon zurückkehren würdest.

Ich habe den Code nicht getestet, aber ich denke, es wäre dieser:

#include <avr/io.h> 
#define F_CPU 16000000 
#define BUAD 9600 
#define BUAD_RATE_CALC ((F_CPU/16/BUAD) - 1)  

//Function definitions
void Setup(void);
void Loop(void);
void serialSetup(void);
void serialSend(char* sendString);

//Global variables.
char ar[]= "hello";

void Setup(){
//Code to be run once (At start).
    serialSetup();
    serialSend(ar);
}

void Loop(){
    //Code to be run continiously.
}

void serialSetup(){
    //Register settings
    //High and low bits
    UBRR0H = (BUAD_RATE_CALC >> 8); 
    UBRR0L = BUAD_RATE_CALC; 
    //transimit and recieve enable
    UCSR0B = (1 << TXEN0)| (1 << TXCIE0) | (1 << RXEN0) | (1 << RXCIE0); 
    UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);  //8 bit data format
}

void serialSend(char* sendString){
     for (int i = 0; i < strlen(sendString); i++){ 
         while (( UCSR0A & (1<<UDRE0))  == 0){};
         UDR0 = sendString[i]; 
     } 
}

int main(void){  
    Setup();
    while(1){
       Loop();
    }
while(1){}//If you ever return from Loop(); This while will catch you, so it won't continue doing randomness.           
}