Unerwartete Atmega16-Reaktion über UART
Kurze Zusammenfassung des Problems
Ich habe einen Atmega16 mit Code geflasht, der dazu führen sollte, dass der Atmega16 jedes Zeichen zurücksendet, das ich über ein Terminal an ihn sende. Ich bekomme eine Antwort, aber es ist selten der Charakter, den ich gesendet habe. Ich kann die korrekte Ausgabe sehen, indem ich die Baudrate ändere, aber ich verstehe nicht, warum die richtige Baudrate funktioniert.
Mehr Details
Ich versuche in meiner Freizeit mehr über Firmware-Programmierung zu lernen, weil es mir sehr gut gefällt. Bisher haben wir in der Firmware-Programmierung, die ich an der Uni durchgeführt habe, Skeleton-Code-Dateien erhalten, die einen Großteil der Peripherie-Schnittstellen übernehmen und für uns eingerichtet sind, aber ich würde dies gerne selbst lernen. Ich habe ein paar Fragen darüber, was ich hier mache, die im ganzen Beitrag verteilt sind, aber ich werde sie am Ende auflisten. Wenn Sie Missverständnisse oder potenzielle Wissenslücken aufgreifen, würde ich mich über Ihre Beiträge sehr freuen.
Der Code
Der Code, den ich auf meinem Atmega16 geflasht habe, stammt fast Zeile für Zeile aus dem Tutorial "Verwenden des USART in AVR-GCC" auf dieser Seite . Alles was ich hinzugefügt habe ist das #define für F_CPU. Der ursprüngliche Code hatte keine #define für F_CPU, sodass mein Code in AtmelStudio 7 nicht kompiliert werden konnte. Kann jemand erklären, warum der Autor F_CPU nicht in seiner Originaldatei definiert hätte? Ich vermute, sie haben möglicherweise ein anderes Tool oder einen anderen Compiler als Atmel Studio 7 verwendet, aber ich kann es nicht mit Sicherheit sagen.
#include <avr/io.h>
#define F_CPU 7372800 //this was chosen because the tutorial states this is the frequency we want to operate at
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((( F_CPU / 16) + ( USART_BAUDRATE / 2)) / ( USART_BAUDRATE )) - 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 theUBRR 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
}
}
Das Hardware-Setup
- MCU: Atmega16;
- Toolchain: Atmel Studio 7, blinkt mit AVR-Drache;
- Stromversorgung: 5-V-Schiene von einem von einer Universität bereitgestellten Entwicklungsboard (das vom Computer-USB stammt). 100nF Keramikscheibenkondensator zur Umgehung der Steckbrettstromleitungen
- USB zu seriellem Konverter: Dieser . TXD am USB-Seriell-Wandler an RXD Atmega angeschlossen (Pin 15). RXD am Konverter an RXD an Atmega angeschlossen (Pin 14).
Terminalsoftware: PuTTY (mit einer Baudrate von 9600).
Nachweis der falschen Antworten
Um es zu wiederholen, die Atmega sollte zurückkehren , was es heißt OUTPUT gesendet wurde sollte genau die gleichen wie INPUT sein.
PuTTY-Ausgabe
Oszilloskop-Aufnahmen
Ich habe mein Picoscope mit serieller Decodierung verwendet, um zu überprüfen, ob der Atmega die richtige Eingabe empfängt, die es zu sein scheint. Wenn ich zum Beispiel die Taste 'f' drücke, wird sie korrekt empfangen. Die Ausgabe ist immer noch eine '6' (oder gelegentlich ein kaufmännisches Und '&').
Ein Fix, auf den ich gestoßen bin, den ich nicht verstehe
Wenn ich die Baudrate auf 2500 in PuTTY ändere, wird alles korrekt angezeigt. Ich habe diesen Wert zufällig ausgewählt und weiß nicht, warum er funktioniert (es lässt mich glauben, dass ich irgendwo einen Fehler mit der Baudrate gemacht habe, aber ich sehe nicht, wo ich das Tutorial fast genau kopiert habe ... ich habe gedacht).
Fragen
- Was habe ich falsch gemacht / was passiert hier?
- Warum definiert das ursprüngliche Tutorial F_CPU nicht #?
- Warum behebt das Festlegen der Baudrate auf 2500 das Problem? (Ich vermute, dass dies beantwortet wird, wenn Frage 1 beantwortet wird)