Forum: Mikrocontroller und Digitale Elektronik STM32F4xx USART RX Interrupt


von Arrtata (Gast)


Lesenswert?

Ich habe folgende Situation. Mit USART2 steuere ich einen 
Motor-Controller an. Es wird ein Befehl gesendet und von der Motor 
Steuerung quittiert. In den Funktionen warte ich zum Teil darauf, bis 
bestimmte Positionen angefahren wurden. Dazu sende ich auch Anfragen an 
die Motor-Steuerung und werte die Rückantwort aus. Soweit so gut, es 
funktioniert alles, wenn ich die Befehle vor der Main-Schleife 
ausprobiere. Sobald ich aber die Steuerbefehle für die Motorsteuerung 
über PC Kommunikation auszulösen (FTDI an USART1), wird über USART2 zwar 
gesendet, aber kein RX Interrupt an USART 2 ausgelöst. USART1 Interrupt 
ist auch aktiv. Das Gleiche passiert, wenn ich über Systick Interrupt 
Befehle an die Motorsteuerung verschicken möchte. Jedes Mal ist USART2 
RX Interrupt deaktiviert, sobald andere Interrupts aktiv sind. Ist es 
normal und wie kann ich das umgehen? Ich habe mal Statusregister 
ausgeben lassen, wenn Daten wie gewünscht Empfangen werden, steht im im 
USART2->SR Register 0xD0, ansonsten steht da eine 0xF8. Kann das jemand 
entziffern?

von Dr. Sommer (Gast)


Lesenswert?

Arrtata schrieb:
> Ist es
> normal
Nein.

Arrtata schrieb:
> Kann das jemand
> entziffern?
Ja. Das Datenblatt.

Vielleicht blockierst du ja irgendwie die Interrupts versehentlich. Ohne 
Code zu zeigen ist das alles nur raten.

von Arrtata (Gast)


Lesenswert?

Also Befehle vom PC kommen über USART1 rein mit 115200 Baud über einen 
FTDI. Die ISR sieht so aus:
1
void
2
USART1_IRQHandler (void) {
3
4
  // USART TX handling --------------------------------------------------
5
  if (USART_GetITStatus(USART1, USART_IT_TXE) == SET) {
6
7
  }
8
9
  // USART RX handling --------------------------------------------------
10
  if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET) {
11
12
    CommandInBuf[InBufCnt] = USART_ReceiveData (USART1);
13
     USART_ClearITPendingBit(USART1, USART_IT_RXNE);
14
     USART_ClearITPendingBit(USART1, USART_IT_TXE);
15
    if ((CommandInBuf[InBufCnt] == '\n') || (CommandInBuf[InBufCnt] == '\0') || (InBufCnt >= (BUFSIZE - 1))) {
16
      CommandInBuf[InBufCnt] = '\0';
17
18
      //ParseCMD();
19
      CommandReceivedFlag = 1;
20
21
      InBufCnt = 0;
22
      GPIO_ToggleBits(LED_GPIO_PORT, LED4_PIN);
23
24
    }
25
    else {
26
      InBufCnt++;
27
    }
28
  }
29
}

Bei USART2 ist ebenfalls RX Interrupt aktiviert. Wenn in der UART1 die 
Funktion ParseCMD(); aufgerufen wird, werden hier Befehle an die 
Motorsteuerung über USART2 gesendet und auf Quittierungen gewartet 
(USART2 IR aktiv). Und genau hier funktioniert es nicht. USART2 sendet 
zwar, aber Emfangsinterrupt ist nicht aktiv, obwohl die Daten über die 
Leitung laufen. Ich vermute, wenn man in einer ISR ist, werden andere 
Interrupts ignoriert, obwohl USART2 höhere Priorität hat. Ich habe es 
jetzt folgendermaßen gelöst, ein Flag CommandReceivedFlag wird gesetzt 
und in der Mainschleife abgefragt, und somit ParseCMD() ausgelöst. So 
geht es wunderbar. Mich würde aber trotzdem interessieren, wie man auf 
Interrupts in einer anderen ISR reagieren kann, ohne dass diese 
blockiert werden.

von Dr. Sommer (Gast)


Lesenswert?

Arrtata schrieb:
> werden hier Befehle an die
> Motorsteuerung über USART2 gesendet und auf Quittierungen gewartet
> (USART2 IR aktiv). Und genau hier funktioniert es nicht.
Ja DAS ist klar! Wahrscheinlich haben dein USART1 und USART2 Interrupt 
die selbe Preemption priority, und daher unterbricht der USART2 RX 
Interrupt den laufenden USART1 Interrupt nicht. Die Priorität kannst 
du ändern beim Parameter an den NVIC_Init aufruf. Das ist aber keine so 
gute Idee, denn was ist wenn eine USART1 Interrupt kommt während der 
USART2 Interrupt am warten ist - der wird dann ignoriert.

Arrtata schrieb:
> ein Flag CommandReceivedFlag wird gesetzt
> und in der Mainschleife abgefragt, und somit ParseCMD() ausgelöst.
Ja, das ist die viel bessere Lösung. Wenn man mehrere Dinge hat die 
gleichzeitig laufen sollen (bei dir: USART1 und USART2 behandlung) 
sollte man nicht in einem Interrupt auf etwas warten, weil dann der 
zweite Interrupt nicht kommen kann.

Arrtata schrieb:
> Mich würde aber trotzdem interessieren, wie man auf
> Interrupts in einer anderen ISR reagieren kann, ohne dass diese
> blockiert werden.
Eben durch Verstellen der Priorität. Aber das ist dann asymmetrisch und 
funktioniert nur in die eine Richtung.

von Arrtata (Gast)


Lesenswert?

USART2 hat aber höhere Priorität und trotzdem ist kein USART2 Empfang in 
der USART1 ISR möglich.

von Dr. Sommer (Gast)


Lesenswert?

Arrtata schrieb:
> USART2 hat aber höhere Priorität und trotzdem ist kein USART2
> Empfang in
> der USART1 ISR möglich.
Das kann nicht sein. Dann hast du was falsch gemacht.

von Kaj (Gast)


Lesenswert?

Arrtata schrieb:
> USART2 hat aber höhere Priorität
Und das machst du wodran genau fest?

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.