Forum: Mikrocontroller und Digitale Elektronik STM32 mehrere UART Interrupts


von Sudo (Gast)


Lesenswert?

Hallo,

ich habe auf meinem STM32L4R5ZI-Nucleo Board 6 UARTs laufen, alle 
half-duplex (Single wire) und mit Interrupts. Gesteuert werden 
Motortreiberbausteine, hauptsächlich geht es um das fortlaufende 
Auslesen der Motorlast im Hintergrund. Nach jedem Sende- und 
Empfangsvorgang wird dann der Parameter in der Callback-Routine geprüft 
und wenn ein Wert überstiegen wird z.B. der Motor angehalten:


1. Sender aktivieren und UART-Interrupt Prozesse starten:
1
        HAL_HalfDuplex_EnableTransmitter(&huart1);
2
  HAL_UART_Transmit(&huart1, data8_ptr, 8, 10);
3
  HAL_HalfDuplex_EnableTransmitter(&huart2);
4
  HAL_UART_Transmit(&huart2, data8_ptr, 8, 10);
5
  HAL_HalfDuplex_EnableTransmitter(&huart3);
6
  HAL_UART_Transmit(&huart3, data8_ptr, 8, 10);
7
  HAL_HalfDuplex_EnableTransmitter(&huart4);
8
  HAL_UART_Transmit(&huart4, data8_ptr, 8, 10);
9
  HAL_HalfDuplex_EnableTransmitter(&huart5);
10
  HAL_UART_Transmit(&huart5, data8_ptr, 8, 10);
11
  HAL_HalfDuplex_EnableTransmitter(&hlpuart1);
12
  HAL_UART_Transmit(&hlpuart1, data8_ptr, 8, 10);

2. Die Callback Funktionen sorgen dann abwechselnd immer selbst dafür, 
dass Daten gesendet und empfangen werden und zwar halt immer für den 
Kanal, der den Interrupt auslöst:
1
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
2
3
    HAL_HalfDuplex_EnableReceiver(huart);
4
    HAL_UART_Receive_IT(huart,indata_ptr,8);
5
6
}
7
8
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
9
10
  if (indata[2] == 65) { // hier passiert dann der Ableich ..... }
11
12
  HAL_HalfDuplex_EnableTransmitter(huart);
13
  HAL_UART_Transmit_IT(huart, data_ptr, sendlength); // Sendeschleife
14
15
}

Leider funktioniert das nur mit einem Kanal. Ich habe das auch so 
ausprobiert, dass die RxCpltCallback-Funktion die Kanäle nacheinander 
ansteuert (also z.B. if huart->INSTANCE==huart1 {huartnext=huart2} dann 
beim  HAL_UART_Transmit_IT(huartnext, data_ptr, sendlength)) aber das 
geht auch nicht.

Habt ihr einen Tipp für mich, wie ich das hinbekomme?

Vielen DANK im Voraus

von Sudo (Gast)


Lesenswert?

SORRY falscher Code bei 1. RICHTIG bitte wie folgt:
1
  HAL_HalfDuplex_EnableTransmitter(&huart1);
2
  HAL_UART_Transmit_IT(&huart1, data_ptr, 4);
3
  HAL_HalfDuplex_EnableTransmitter(&huart2);
4
  HAL_UART_Transmit_IT(&huart2, data_ptr, 4);
5
  HAL_HalfDuplex_EnableTransmitter(&huart3);
6
  HAL_UART_Transmit_IT(&huart3, data_ptr, 4);*/
7
  HAL_HalfDuplex_EnableTransmitter(&huart4);
8
  HAL_UART_Transmit_IT(&huart4, data_ptr, 4);
9
  HAL_HalfDuplex_EnableTransmitter(&huart5);
10
  HAL_UART_Transmit_IT(&huart5, data_ptr, 4);
11
  HAL_HalfDuplex_EnableTransmitter(&hlpuart1);
12
  HAL_UART_Transmit_IT(&hlpuart1, data_ptr, 4);

von Harry L. (mysth)


Lesenswert?

1
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
2
  if (huart == &huart1)
3
    {
4
      // Code für UART1
5
    }
6
7
  if (huart == &huart2)
8
    {
9
      // Code für UART2
10
    }
11
    
12
  // usw.
13
}

von Sudo (Gast)


Lesenswert?

@Harry: genauso gehe ich schon bei der Auswertung vor, das ist mir nicht 
neu, aber danke trotzdem

Irgendwie blockieren sich die Interrupts gegenseitig, kann das sein?

von Kevin M. (arduinolover)


Lesenswert?

Sudo schrieb:
> Irgendwie blockieren sich die Interrupts gegenseitig, kann das sein?

Haben die denn auch unterschiedliche Prioritäten?

von Sudo (Gast)


Lesenswert?

Nein alle dieselbe Priorität, 500k Baudrate. Im Hintergrund laufen auch 
noch 6 Timer mit Interrupts

von Kevin M. (arduinolover)


Lesenswert?

Sudo schrieb:
> Nein alle dieselbe Priorität

Schlechte Idee...
Würde mich nicht wundern wenn dein Interrupts sich gegenseitig 
abschießen.

von Sudo (Gast)


Lesenswert?

Sollte theoretisch aber keinen Unterschied machen wenn alle dieselbe 
Prio haben, oder was meinst du da konkret?

von Kevin M. (arduinolover)


Lesenswert?

Denkst mal scharf nach was passiert wenn du 6 oder noch mehr Interrupts 
hast die gleichzeitig auftreten können und dann die selbe Priorität 
haben. Besonders toll wird es wenn deine ISR länger zum Ausführen 
braucht als die Abstände zwischen dem Interrupt.

Der STM hat den NVIC nicht ohne Grund benutz ihn doch einfach.

von Sudo (Gast)


Lesenswert?

Da muss ich mir wohl das ganze nochmal genau ansehen, danke für den Tipp

von Harry L. (mysth)


Lesenswert?

Zeitverschwendung!
Das muß auch funktionieren, wenn alle Ports die selbe 
Interrupt-Priorität haben.

von m.n. (Gast)


Lesenswert?

Kevin M. schrieb:
> Denkst mal scharf nach was passiert wenn du 6 oder noch mehr Interrupts
> hast die gleichzeitig auftreten können und dann die selbe Priorität
> haben. Besonders toll wird es wenn deine ISR länger zum Ausführen
> braucht als die Abstände zwischen dem Interrupt.
>
> Der STM hat den NVIC nicht ohne Grund benutz ihn doch einfach.

Du willst eine Kuh auf's Eis ziehen?
Der NVIC verschafft keine zusätzliche Rechenzeit. Bei gleicher Priorität 
werden die Interrupts nacheinander abgearbeitet. Der STM32L4 ist viel zu 
schnell, als daß man ihn mit ein paar UARTs groß in die Knie zwingen 
könnte.

Sudo schrieb:
> Habt ihr einen Tipp für mich, wie ich das hinbekomme?

Reduziere Deine UARTs erst einmal auf zwei und finde heraus, wo es 
klemmt.

von Kevin M. (arduinolover)


Lesenswert?

Zwischen "Funktionieren" und sinnvoll sein und sinnvoll zu funktionieren 
gibt es einen großen Unterschied.

von Kevin M. (arduinolover)


Lesenswert?

m.n. schrieb:
> Du willst eine Kuh auf's Eis ziehen?

Nein Kühe gehören auf die Weide.

m.n. schrieb:
> Der NVIC verschafft keine zusätzliche Rechenzeit.

Das habe ich mit keinem Stück behauptet.

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.