Hallo, ich möchte ein Programm für den ATtiny2313 schreiben, damit dieser unterschiedliche Ports schaltet, abhängig von den Zeichen die er per RS232 vom PC bekommt. Das empfangen der Daten funktioniert soweit. Der Controller bekommt immer nur ein Byte geschickt. #include <avr/io.h> #ifndef F_CPU #define F_CPU 1000000UL //1MHZ kann eigentlich 8 Mhz aber CKDIV8 ist noch gesetzt #endif #include <util/delay.h> #include <avr/interrupt.h> void InitUART(void); unsigned char ReceiveByte(void); int main (void) { DDRD |= (1<<PORTD4) | (1<<PORTD5) | (1<<PORTD6);// LED 1,2,3 als Ausgang InitUART(); while(1) { if(ReceiveByte() == 0b00000101) //Senden mit 300 Baud nötig (300,N,8,1) { PORTD = PIND^(1<<PORTD4); //Zustand LED 1 wechseln } if(ReceiveByte() == 0b01100010) { PORTD = PIND^(1<<PORTD5); //Zustand LED 2 wechseln } else { PORTD |= (1<<PORTD6); // Blinken LED 3 wenn sonstiges empfangen wird _delay_ms(20); PORTD &= ~(1<<PORTD6); _delay_ms(20); PORTD |= (1<<PORTD6); _delay_ms(20); PORTD &= ~(1<<PORTD6); _delay_ms(20); PORTD |= (1<<PORTD6); _delay_ms(20); PORTD &= ~(1<<PORTD6); } } } void InitUART(void) { UBRRL = 0b11001111; UBRRH = 0b00000000; UCSRB = (1 << RXEN) | (1 << TXEN); UCSRC = (1 << UCSZ1) | (1 << UCSZ0); } unsigned char ReceiveByte(void) { while (!(UCSRA & (1 << RXC))); return UDR; } Mit der if/else Anweisung wollte ich die empfangenen Zeichen zum Schalten der Ausgänge selektieren. (Im Code den Wert 5 um LED1 zu schalten und 98 für LED2.) Wenn ich jetzt das Signal sende um LED 1 zu Schalten, wechselt diese auch den Zustand. Sende ich den Befehl erneut, wird dieser jedoch als else-Fall erkannt (LED3). Beim dritten Senden des Befehls wechselt die LED1 wieder den Zustand. Beim vierten Senden wird es wieder ein else-Fall. Gleiches passiert bei LED2. Sende ich die Befehle für LED1 und 2 abwechselnd klappt dies. Sprich LED1 an - LED2 an - LED1 aus -LED2 aus -... (an aus versetzt funktioniert auch) Schicke ich nach dem Reset des Controllers den Befehl für LED1, wechselt diese und macht dann Probleme. Sende ich nach dem Reset den Befehl für LED2, wird dies gleich als else-Fall bewertet. Erst ein erneutes Senden des Befehls wechselt den Zustand von LED2. Als die Anweisung nur aus einem if und einem else bestand funktionierte alles problemlos. Mit dem Einfügen des zweiten if kam das Problem. Auch nachdem ich mich durch einige Foreneinträge zu if/else und switch/case gearbeitet habe, weis ich nicht wo der Fehler liegt. Was habe ich übersehen? Vielen Dank Andreas
Zumindest ein Fehler liegt darin, dass du für jedes if ReceiveByte() erneut aufrufst. Du läufst also in das erste if hinein und wartest dort auf ein Byte. Ist das Byte 5, wird die LED 1 geschalten. Dann läufst du in das zweite if hinein und wartest wieder. Da das Byte nicht den Wert 0x62 hat, wird der else-Zweig ausgeführt. Du möchtest aber ein Byte lesen, und dann sehen welcher Fall passt:
1 | unsigned char c; |
2 | while(1) |
3 | { |
4 | c = ReceiveByte(); |
5 | if(c == ...) |
6 | ... |
7 | if(c == ...) |
8 | ... |
9 | } |
Oder etwas schöner (wie ich finde) mit switch:
1 | while(1) |
2 | { |
3 | switch(ReceiveByte()) { |
4 | case 0x5: |
5 | ... |
6 | break; |
7 | case 0x62: |
8 | ... |
9 | break; |
10 | default: |
11 | ... |
12 | } |
13 | } |
Stimmt natürlich. Ich habe ReceiveByte()als Variable behandelt. Aber mit ReceiveByte() rufe ich jedes mal das Unterprogramm auf, dass dann auf ein Zeichen wartet. Sowohl mit if/else als auch mit switch funktioniert es jetzt. Danke für den Hinweis. Anbei der funktionierende Quelltext für Interessenten.
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.