Forum: Mikrocontroller und Digitale Elektronik Atmega128L + SIG_UART0_RECV


von Tanja H. (hoefme)


Lesenswert?

HAllo zusammen,

Zwar habe ich eine Frage Betreff der RS232. Habe ein problem mit dem 
Empfangen von Daten. Senden an den PC kann ich zeichen via rs232, jedoch 
empfangen über rs232 geht irgenwie nicht. Zwar funtioniert nicht mal der 
Interrupt richtig, dehalb vermute ich da das problem. Hat jemand eine 
idee was ich in der Initalisierung oder sonst vergessen habe?

Mein Code:

#include <avr/interrupt.h>
void  init_RS232(void);


//Interrupt für RX von USART
SIGNAL (SIG_UART0_RECV)
{
    //Daten empfangen, aufruf für LED um zu togglen.

    Leds.led2Toggle();
}



//Main Programm
int main(void)
{
     /* Set baud rate */
   UBRR0H = (unsigned char)(ubrr>>8);
   UBRR0L = (unsigned char)ubrr;
   /* Enable receiver and transmitter */
   UCSR0B = (1<<RXEN)|(1<<TXEN);
   /* Set frame format: 8data, 2stop bit */
   UCSR0C = (1<<USBS)|(3<<UCSZ0);

   sei();
   // test
   WriteChar('s')

  return 0;
}


//Write Data over RS232
void WriteChar(unsigned char c)
{
    while(!(UCSR0A & (1 << UDRE0)))
    ;   /* warte, bis UDR bereit */

    UDR0 = c;    /* sende Zeichen */
}


/*void ReceiveData( void )
{

  while(! (UCSR0A & (1<<RXC)));
  rx_ = UDR0;


}
*/




Besten dank für eure Hilfe.

lg

von Johannes M. (johnny-m)


Lesenswert?

Du musst das UDR im Interrupt Handler lesen, sonst wird das Flag nicht 
gelöscht und der Interrupt immer wieder ausgelöst!

Abgesehen davon sind SIGNAL und die Vektornamen à la SIG_XXXX veraltet 
und sollten nicht mehr verwendet werden...

von pschober (Gast)


Lesenswert?

Der Interrupt muss noch auf enable gesetzt werden.

UCSR0B = (1<<RXEN)|(1<<TXEN)|(1 << RXCIE);

von pschober (Gast)


Lesenswert?

Und in der main Funktion fehlt noch eine Endlosschleife.

//Main Programm
int main(void)
{
     /* Set baud rate */
   UBRR0H = (unsigned char)(ubrr>>8);
   UBRR0L = (unsigned char)ubrr;
   /* Enable receiver and transmitter */
   UCSR0B = (1<<RXEN)|(1<<TXEN);
   /* Set frame format: 8data, 2stop bit */
   UCSR0C = (1<<USBS)|(3<<UCSZ0);

   sei();
   // test
   WriteChar('s')

  while(1);
  return 0;
}

von Johannes M. (johnny-m)


Lesenswert?

Und was soll der Blödsinn mit Interrupt und Polling gleichzeitig? Du 
musst Dich schon entscheiden, ob Du einen Interrupt auslösen oder das 
Flag in einer Schleife abfragen willst! Beides gleichzeitig geht nicht.

von Klaus (Gast)


Lesenswert?

Wenn du uns jetzt auch noch verraten würdest, wo du eine Schleife siehst 
in der was empfangen wird? Ansonsten war nämlich leider dein Post 
Blödsinn.

von Tanja H. (hoefme)


Lesenswert?

Okay habe gsehen das der Interrupt doch aufgerufen wird. Um jedoch die 
Daten zu speichern ist so zu machen:


  SIGNAL(SIG_UART0_RECV) {
       while(! (UCSR0A & (1<<RXC)));
       rx_ = UDR0;
  }


Gruss

von Klaus (Gast)


Lesenswert?

Dabei besteht allerdings die Gefahr, dass du beim Empfang mehrerer 
Zeichen die Daten in rx_ überschreibst bevor du sie im Hauptprogramm 
verarbeitet hast. Je nach dem was du eigentlich vorhast, kann es 
sinnvoller sein, das lesen direkt im Hauptprogramm ohne Interrupt zu 
machen. Dann hast du nämlich die Möglichkeit anhand des Flags DOR (data 
over run) zu überprüfen, ob ein Zeichen verloren gegangen ist.

Wenn du es optimal lösen willst, dann solltest du in der Interrupt 
Routine fürs Empfangen die Daten in einen FIFO Puffer schreiben. Dabei 
solltest du dann Prüfen, ob der Puffer voll ist, und wenn ja selber eine 
globale Variable  als Buffer Overrun Flag setzen.

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.