Forum: Mikrocontroller und Digitale Elektronik ATtiny2313 über RS232 steuern - Problem mit if/else


von Andreas W. (a-w)


Lesenswert?

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

von h_ (Gast)


Lesenswert?

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
}

von Andreas W. (a-w)


Angehängte Dateien:

Lesenswert?

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
Noch kein Account? Hier anmelden.