AVR USART OUTPUT fast ähnlich wie Eingang

Meine Ausgabe unterscheidet sich von meiner Eingabe, wenn ich versuche, sie von meinem Hercules-Terminal zu lesen. Könnte dies von einer schlechten UART-Initialisierung herrühren?

Eingänge : | a, 1, 123

Ausgänge:|a, ±, ±²³

Code:

#include <avr/io.h>
#ifndef F_CPU
#define F_CPU 1000000 // 1 Mhz
#endif

#define USART_BAUDRATE 9600
#define BAUD_PRESCALE ((( F_CPU / ( USART_BAUDRATE * 16UL ))) - 1)

int main (void)
{
    char ReceivedByte ;
    UCSRB = (1 << RXEN ) | (1 << TXEN ); // Turn on the transmission and reception circuitry
    UCSRC = (1 << URSEL ) | (1 << UCSZ0 ) | (1 << UCSZ1 ); // Use 8-bit character sizes
    UBRRH = ( BAUD_PRESCALE >> 8) ; // Load upper 8-bits of the baud rate value into the high byte
                                    //of the UBRR register
    UBRRL = BAUD_PRESCALE ; // Load lower 8 -bits of the baud rate value into the low byte of the
    //UBRR register
    for (;;) // Loop forever
    {
    while (( UCSRA & (1 << RXC )) == 0) {}; // Do nothing until data have been received and is
    //ready to be read from UDR
    ReceivedByte = UDR ; // Fetch the received byte value into the variable "ByteReceived"
while (( UCSRA & (1 << UDRE )) == 0) {}; // Do nothing until UDR is ready for more data to
//be written to it
UDR = ReceivedByte ; // Echo back the received byte back to the computer
}
}

Antworten (1)

Verwenden Sie ungefähre Zahlen für 9600 mit einem 1-MHz-Takt 1000000 / 9600 / 16 = 6,51, die auf 6 gekürzt und dann auf 5 fallen gelassen werden, sobald 1 subtrahiert wird. Sie können sehen, dass Sie viel Genauigkeit verlieren, wenn die Teilerzahlen so klein sind, wie sie in eine Ganzzahl umgewandelt werden. Hier finden Sie einen Taschenrechner, der Ihnen nützlich sein könnte:

AVR-Baudratenrechner von WormFood

Das zeigt einen Fehler von 7,5 %, was zu hoch ist. Sie benötigen eher 5 % für einen zuverlässigen Betrieb, wenn das angeschlossene Gerät sehr genau ist, aber normalerweise strebe ich einen Fehler von 2 % oder weniger an. Die Alternativen, die einem in den Sinn kommen, sind das Ändern Ihrer Quarzfrequenz (oder das Ausschalten der CKDIV8Sicherung, wenn Sie sie verwenden) oder die Auswahl einer Baudrate wie 4800, die bei dieser Taktrate eine akzeptable Fehlermarge aufweist.

Obwohl Sie sich die Tabelle weiter ansehen (durch Klicken auf das entsprechende Kontrollkästchen), wäre eine andere Option die Verwendung des U2X=1Modus, der die effektive UART-Taktrate verdoppelt, wodurch der Fehler auf 0,2 % sinken würde. In diesem Fall sollte Ihr Code Folgendes enthalten:

#define BAUD_PRESCALE ((( F_CPU / ( USART_BAUDRATE * 8UL ))) - 1)
UCSRA |= (1 << U2X);

Dies führt zwar dazu, dass der Empfänger halb so oft abtastet, was möglicherweise nicht ganz so zuverlässig ist, aber möglicherweise eine Option ist, wenn es einen Grund gibt, warum Sie die Taktrate nicht erhöhen möchten.

Woher weißt du, dass 5 schlecht ist?
Es liegt einfach daran, dass der Unterschied zwischen 5 und 5,51 prozentual ziemlich groß ist. Angenommen, Sie verwenden einen 10-MHz-Takt, es wäre 65,1 - 1 = 64,1, und der Unterschied zwischen 64 und 64,1 ist prozentual viel kleiner.