Forum: Mikrocontroller und Digitale Elektronik Uart rx mittels Interrupt


von frox (Gast)


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.

von Karl H. (kbuchegg)


Lesenswert?

Der Empfangs Interrupt ist freigegeben?
Die Interrupts sind global freigegeben?

Hast du schon kontrolliert, ob die ISR überhaupt betreten wird?

von frox (Gast)


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);

von Karl H. (kbuchegg)


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.

von c-hater (Gast)


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!

von frox (Gast)


Lesenswert?

Sehr gut!
Besten Dank! Musste noch das RXCIE Bit setzten, jetzt läufts. ;)

von Karl H. (kbuchegg)


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
}

von frox (Gast)


Lesenswert?

Hab, die Funktion angepasst und noch ein paar andere Fehler 
ausgebessert.

Vielen Dank für deine Hilfe, jetzt scheint alles zu laufen.

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.