Probleme mit USART Recive

OP #352987
Lesenswert?

Hallo...ich hab ein Problem beim empfangen von daten über USART bei
einem ATmega48. Der Controller läuft auf 4Mhz und Senden geht auch
prima. nur empfängt er nix. Hier meine initialisierung
1
/*Baudrate setzen */
2
  UBRR0H = (unsigned char)(ubrr>>8);
3
  UBRR0L = (unsigned char)(ubrr);
4

5
  /* Sender und Empfaenger anschalten */
6
  UCSR0B = (1<<RXEN0)|(1<<TXEN0);
7
  /* Frame format: 8data, 2stop bits */
8
  UCSR0C = (1<<USBS0)|(3<<UCSZ00);

Und hier der Code zum empfangen:
1
unsigned char USART_Receive( void )
2
{
3
  while ( !(UCSR0A & (1<<RXC0)) );
4
  return UDR0;
5
}

Nur wenn ich dann die hier mache funktioniert es nicht;
1
  DDRB = 0xff;
2
  USART_Init(MYUBRR); /* UART initialisieren */
3
  while(1)
4
  {
5
      if (USART_Receive() == '1')
6
    {
7
      PORTB ^= (0<<PB0);
8
    }
9
    if (USART_Receive() == '0')
10
    {
11
    PORTB ^= (1<<PB0);
12
    }
13
  }

egal ob ich 1 oder 0 zu ttyS1 schicke es passiert nix. Das senden vom
µC zum PC geht jedoch.

Hat Jemand eine Idee woran das liegen könnte?

Thomas
#352989
Lesenswert?

> egal ob ich 1 oder 0 zu ttyS1 schicke es passiert nix

Nicht 'egal ob ich'

So wie das geschrieben ist, erwartet der AtMega48
genau die Sequenz '1' '0' '1' '0'
Genau in dieser Reihenfolge.

Das hier
>      PORTB ^= (0<<PB0);

macht gar nichts. 0 nach links geschoben (egal um
wieviele Positionen) ist immer noch 0. Und ein
Wert ge-xor-t mit 0, ändert nichts am Wert.
#352991
Lesenswert?

> wie kommst du auf 1010?

Weil ich dein Programm analysiert habe !

>  while(1)
>  {
>      if (USART_Receive() == '1')
>    {
>      PORTB ^= (0<<PB0);
>    }
>    if (USART_Receive() == '0')
>    {
>    PORTB ^= (1<<PB0);
>    }
>  }

Angenommen du schickst die Sequenz 0101
USART_Receive wartet jedesmal bis tatsaechlich ein Zeichen
empfangen wird.

  while( 1 )

soweit so gut.
    if( USART_Receive() == '1' )

der USART_Receive empfängt das Zeichen (hier solltest
du unbedingt mal das empfangene Zeichen zu Kontrollzwecken
einfach mal wieder ausgeben. Sowas hilft ungemein bei der
Fehlersuche!). Wie auch immer: '0' ist nicht '1', also
passiert nichts.
Das Programm läuft weiter und kommt in den nächsten if:

    if( USART_Receive() == '0' )
USART_Receive() wartet wieder auf das nächste Zeichen, das ist ein
'1'. '1' ist aber nicht gleich '0', also passiert wieder nichts.
Die while Schleife fängt von vorne an:

    if( USART_Receive() == '1' )
USART_Receive() wartet auf das nächste Zeichen, das ist laut unserer
Eingabe Vereinbarung ein '0'. '0' ist nicht gleich '1', also
passiert nichts.
Weiter gehts:

    if( USART_Receive() == '0' )
Als nächstes kommt wieder ein '1'. -> Nichts passiert
und die while Schleife beginnt wieder von vorne.
Mit der Eingabesequenz: 0101 wird also kein einzige der if-
Bedingungen als true angesehen, weil jedesmal das falsche Zeichen
zum falschen Zeitpunkt daherkommt.

Machs so:

   unsigned char Received;

   while( 1 ) {
     Received = USART_Receive();

     USART_Send( Received );   // ganz wichgtig zur Kontrolle
                               // ob Dein Programm auch wirklich
                               // das empfängt was du glaubst

     if( Received == '0' )
       PORTB &= ~( 1 << PB0 );

     else if( Received == '1' )
       PORTB |= ( 1 << PB0 );
   }

1) USART_Received wird nur noch 1 mal pro Schleifen-Durchlauf
   aufgerufen. Das empfangene Zeichen steht danach allen
   if-Abfragen zur Verfügung

2) Und das ist schon fast die wichtigere Änderung:
   Geh niemals davon aus, dass schon alles stimmen wird.
   Insbesondere: Geh niemals davon aus, dass Input in ein
   Programm auch tatsächlich so ausschaut wie du annimmst.
   Überprüfe es! In dem Fall heist überprüfen, dass man das
   empfangene Zeichen zur Kontrolle auch wieder ausgibt!
   Ganz zum Schluss, wenn alles fertig ist, entfernt man diese
   Kontrollausgaben wieder. Aber solange ein Programmteil in
   der Entwicklung ist, kannst du niemals genug Kontrollen
   im Programm haben.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren