Hallo, bin schon eine ganze Weile am Fehlersuchen (auch hier im Forum). Leider hab bisher ich keinen Erfolg gehabt. Vielleicht könnt Ihr mir ja weiterhelfen. Mein Programm soll Daten über die serielle Schnittestelle des USART0 des ATmegas1284P empfangen und wieder zurücksenden. Um das zu testen habe ich im AVR Studio Simulator das Programm durchlaufen lassen. Natürlich bleibt er dann bei while ( !(UCSR0A & (1<<RXC0)) ); hängen, sodass ich in das UDR0 Register einen Wert schreiben und anschließend RXC0 auf 1 setzen musste. Das Programm läuft dann auch weiter allerdings verwirft er den Wert von UDR0 auch gleich wieder. Gesendet wird dann immer der Wert 0. Der unten stehende Code ist direkt kopiert, also original. Wenn jemand da ne Idee hat wär super. // Mikrocontroller: ATmega1284P // Externer Quarz: 20MHz // // Compiler: AVR-GCC /**********************Inkludierung der Headerdateien*****************/ #include <stdlib.h> #include <avr/io.h> #include <stdint.h> #include <util/delay.h> /*******************************Definitionen**************************/ #define LED_R (1<<PB0) #define LED_G (1<<PB1) #define PLED_L_R (1<<PD6) #define FLED (1<<PD2) #define BLED (1<<PD7) #define Summer (1<<PB5) /***********************Deklaration globaler Variablen****************/ char buffer; /**************************Unterprogramme*****************************/ void usart_init(unsigned int baud); void usart_transmit (unsigned char data); unsigned char usart_receive( void ); /******************************Hauptprogramm**************************/ int main ( void ){ DDRA = 0x00; DDRB = 0xFF; DDRC = 0x51; DDRD = 0xFE; usart_init(21); while (1) { usart_receive(); buffer = UDR0; usart_transmit(buffer); _delay_ms(1000); } } /***************************USART-Initialisierung*********************/ void usart_init( unsigned int baud ) { UCSR0A = 0x22; //00100010 -> Setzen des Double Speed Mode UCSR0B = 0x18; //Aktiviert den Receiver und Transmitter UCSR0C = 0x26; //Festlegung des Frames: //1 Startbit //8 Datenbits //1 Paritätsbit even //1 Stoppbit UBRR0H = (unsigned char)(baud>>8); //Setzen der Baud Rate -> im //Double Speed Mode UBRR0L = (unsigned char)baud; } /**************************USART-Transmitter*************************/ void usart_transmit (unsigned char data) { while ( !(UCSR0A & (1<< UDRE0)) ); UDR0 = data; } /****************************USART-Receiver**************************/ unsigned char usart_receive ( void ) { while ( !(UCSR0A & (1<<RXC0)) ); buffer = UDR0; return buffer; }
>... allerdings verwirft er den Wert von UDR0 auch gleich wieder.
Das wundert mich nicht. Das ist ja genau das, wozu Du ihn angewiesen
hast.
Schau Dir noch einmal genau Deinen Code an. Welche Schritte werden
ausgeführt?
...
usart_receive();
-->
while ( !(UCSR0A & (1<<RXC0)) );
buffer = UDR0; // hier liest Du also das empfangene
Byte
return buffer; // da koennte man auch noch was zu
sagen
<--- zurück in main
buffer = UDR0; // und was liest Du hier?
Schrott!
Der Fifo hat nämlich schon seinen Zustand geändert.
Siehe Datasheet S. 190
"The receive buffer consists of a two level FIFO. The FIFO will change
its state whenever the
receive buffer is accessed. Due to this behavior of the receive buffer,
do not use Read-Modify-
Write instructions (SBI and CBI) on this location. Be careful when using
bit test instructions
(SBIC and SBIS), since these also will change the state of the FIFO."
Oh Mann. Ja du hast recht. Hab nun den Teil im Hauptprogramm geändert. Er lautet nun: while (1) { usart_receive(); usart_transmit(buffer); _delay_ms(1000); } So müsste es ja eigentlich funktionieren. Allerdings verwirft er den Wert von UDR0 immer noch. So bin ich weiterhin ratlos.
Hm. Das ist seltsam. Dann müssen wir mal von den Deutungen wegkommen. Zunächstmal, was meinst Du mit "er verwirft" den Wert von UDR? Woran siehst Du das? Wie gehst Du genau vor? Immer noch im Debugger? (Das UDR Register wird nicht notwendigerweise korrekt simuiert) Beschreibe möglichst genau was Du tust. Nimm mal Hapsim. Da kannst Du ein Terminal simulieren.
Hier hab ich mal von der Problemstelle zwei Screenshots gemacht. Bild 1 zeigt rechts den Wert UDR0 = 0x40 bei gesetztem RXC0. Die beiden Werte musste ich manuell setzen (bin schließlich im Simulator). Bild 2 zeigt die Register nach dem der Empfangsprozess abgeschlossen wurde. Wie man sieht steht in UDR0 nichts mehr drin. Kein Wunder das ich also auch nichts als eine 0 zurück gesendet bekomme. Frage ist nur warum er das macht. Geschrieben habe ich das Programm um meine Verbindung zwischen zwei XBees zu testen. Der Datenverkehr wird mir dabei über zwei LEDs visualisiert. Das funktioniert auch. Die Led für den Dateneingang leuchtet auf wenn Daten eingehen und die Led für den Datenausgang leuchtet auf wenn Daten ausgehen. Die Hardware scheint also zu funktionieren. Nur der Mikrocontroller löscht (verwirft) den Wert von UDR0 sofort nach dem vollständig empfangen wurde.
Hmm. Also mein letzter Stand ist, "UART/USART The UART/USART UDR register can only be modified from the application. Input via stimuli files or by modifying the I/O view etc is not possible." d.h. das die UART Register garnicht von Hand geändert werden können. Man kann da also im Simulator nichts simulieren. Deswegen auch mein Tip mit dem Hapsim. Aber: Welche Version/Build vom AVRStudio verwendest Du? Ist unter Help zu sehen. Irgendwie scheinst Du das UDR ja geändert zu haben. Wie genau hast Du das gemacht? Bitte Schritt für Schritt erklären.
AVR Studio Version 4.18 Build 684 Das UDR hab durch einfaches anklicken der weissen/schwarzen Kästchen (siehe Bild 1 und Bild 2 rechts) verändern können. Das geht allerdings nur im Running-Modus, also bei laufender Simulation. Den Transmitter habe ich so auch getestet. Das lief einwandfrei. 1. Schritt: auf Build+Run klicken 2. Schritt: Step into solange bis in die Funktion "unsigned char usart_receive ( void )" gesprungen wird. 3. Schritt: Programm bleibt bei "while ( !(UCSR0A & (1<<RXC0)) );" hängen da nichts in UDR0 steht und das RXC0-Bit nicht gesetzt ist. Also setze ich wie oben beschrieben die entsprechenden Bits. -> UDR0=irgendein Wert RXC=1 4. Schritt: Step into 5. Schritt: Jetzt sind man dass UDR0 wider gelöscht worden ist. Bevor es durch die Variable buffer gesichert werden konnte.
Ich habe die selbe Version.
>Das UDR hab durch einfaches anklicken der weissen/schwarzen Kästchen
(siehe Bild 1 und Bild 2 rechts) verändern können. Das geht allerdings
nur im Running-Modus, also bei laufender Simulation.
Aha. Ja, gut. Dann ist das klar. Ich wollte schon nach nem kompletten
Screenshot fragen. Das sind leider bloss alles Fata Morganas. Du kannst
das im Simulator nicht so machen. Das das Kästchen auf eins steht ist
bloss der Tatsache zu verdanken, das die Anzeige nur sporadisch
aufgefrischt wird.
Was immer für ein Problem Du lösen willst: Das geht in Bezug auf den
UART nicht im Simulator.
Ich habe Dir ja schon geraten Hapsim zu verwenden. Mach das mal.
Ich danke Dir für deine Zeit. Ich weiss zwar immer noch nicht was das Problem war. Aber es funktioniert auf einmal.
>Ich weiss zwar immer noch nicht was das >Problem war. Aber es funktioniert auf einmal. Naja. Entweder Du analysierst es jetzt oder es kommt wieder.
Das Problem liegt in der hier völlig unsinnigen globalen Variable "buffer". Ein Paradebeispiel dafür, daß globale Variablen problematisch sind. "buffer" sollte nur lokal in main() deklariert werden, und nochmal lokal in usart_receive. Dazu kommt noch erschwerend der mehrfache Lesezugriff auf das USART-Empfangsregister - der sollte ausschließlich in usart_receive erfolgen und sonst nirgends.
1 | int main(void) |
2 | {
|
3 | unsigned char buffer; |
4 | |
5 | // diverse Initialisierungen ausgelassen
|
6 | usart_init(21); |
7 | |
8 | while (1) |
9 | {
|
10 | buffer = usart_receive(); |
11 | usart_transmit(buffer); |
12 | _delay_ms(1000); |
13 | }
|
14 | }
|
Hier stellt sich noch die Frage, was um alles in der Welt 21 ist. Wo kommt der Wert her?
1 | unsigned char usart_receive(void) |
2 | {
|
3 | while (!(UCSR0A & (1<<RXC0))); |
4 | return UDR0; |
5 | }
|
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.