stm32f411 USART2 will nicht wie er soll

#7789656
Lesenswert?

1
extern volatile uint8_t rx_buff[];
2
extern volatile uint8_t rx_buff_ct;
3
void USART2_IRQHandler_kk(void)
4
{
5
  rx_buff[rx_buff_ct++]=USART2->DR;
6
  USART2->CR1 &= ~USART_CR1_RE;
7
  USART2->CR1 |= USART_CR1_RE;//
8
  //_delay_us(15);
9

10
if(rx_buff_ct==7)
11
{
12
  rx_buff_ct=0;
13
  lcd_goto(15,1);//
14
  lcd_int2(rx_buff[0]);//
15
lcd_write(" ");
16
lcd_int2(rx_buff[1]);//
17
lcd_write(" ");
18
lcd_int2(rx_buff[2]);//
19
lcd_write(" ");
20
lcd_int2(rx_buff[3]);//
21
lcd_write(" ");
22
lcd_int2(rx_buff[4]);//
23
lcd_write(" ");
24
lcd_int2(rx_buff[5]);//
25
lcd_write(" ");
26
lcd_int2(rx_buff[6]);//
27
lcd_write(" ");
28
}

Es sollen immer sieben Zeichen gesendet werden. Das erste Byte wird per isr angesprungen und richtig in den buffer geschrieben. Danach wird die isr nicht mehr ausgeführt. Im Debugger - langsam - funktioniert es alle 7 bytes durch (natürlich nicht mit einer Sendefolge).

Was mache ich falsch?

Gast #7789661
Lesenswert?

Karl K. schrieb:

Was mache ich falsch?

Warum schaltest du innerhalb der ISR den Receiver aus und wieder ein?

Du hast zu viel Arbeit in die ISR gepackt. So verpasst du während der Ausgabe due nächsten Bytes. Die ISR sollte die empfangenen Daten nur in den Puffer schreiben. Deren Verarbeitung gehört außerhalb von ISR in die main loop.

#7789704
Lesenswert?

Sherlock 🕵🏽‍♂️ schrieb:

Warum schaltest du innerhalb der ISR den Receiver aus und wieder ein?

Beitrag "Re: STM32F4xx UART-State während des Empfangs zurücksetzen"

Sherlock 🕵🏽‍♂️ schrieb:

Du hast zu viel Arbeit in die ISR gepackt.

Wenn das 7.byte empfangen ist ist das Empfangen beendet und die isr wird nicht mehr gebraucht. Zwecks Fehlersuche habe ich da die tft-Ausgabe eingebaut. fliegt wieder raus wenn das ganze funktionieren sollte. In meiner ISR sind 4 Takte - das ist sehr viel kürzer als das hal-Gedöns.

Der code scheint prinzipiell auch zu funktionieren. Wenn ich mit dem avr sende, werden Zeichen - zum Teil richtig - angezeigt. Vielleicht ist das Ganze nur ein Timing-Problem.

Kann mir jemand verraten, wo man bei Cube die Usart-Baudrate einstellt? Habe das im ioc nicht gefunden. Hal generiert

1
  huart2.Instance = USART2;
2
  huart2.Init.BaudRate = 115200;
3
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
4
  huart2.Init.StopBits = UART_STOPBITS_1;
5
  huart2.Init.Parity = UART_PARITY_NONE;
6
  huart2.Init.Mode = UART_MODE_TX_RX;
7
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
8
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
9
  if (HAL_UART_Init(&huart2) != HAL_OK)
10
  {
11
    Error_Handler();
12
  }
13

14
 /* USER CODE BEGIN USART2_Init 2 */
15
   huart2.Instance = USART2;
16
    huart2.Init.BaudRate = 9600;
17
    huart2.Init.WordLength = UART_WORDLENGTH_8B;
18
    huart2.Init.StopBits = UART_STOPBITS_1;
19
    huart2.Init.Parity = UART_PARITY_NONE;
20
    huart2.Init.Mode = UART_MODE_TX_RX;
21
    huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
22
    huart2.Init.OverSampling = UART_OVERSAMPLING_16;
23
    if (HAL_UART_Init(&huart2) != HAL_OK)
24
    {
25
      Error_Handler();
26
    }
27
  /* USER CODE END USART2_Init 2 */

kann es ja irgendwie nicht sein?

#7789782
Lesenswert?

Matthias S. schrieb:

Wenn du zweimal hintereinander USART2 initialisierst, solltest du dazwischen ein De_Init auslösen.

Ist beim U(S)ART mit HAL tatsächlich nicht erforderlich. Ein "beherztes Init" reicht in diesem Fall aus.

Allerdings sollte das die Ausnahme sein.

Im Normalfall stellt man die Parameter einmal im CubeMX ein, und kümmert sich nicht weiter darum.

Die Geschwindigkeit oder das Frame-Format im laufenden Betrieb zu wechseln, dürfte ein eher exotisches Scenario sein...ist aber auch kein Hexenwerk.

#7789859
Lesenswert?

2 x 0xff vom PC gesendet. Das Osci erkennt 0x1f.

Zeit zwischen Zwei steigenden Flanken 1,14ms. Müsste sein 1sec/9600/(1+8+1)=1,0416ms.

Ich werde jetzt mal versuchen, die Zeit zwischen zwei Interrupts des stm zu messen.

ist

1
  rx_buff[rx_buff_ct++]=USART2->DR;
2
  USART2->CR1 &= ~USART_CR1_RE;
3
  USART2->CR1 |= USART_CR1_RE;//

für Abholen des Bytes und Rücksetzen auf Lesezustand ausreichend und richtig?

Angehängte Dateien:
Gast #7789909
Lesenswert?

Du resettest den Receiver nach jedem einzelnen Byte während er das nächste Byte empfängt. Du verpasst bzw. verwirfst also jedes zweite Byte.

Was du vermutlich machen wolltest:

Erst NACH dem Empfang des siebten Bytes den Receiver disablen, dann dir 7 Bytes verarbeiten/anzeigen, und DANACH den Receiver wieder enablen.

#7790036
Lesenswert?

Sherlock 🕵🏽‍♂️ schrieb:

Du resettest den Receiver nach jedem einzelnen Byte während er das nächste Byte empfängt. Du verpasst bzw. verwirfst also jedes zweite Byte.

Ist das so? RXNE wir ausgelöst zum Zeitpunkt "Anfang bis Mitte Stoppbit". Es ist dann zumindest Zeit bis zum nächsten Startbit.

Ich habe leider vergeblich versucht herauszufinden, welche Register-Bits in den HAL-UART-Routinen gesetzt und geschrieben werden.

Allein das Lesen von USART2->DR führt jedenfalls nicht dazu, dass DR für das Lesen des nächsten Bytes freigegeben wird.

Gast #7790047
Lesenswert?

Karl K. schrieb:

RXNE wir ausgelöst zum Zeitpunkt "Anfang bis Mitte Stoppbit". Es ist dann zumindest Zeit bis zum nächsten Startbit.

Ich habe auf die Schnelle keine Info gefunden, wie schnell der Receiver nach dem enablen empfangsbereit wird. Vielleicht dauert das länger, als bis zum Beginn des nächsten Start-Bit. Kannst du das Timing deines Test-Senders ändern, um dieses Deal zu erforschen?

Karl K. schrieb:

Allein das Lesen von USART2->DR führt jedenfalls nicht dazu, dass DR für das Lesen des nächsten Bytes freigegeben wird.

Beim F1, F3 und L0 ist das aber ganz sicher so.

Und im Referenzhandbuch vom F4 steht: "In single buffer mode, clearing the RXNE bit is performed by a software read to the USART_DR register. "

https://www.st.com/resource/en/reference_manual/rm0383-stm32f411xce-advanced-armbased-32bit-mcus-stmicroelectronics.pdf

Gast #7790065
Lesenswert?

Karl K. schrieb:

Ich habe leider vergeblich versucht herauszufinden, welche Register-Bits in den HAL-UART-Routinen gesetzt und geschrieben werden.

Der HAL Code ist wirklich scheer zu durchschauen, vor allem für Anfänger.

Ich denke, das ist ST durchaus bewusst. Für die F0 und L0 Modelle stellt die Firma immer noch reichlich Code-Beispiele mit direkten Register-Zugriffen bereit. Ich denke, diese Serien eignen sich besser, um sich mit STM32 vertraut zu machen.

#7790072
Lesenswert?

Karl K. schrieb:

Was mache ich falsch?

Eigentlich alles. In der ISR schreibt man die Bytes nur in einen Puffer und mehr nicht. Das aber auch erst, wenn das Statusregister den Empfang anzeigt. Diese Abfrage fehlt.

Harry L. schrieb:

Im Normalfall stellt man die Parameter einmal im CubeMX ein, und kümmert sich nicht weiter darum.

Im 'Normalfall' braucht man CubeMX dafür garnicht ;-)

Gast #7790076
Lesenswert?

Mi N. schrieb:

Im 'Normalfall' braucht man CubeMX dafür garnicht

Spätestens wenn der federführende Student wo anders einen besseren Job gefunden hat kommt das nächste inkompatible Framework. Mein Bauch sagt mir, dass es bald wieder so weit sein wird.

#7790151
Lesenswert?

Mi N. schrieb:

Eigentlich alles. In der ISR schreibt man die Bytes nur in einen Puffer und mehr nicht. Das aber auch erst, wenn das Statusregister den Empfang anzeigt. Diese Abfrage fehlt.

Sorry - wenn im Statusregister der Empfang angezeigt wird wird der Interrupt ausgelöst. Was soll ich da in der zugehörigen isr noch abfragen ob der Empfang erfolgt ist?

In der ISR schreibt man die Bytes nur in einen Puffer und mehr nicht. Das macht ja wohl rx_buff[rx_buff_ct++]=USART2->DR;

nur dann hört es mit dem Empfangen auf. Das Problem wurde hier

Beitrag "Re: STM32F4xx UART-State während des Empfangs zurücksetzen"

diskutiert und mit USART2->CR1 &= ~USART_CR1_RE; USART2->CR1 |= USART_CR1_RE;// gelöst.

Mehr hab ich bei den ersten bytes nicht drin und kürzer ist kaum denkbar. Vergleich das mal mit den Hal-Usart-Abfragen. Es hat ja auch ein paar mal funktioniert.

Das Problem ist m.E. das Timing des Senders. Das haut die STM-Fehlerabfragen zu und dann geht rx halt nicht mehr.

Harry L. schrieb:

Deine Versuche, HAL und direkte Registerzugriffe zu mischen ist einfach eine ganz schlechte Idee (so lange man nicht wirklich versteht, was man tut), und zudem vollkommen unnötig!

Ich versuche, das ohne Hal registernah zu programmieren. Dafür müsste ich nur wissen, wie man den Empfang nach auslesen von DR wieder freigibt.

Sherlock 🕵🏽‍♂️ schrieb:

Und im Referenzhandbuch vom F4 steht: "In single buffer mode, clearing the RXNE bit is performed by a software read to the USART_DR register. "

Das Löschen des RXNE funktioniert auch - nur das DR-Register wird nicht geleert oder freigegeben.

#7790154
Lesenswert?

Sherlock 🕵🏽‍♂️ schrieb:

Karl K. schrieb:

Ich habe leider vergeblich versucht herauszufinden, welche Register-Bits in den HAL-UART-Routinen gesetzt und geschrieben werden.

Der HAL Code ist wirklich scheer zu durchschauen, vor allem für Anfänger. Ich denke, das ist ST durchaus bewusst. Für die F0 und L0 Modelle stellt die Firma immer noch reichlich Code-Beispiele mit direkten Register-Zugriffen bereit. Ich denke, diese Serien eignen sich besser, um sich mit STM32 vertraut zu machen.

Gast #7790207
Lesenswert?

Karl K. schrieb:

In der ISR schreibt man die Bytes nur in einen Puffer und mehr nicht. Das macht ja wohl rx_buff[rx_buff_ct++]=USART2->DR;

ja

nur dann hört es mit dem Empfangen auf.

OK, verstanden. Hast du inzwischen meinen Korrekturvorschlag ausprobiert?

Das Problem wurde hier Beitrag "Re: STM32F4xx UART-State während des Empfangs zurücksetzen" diskutiert und mit USART2->CR1 &= ~USART_CR1_RE; USART2->CR1 |= USART_CR1_RE; gelöst.

Nein, da ging es um ein ganz anderes Problem. Dort sollte der Mikrocontroller nach einem einem Framing Fehler "den nächsten Low-Pegel wieder als Startbit (und nicht als x-tes Datenbit) erkennen".

Bei dir geht es nicht um Framing Fehler, und vermutlich um ein engeres Timing.

#7790233
Lesenswert?

Karl K. schrieb:

Sorry - wenn im Statusregister der Empfang angezeigt wird wird der Interrupt ausgelöst. Was soll ich da in der zugehörigen isr noch abfragen ob der Empfang erfolgt ist?

Sorry, du hast noch sehr wenig Ahnung .... Wenn ein Interrupt ausgelöst wird ist das ein Signal dass sich etwas im Status verändert hat, und das ist nun mal nicht nur das Received-Bit welches sich ändern kann.

Sorgfältigerweise muss man noch abfragen ob das richtige Bit gesetzt ist (hier RXNE) sonst greift man evtl. ins Leere.

1
    if (LL_USART_IsActiveFlag_RXNE(USART1) != 0)
2
    {
3
      //ch_temp = USART_ReceiveData(USART1);
4
      buff[idx] = (USART1->DR & (uint16_t)0x01FF);
5
      idx++;
6
      ..... etc
7
    }
#7790234
Lesenswert?

Karl K. schrieb:

Das Problem ist m.E. das Timing des Senders. Das haut die STM-Fehlerabfragen zu und dann geht rx halt nicht mehr.

Käse! Sobald du das RX Register gelesen hast ist es automatisch frei für den nächsten Empfang.

Karl K. schrieb:

Ich versuche, das ohne Hal registernah zu programmieren. Dafür müsste ich nur wissen, wie man den Empfang nach auslesen von DR wieder freigibt.

Brauchst du nicht, wie gerade vorher beschrieben.

Karl K. schrieb:

Das Problem ist m.E. das Timing des Senders.

Nein! Das Problem ist dass du viel zu viel Zeit in der ISR verschwendest. Es ist nicht egal wo man ein und dieselbe Aufgabe erledigt.

#7790244
Lesenswert?

Schaue dir um Gottes Willen endlich ein vernünftiges Beispiel an und lerne daraus, oder "Copiere und Paste" Teile daraus bevor du spekulierst (nicht verstehst) was mit den Registern passiert.

Harry L. schrieb:

Schau dir meinen Code mal an! Der funktioniert bei mir in vielen Projekten sehr zuverlässig:

Beitrag "[STM32/HAL] simples U(S)ART-Library"

.... ist durchaus empfehlenswert!

#7790264
Lesenswert?

J. S. schrieb:

Eine Tücke ist das es beim Cortex-M mehrere Busse gibt und die Devices asynchron laufen, das ist nicht so einfach wie bei AVR.

Nur darum muß man sich hier garnicht kümmern, außer die passende Bustaktfrequenz für die Baudrateneinstellung zu verwenden.

Wastl schrieb:

Schaue dir um Gottes Willen endlich ein vernünftiges Beispiel an und lerne daraus,

Gut, dann hänge ich mal etwas an, was bei mir auf einem F407 läuft und USART3 verwendet. Das kann man ja auf USART2 ändern. Die Sende- und Empfangspuffer kann man jederzeit löschen.

'HAL'frei und vegan! ;-)

Angehängte Dateien:
#7790419
Lesenswert?

Mi N. schrieb:

'HAL'frei und vegan! ;-)

Danke, das war es wohl:

1
void clr_rx3_buf()
2
{
3
  USART3->CR1 &= ~(USART_CR1_RXNEIE);   // RXIE abschalten
4
  __ISB();
5
  usart3_rx_lese_zeiger = 0;
6
  usart3_rx_schreib_zeiger = 0;
7
  USART3->CR1 |= (USART_CR1_RXNEIE);    // RXIE einschalten
8
}

statt

1
  rx_buff[rx_buff_ct++]=USART2->DR;
2
  USART2->CR1 &= ~USART_CR1_RE;
3
  USART2->CR1 |= USART_CR1_RE;

läuft es mit

1
  rx_buff[rx_buff_ct++]=USART2->DR;
2
  USART2->CR1 &= ~(USART_CR1_RXNEIE);
3
  USART2->CR1 |= (USART_CR1_RXNEIE);
Gast #7790539
Lesenswert?

Karl K. schrieb:

es läuft mit
rx_buff[rx_buff_ct++]=USART2->DR; USART2->CR1 &= ~(USART_CR1_RXNEIE); USART2->CR1 |= (USART_CR1_RXNEIE);

Das glaube ich dir, aber welchen Sinn macht es, innerhalb der ISR diesen einen Interrupt zu deaktivieren und wieder aktivieren?

Bei mir sehen die ISR ganz schlicht so aus:

1
void USART2_IRQHandler()
2
{
3
    char c = USART2->DR;
4
    // do something with c
5
}

Weitere Registerzugriffe finden dort nicht statt.

Das vollständige Beispiel ist auf: http://stefanfrings.de/stm32/stm32f1.html#usart

#7790547
Lesenswert?

Sherlock 🕵🏽‍♂️ schrieb:

Karl K. schrieb:

es läuft mit rx_buff[rx_buff_ct++]=USART2->DR; USART2->CR1 &= ~(USART_CR1_RXNEIE); USART2->CR1 |= (USART_CR1_RXNEIE);

Das glaube ich dir, aber welchen Sinn macht es, innerhalb der ISR diesen einen Interrupt zu deaktivieren und wieder aktivieren?

bis

rx_buff[rx_buff_ct++]=USART2->DR; sind wir uns alle einig. DR ist jetzt not empty (RXNE) und muss für den nächsten Lesevorgang freigegeben werden. Lesen von DR löscht RXNE, DR bleibt aber trotzdem gesperrt. Gesucht werden die Register, die für das Lesen des nächsten Bytes gehandelt werden müssen. Ich habe sie nicht gefunden. Das Manual hilft nicht weiter. Der Hal-Code ist kryptisch. In dem hier geposteten Code habe ich auch nichts gefunden.

USART_CR1_RXNEIE ist vielleicht der Holzhammer - aber zumindest bei 9600 Baud wirkt er perfekt. Kürzer geht es nicht. Was spricht also gegen den Holzhammer?

Gast #7790565
Lesenswert?

Karl K. schrieb:

DR ist jetzt not empty (RXNE) und muss für den nächsten Lesevorgang freigegeben werden.

Lesen von DR löscht RXNE, DR bleibt aber trotzdem gesperrt

Ich weiß 100% sicher, dass man auf L0, F1 und F3 nichts extra freigeben muss. Wenn das beim F4 entgegen seinem Referenzhandbuch plötzlich anders ist, fresse ich einen Besen. Im Errata steht auch nichts dazu.

Der Professor Laurent Latorre sieht das sieht vielen Jahren genau so:

2.2 Basic USART RX interrupt handler

1
extern uint8_t  console_rx_byte;
2
extern uint8_t  console_rx_irq;
3

4
void USART2_IRQHandler()
5
{
6
  // Test for RXNE pending interrupt
7
  if ((USART2->ISR & USART_ISR_RXNE) == USART_ISR_RXNE)
8
  {
9
    // RXNE flags automatically clears when reading RDR.
10

11
    // Store incoming byte
12
    console_rx_byte = USART2->RDR;
13
    console_rx_irq = 1;
14
  }
15
}

https://www.pomad.fr/tutorials/stm32/uart_tx_interrupts

(Firma: Jasinski) #7790580
Lesenswert?

Sherlock 🕵🏽‍♂️ schrieb:

Ich weiß 100% sicher, dass man auf L0, F1 und F3 nichts extra freigeben muss. Wenn das beim F4 entgegen seinem Referenzhandbuch plötzlich anders ist, fresse ich einen Besen. Im Errata steht auch nichts dazu.

Beim F411 muss auch nichts „freigegeben werden” – für einfache (Test)Zwecke reicht es aus, es so mit einer Zeile zu machen wie Du es vorhin geschrieben hast. Das Lesen des Datenregisters löscht das RXNE-Flag. Wenn man es besser machen will, dann sollte man die drei Haupt-Error-Flags (ORE, NF/NE und FE) überprüfen. Die Sequenz, diese zu löschen, ist etwas anders, aber auch nicht schwer: Statusregister lesen, danach Datenregister lesen und fertig – ist alles im Reference Manual beschrieben. Was hier mit dem F411 gemacht wird, gleicht einer Comedy.

(Firma: Jasinski) #7790671
Lesenswert?

Übrigens, wer zusätzlich den Sende-Interrupt aktiviert oder ihn abfragt, obwohl dieser deaktiviert ist, ist selber schuld und hat meistens seine Hausaufgaben nicht gemacht – diesen Interrupt braucht man normalerweise nicht, denn was man zu welchem Zeitpunkt sendet, weiß man ja in der Regel selbst – der Zeitpunkt des Empfangs ist dagegen unbekannt und muss daher per Interrupt abgefangen werden – das ist ja auch der Witz an der Geschichte. Durch den aktivierten Sendeinterrupt verschenkt man ferner auch unnötig Rechenzeit der CPU, denn die Interruptroutine wird bei jedem Senden (Überschreiben der Sendedaten in das Output-Schieberegister) immer sinnlos in voller Montur angesprungen – mit Prolog und Epilog – obwohl nichts angekommen ist. Vollführt man dann auch noch nur eine einzige Fließkommaberechnung in derselben, so werden auch diese Spezial-Register von der CPU real auf dem Stack gerettet und das dauert dann gleich 2-3x so lange als der übliche Prolog und Epilog. Ist nur der Interrupt für den Empfang aktiviert, muss man auch nicht immer stupide abfragen, was nun passiert ist, denn das ist dann völlig klar – im Empfangsbuffer ist etwas angekommen. Ob es verwertbar ist oder nicht, kann man dann anhand der Error-Flags entscheiden – das hat aber erstmal mit dem ersten Sachverhalt nichts zu tun, sondern ist nur eine zusätzliche Luxusaufgabe. Wer wirklich den Sendeinterrupt braucht und ihn deswegen explizit einschaltet, der wird in der Regel auch wissen, wie das mit dem Lesen und Löschen der Flags und dem Empfang von Daten vonstattengeht und dass man das vorab auch abzufragen braucht. Es gibt noch den TC-Interrupt – hier gilt eigentlich das gleiche – was nicht nötig ist, wird auch nicht aktiviert und braucht deswegen in der Interruptroutine auch nicht abgefragt zu werden. Ferner gibt es bei den STM32 noch gebündelte Interrupts – hier muss man dann ggfs. vorher die Instanz, von der der Interrupt kommt, abfragen.

HAL, LL und selbstgeschriebene Registerzugriffe miteinander zu verbinden, ist eigentlich gar nicht so schwer – jedes Kind kann das, welches z.B. mit 6 Jahren angefangen hat, seine – ihm vom Schicksal vorher bestimmte – Geige zu spielen. Wer aber sehr fleißig mit dem Studieren der Datenblätter ist, schafft es auch mühelos im Laufe der Jahre trotz seines Alters. Aufholen wird er das Kind aber vermutlich nicht.

#7790674
Lesenswert?

Wastl schrieb:

Das TO- Verhalten kann eigentlich nur durch Dummheit und/oder Wahrnehmungs- störungen entschuldigt werden.

Dummheit muss man nicht entschuldigen. Es gibt halt nicht nur kluge sondern auch dumme Menschen. Ich muss al dummer Mensch Probleme bewältigen, die kluge Menschen vielleicht gar nicht erst haben.

Sherlock 🕵🏽‍♂️ schrieb:

Der Professor Laurent Latorre sieht das sieht vielen Jahren genau so:

if ((USART2->ISR & USART_ISR_RXNE) == USART_ISR_RXNE) { // RXNE flags automatically clears when reading RDR. // Store incoming byte console_rx_byte = USART2->RDR; console_rx_irq = 1; }

Ist ein interessanter Ansatz: During an USART reception, data shifts in least significant bit first through the RX pin. In this mode, the USART_DR register consists of a buffer (RDR) between the internal bus and the received shift register.

Der Professor greift statt des DR das RDR-Register ab. Das soll funktionieren? Muss man erst mal drauf kommen. Ich werde das ausprobieren.

Es gibt hier verschiedene stm-Uart-threads wo zunächst was nicht ging - was eigentlich hätte gehen müssen - und dann auf einmal doch ging: STM-Mysterium.

Gast #7790679
Lesenswert?

Gregor J. schrieb:

Übrigens, wer zusätzlich den Sende-Interrupt aktiviert oder ihn abfragt, obwohl dieser deaktiviert ist, ist selber schuld und hat meistens seine Hausaufgaben nicht gemacht – diesen Interrupt braucht man normalerweise nicht, denn was man zu welchem Zeitpunkt sendet, weiß man ja in der Regel selbst

Wenn man ungepuffert sendet: ja

Das ist aber eher Anfänger-Niveau. Selbst Arduino ist darüber hinweg.

(Firma: Jasinski) #7790696
Lesenswert?

Sherlock 🕵🏽‍♂️ schrieb:

Wenn man ungepuffert sendet: ja Das ist aber eher Anfänger-Niveau. Selbst Arduino ist darüber hinweg.

Die meisten AVRs haben für RX und TX getrennte Interruptvektoren und genau darum geht es – also am besten nochmal darüber nachsinnen. Besser noch – immer vor dem Schreiben diese Aufgabe sorgfältig mehrmals tätigen.

#7790856
Lesenswert?

Karl K. schrieb:

Der Professor Laurent Latorre sieht das sieht vielen Jahren genau so:

ausprobiert:

1
   if ((USART2->SR & USART_SR_RXNE) == USART_SR_RXNE)
2
    {
3
      // RXNE flags automatically clears when reading RDR.
4
      // Store incoming byte
5
    rx_buff[rx_buff_ct++] = USART2->DR;
6
            //console_rx_byte = USART2->RDR;
7
      //console_rx_irq = 1;
8
    }

liest immer das erste Byte - und dann ist Schluss. Mag bei einem F0 funktionieren - bei meinem F4 nicht.

#7790955
Lesenswert?

Karl K. schrieb:

ausprobiert:

Was soll das? Einfach irgendwas hingerotzt ohne Zusammenhänge zu zeigen. Entweder bist du ein hartnäckiger Troll oder du musst noch sehr viel (vieeeeel) lernen.

Fang am besten mal hier an (falls du kein Troll sein willst: Netiquette Besonders Punkt drei gilt es stark zu beherzigen.

Aber eigentlich bist du zu lange hier angemeldet (mehr als 13 Jahre) um das nicht zu wissen. Also doch eher Troll(iges) Verhalten .....

(Firma: Jasinski) #7790980
Lesenswert?

Folgender auf ein Minimum reduzierter Code funktioniert mit einem STM32F411RET6 ohne Probleme:

1
void USART1_IRQHandler(void)
2
{
3
  USART1->DR = USART1->DR;
4
}

Ich kann vom PC aus über ein Terminal sowohl einzelne Zeichen als auch lange Textpassagen versenden – alles kommt ordnungsgemäß zum Terminal zurück und es blockiert sich nichts, ich kann anschließend immer wieder erneut etwas schicken und bekomme es ordnungsgemäß zurück. Die Interruptroutine wird auch nicht fehlerhaft mehrfach ausgeführt, da das besagte RXNE-Flag durch das Lesen des Datenregisters gelöscht wird, so wie es im Datenblatt steht. Die USART-Verbindung läuft über ST-LINK-2V1 und dann über USB-Kabel zum PC – das Terminalprogramm ist HTerm, würde aber auch mit anderen, vergleichbaren Programmen funktionieren. Genommen wurde meine Standardbaudrate 115200, das F411-Board selbst stammt aus meinen Entwürfen, die ich offiziell verkaufe, mit einem F411RE-Nucleo wird es aber genauso funktionieren. Aktiviert ist in so einem Fall natürlich nur der Empfangsinterrupt.

(Firma: Schweigstill IT) Persönliche Seite #7791042
Lesenswert?

Sherlock 🕵🏽‍♂️ schrieb:

Mi N. schrieb:

Im 'Normalfall' braucht man CubeMX dafür garnicht

Spätestens wenn der federführende Student wo anders einen besseren Job gefunden hat kommt das nächste inkompatible Framework. Mein Bauch sagt mir, dass es bald wieder so weit sein wird.

Unsinn. STM32CubeMX ist mittlerweile ein ziemliches leistungsfähiger Konfigurator für so ziemlich alles geworden und wird immer weiter ausgebaut. Neue Features sind zwar anfangs manchmal etwas fehlerhaft (wie bei fast jeder Software), aber ein, zwei Versionen später recht brauchbar. Da es das Programm schon seit deutlich über zehn Jahre gibt, dürfte "der federführende Student" entweder schon längst bei ST fest angestellt sein, oder es steckt wohl mittlerweile längst ein ganzes Team dahinter.

Gast #7791066
Lesenswert?

Spätestens wenn der federführende Student wo anders einen besseren Job gefunden hat kommt das nächste inkompatible Framework. Mein Bauch sagt mir, dass es bald wieder so weit sein wird.

Andreas S. schrieb:

Unsinn.

Sage das keinem Bauch :-)

Spaß beiseite: Ich würde mich natürlich freuen, wenn das noch lange weiter gepflegt wird.

#7791100
Lesenswert?

Gregor J. schrieb:

Folgender auf ein Minimum reduzierter Code funktioniert mit einem STM32F411RET6 ohne Probleme:

Das glaube ich dir. Ich habe nur einen STM32F411CEU6 - mit dem funktioniert das fortlaufende Lesen nur mittels Auslesen von USART2->DR; nicht. Das habe ich jetzt genügend getestet. Ich verstehe den hier teilweise auftretenden Unmut, weil es wohl eigentlich funktionieren müsste. Das hilft mir mit meinem speziellen CEU6 nicht weiter. Ihr erklärt mir, wie es normalerweise laufen müsste. Ich probiere es aus und es geht nicht und frage nach wie es funktionieren soll weil die Erklärungen zum normalen Verlauf nicht zum erwarteten Ergebnis führen. Wir reden aneinander vorbei.

Liegt vielleicht an dem speziellen chip. Kommt bei stm wohl schon mal vor.

(Firma: Jasinski) #7791120
Lesenswert?

Karl K. schrieb:

Liegt vielleicht an dem speziellen chip. Kommt bei stm wohl schon mal vor.

Es ist sehr unwahrscheinlich, dass es am Chip liegt, den Fehler solltest Du in erster Linie bei Dir selbst suchen, das ist zu 99% immer so – Code, Aufbau, Design, Testmethode etc. So speziell ist der CEU6 außerdem auch wieder nicht wie man von außen denken könnte – hier ist das Siliziumplättchen vermutlich einfach nur in einem anderen Gehäuse mit weniger Bonding eingekapselt, aber wenn Du Zweifel daran hast, kannst Du Dich mit diesem Anliegen direkt an STM wenden. Viel wichtiger ist außerdem die Revisionsnummer des Chips, aber als ich meine Boards entwickelt habe, habe ich damals nichts Besorgniserregendes zu den F411 und F446 in den Erratas gefunden – die üblichen Fehler halt, die sich in den Kernen von Familie zu Familie wiederholen. Beim STM32F303CCT6 war das z.B. anders – hier ist es wichtig, die richtige Revision beim Kauf erwischt zu haben.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren