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.