Uart rx mittels Interrupt

Gast #4395048
Lesenswert?
• ▲
▼
Hallo,

ich komm nun bei meinem Programm einfach nicht mehr weiter. Das Senden 
von Strings über Uart funktioniert schon mal sehr gut. Nur der Empfang 
bzw. die Reaktion auf Daten die über den Uart kommen funkioniert einfach 
nicht.

Meine Uart-ISR sieht so aus:
1
  ISR(USART_RXC_vect)
2
{
3
static uint8_t uart_rx_cnt;
4
  uint8_t data;
5

6
  data = UDR;
7

8
    if (data=='\n')
9
    {
10
        uart_rx[uart_rx_cnt]=0;
11

12
        uart_rx_cnt=0;
13
  }
14
  else if (uart_rx_cnt<(UART_BUFFER_SIZE-1))
15
  {
16
        uart_rx[uart_rx_cnt]=data;
17
    uart_rx_cnt++;
18
    }}

Im Programmverlauf sende ich dann einen Befehl über Uart, dieser wird 
auch richtig gesendet. Die Reaktion der Gegenstelle darauf ist "OK\n\n".
1
uart_puts("AT\r\n");
2

3
_delay_ms(1000);
4

5
for (i=0; i<(UART_BUFFER_SIZE-1); i++)
6
{
7
    if ((uart_rx[i]=='O') && (uart_rx[i+1]=='K'))
8
    {
9
        ok=1;
10
    }
11
}

Ok wird aber nicht gesetzt, obwohl "OK" über Uart kommt.
Gast #4395103
Lesenswert?
• ▲
▼
Ja Interrupts sind freigegeben. Ein weiterer Interrupt der ausgelöst 
wird wenn an INT0 eine steigende Flanke kommt funktioniert einwandfrei.

Hab gerade mein mal ein PORTD |= (1 << PD3); in die Uart rx routine 
eingefügt... der Ausgang wird nicht gesetzt, also wird der Interrupt 
wohl nicht ausgeführt. Woran kann das liegen?

Der UART-RX ist freigegeben: UCSRB = (1<< RXEN) | (1<<TXEN);
#4395113
Lesenswert?
• ▲
▼
frox schrieb:
> Ja Interrupts sind freigegeben. Ein weiterer Interrupt der ausgelöst
> wird wenn an INT0 eine steigende Flanke kommt funktioniert einwandfrei.
>
> Hab gerade mein mal ein PORTD |= (1 << PD3); in die Uart rx routine
> eingefügt... der Ausgang wird nicht gesetzt, also wird der Interrupt
> wohl nicht ausgeführt. Woran kann das liegen?
>
> Der UART-RX ist freigegeben: UCSRB = (1<< RXEN) | (1<<TXEN);

Damit enablest du die UART (Transmitter und Receiver).
Aber damit ist der Receive Interrupt noch lange nicht freigegeben.
Noch mal ins Datenblatt (oder das von dir benutzte Tutorial) und noch 
mal nachsehen, welche Bits es da noch gibt.
Gast #4395115
Lesenswert?
• ▲
▼
frox schrieb:

> wohl nicht ausgeführt. Woran kann das liegen?
>
> Der UART-RX ist freigegeben: UCSRB = (1<< RXEN) | (1<<TXEN);

Damit läuft zwar die UART-Hardware vollständig, aber davon ist noch kein 
UART-Interrupt freigegeben.

Lies' einfach mal das verdammte Datenblatt!
#4395152
Lesenswert?
• ▲
▼
OK. Damit können wir dann mal die Funktion korrigieren :-)

Normalerweise würde man sich ein Flag setzen, wenn die UART eine 
komplette Zeile beisammen hat. Denn so wie du das abfragst, ist das 
Murks. Du willst nicht den kompletten Buffer durchgehen, ob irgendwo 
(zufällig) ein OK drinnen steht. Das könnte ja auch aus dem Zusammenhang 
gerissen noch von etwas ganz anderem drinnen stehen.
Daher willst du
1) dass dich die UART benachrichtigt, wenn eine (neue)Zeile beisammen 
ist. Das 'OK' von vor einer halben Stunde und einer ganz anderen Anfrage 
gilt nicht mehr.
2) willst du die Buchstabenfolge 'O' und 'K' nur dann akzeptieren, wenn 
sie am Zeilenanfang steht. Eine "DAMPFLOK" gilt nicht.
1
volatile uint8_t uart_haveLine;
2

3
ISR(USART_RXC_vect)
4
{
5
  static uint8_t uart_rx_cnt;
6
  uint8_t data;
7

8
  data = UDR;
9

10
  if (data=='\n')
11
  {
12
    uart_rx[uart_rx_cnt]=0;
13
    uart_rx_cnt=0;
14
    uart_haveLine = TRUE;
15
  }
16
  else if (uart_rx_cnt<(UART_BUFFER_SIZE-1))
17
  {
18
    uart_rx[uart_rx_cnt]=data;
19
    uart_rx_cnt++;
20
  }
21
}

1
  ....
2

3
  uart_puts("AT\r\n");
4

5
  _delay_ms(1000);
6

7
  ok = 0;
8
  if( uart_haveLine && strcmp( uart_rx, "OK" ) == 0 )
9
    ok = 1;
10

11
  uart_haveLine = FALSE;
12

13
  ....

sicherheitshalber sollte man noch alle (möglichen) '\r' ausfiltern. Es 
ist nicht ganz einheitlich, ob ein Gerät sein Zeilenende nur mit einem 
'\n' alleine, oder mit der Kombination '\r\n' markiert.
1
ISR(USART_RXC_vect)
2
{
3
  static uint8_t uart_rx_cnt;
4
  uint8_t data;
5

6
  data = UDR;
7

8
  if (data == '\r' )    // wollen wir nicht haben
9
    return;
10

11
  if (data == '\n')
12
  {
13
    uart_rx[uart_rx_cnt]=0;
14
    uart_rx_cnt=0;
15
    uart_haveLine = TRUE;
16
  }
17
  else if (uart_rx_cnt<(UART_BUFFER_SIZE-1))
18
  {
19
    uart_rx[uart_rx_cnt]=data;
20
    uart_rx_cnt++;
21
  }
22
}

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.