Forum: Mikrocontroller und Digitale Elektronik Probleme mit USART Recive


von Thomas P. (gonzo)


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

von Thomas P. (gonzo)


Lesenswert?

Ach mist. hier heißt das ja [ C ] und nicht [code] verdammt. aber ich
kann den beitrag nicht mehr bearbeiten. SORRY

von Karl H. (kbuchegg)


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.

von Thomas P. (gonzo)


Lesenswert?

wie kommst du auf 1010? Wenn ich das sende kommt auch nix,

von Karl H. (kbuchegg)


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.

von Karl heinz B. (kbucheg)


Lesenswert?

Wenns dann immer noch nicht geht, dann liegt dein
Problem ganz woanders.
Ich tippe mal auf: Am PC ist Hardware Handshake (RTS/CTS)
aktiviert und der PC hat keine Freigabe zum Senden.

von Thomas P. (gonzo)


Lesenswert?

Cool. So funktioniert es super.

Vielen vielen Dank.

Thomas

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.