Forum: Mikrocontroller und Digitale Elektronik STM32F303 USART2 DMA1 funktioniert halblebig ?


von Andrey (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen !!!

ich habe versucht die Daten über USART2 mit Hilfe von DMA1 zu senden. So 
wie es in mehreren Foren geschrieben ist funktioniert alles soweit, aber 
nur mit einem einzigen String.
Wenn man versucht mehrere Strings mit unterschiedlicher Länge (was auch 
in der Praxis oft vorkommt) zu senden, wird die erste Sendung durch den 
zweiten "verschluckt". Schauen Sie bitte das Bild wrong_text.jpg an !

Vielleicht hat jemand dafür eine Erlärung ?

Die Quellcodedateien füge ich auch bei.

Im voraus - Danke für eure Hilfe.

Andrey

von Jim M. (turboj)


Lesenswert?

Du schaust vor dem Senden (genauer: Start des DMA) nicht nach, ob der 
vorherige Transfer schon abgeschlossen wurde. Alle noch nicht 
verarbeiteten Zeichen fallen damit weg.

von Andrey (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Jim,

du hast ja recht - ich starte die neue Übertragung ohne zu prüfen ob die 
vorheriege bereits abgeschlossen ist. Ich habe die Funktion 
usart2_sendDataDma() verbessert und die Applikation funktioniert jetzt 
problemlos.

Im Anhang die koregierte Files: user2dmactrl.c und main.c 
veröffentlicht.

Ich habe in der Funktion usart2_sendDataDma() neue Codezeile eingefügt:
while((USART_GetFlagStatus(USART2,USART_FLAG_TC)==RESET){;}

Danke fü deine Hilfe !!!

Gruß

Andrey

von Andrey (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Jim,

ich habe noch eine Frage:
Ich krige das Datenempfang über USART2 per DMA nicht zum laufen ?
Das USART2 , DMA Rx Interrupt und den DMA Kanal habe ich initialisiert 
und kriege sogar drei Zeichen aus den zehn gesandten zu empfang. 
Restliche sieben Zeichen sind wieder geschluckt. Siehe das Bild.
In disem Fall, denke ich, muss man nichts prüfen: sobald DMA übertragung 
abgeschlossen ist wird ein DMA Rx Interrupt ausgelost und ich kann die 
Daten lesen ?! Verstehe ich was falsch ?

Vielleicht hast du eine Idee warum nur drei Zeichen aus zehn werden 
übertragen ?

Im voraus Danke für deine Antwort !

Gruß

Andrey

von Karl H. (kbuchegg)


Lesenswert?

Andrey schrieb:

> und kriege sogar drei Zeichen aus den zehn gesandten zu empfang.
> Restliche sieben Zeichen sind wieder geschluckt.

Kardinalfehler.
Nur weil DU am Terminal 10 Tasten drückst, bedeutet das nicht, dass die 
an der Gegenstelle auch alle 10 auf einem aus dem Read Code rauskommen.
1
  while (1)
2
  {
3
    // if USART2 data received ?
4
    if(usart2_getUsart2Ctrl()->flagRx == 1)
5
    {

sobald das erste Zeichen übertragen wurde, kriegst du hier schon die 
Benachrichtigung, dass etwas auf der UART eingetrudelt ist. Die UART 
kann ja nicht wissen, dass du noch weitere 9 mal auf eine Taste drücken 
wirst.

D.h. wenn du dir die bisher eingetrudelten Daten dann abholst, kannst du 
nicht a prioir sagen: da sind jetzt 10 Bytes in der UART. Es sind so 
viele Bytes in der UART, wie bis zu diesem Zeitpunkt übertragen wurden.
Und während du dir die bisher übertragenen Bytes abholst, läuft die 
Übertragung weiter. D.h. während dieser Code
1
        // copy Rx Buffer to Tx Buffer
2
      sprintf(usart2_getUsart2Ctrl()->txBuf,usart2_getUsart2Ctrl()->rxBuf);
3
      // send received data back to terminal
4
      usart2_sendDataDma(usart2_getUsart2Ctrl()->txBuf, strlen(usart2_getUsart2Ctrl()->txBuf));
5
      // clear Flag
6
      usart2_getUsart2Ctrl()->flagRx = 0; // clear Rx flag
7
      memset(usart2_getUsart2Ctrl()->rxBuf,'\0',sizeof(usart2_getUsart2Ctrl()->rxBuf));   // clear Rx buffer
läuft, ist noch immer Aktivität auf der UART. Was natürlich blöd ist, 
weil du dir mit dem memset ganz zum Schluss genau diese in der 
Zwischenzeit eingetrudelten Bytes über den Haufen schiesst.

Der Kardinalfehler besteht praktisch immer in der Annahme, man würde aus 
einer UART komplette Strings rauskriegen, die genau so lang sind wie 
die, die die Gegenstelle auf den Weg bringt. Dem ist nicht so. Du musst 
darauf vorbereitet sein, dass du das Übertragene in kleinen Happen 
kriegst und das entweder auch in kleinen Happen verarbeiten musst oder 
aber erst  mal die kleinen Happen wieder zu kompletten Strings 
zusammensetzen musst. Oder warum denkst du, ist es üblich eine Eingabe 
am einem Sichtgerät (meistens) mit einem Druck auf die Return-Taste 
abzuschliessen?

von Little B. (lil-b)


Lesenswert?

Ich sehe hier zwei potentielle punkte zum ansetzen:

1. Du prüfst das USART-Flag, um empfangene Daten engegen zu nehmen. Aber 
das tut ja der DMA bereits. Frage besser den DMA, wieviel Daten er schon 
in den Speicher geschrieben hat.

2. Ich sehe keine Hinweiße auf den DMA FIFO. Beim Receive ist der FIFO 
eher hinderlich, da dieser erst geflusht wird, sobald genug Daten 
vorhanden sind. Kommen nicht genug Daten an (weil die empfangene 
nachricht einfach nicht die richtige länge hat) kommen bis zu 8 byte 
nicht im Speicher an.

Noch ein Tipp:
Du nutzt den Interrupt des DMA Rx, um diesen zurück zu setzen, wenn der 
Buffer voll ist. Nutze besser die "Circular"-Option, dann setzt sich der 
DMA selbst zurück und startet den Job nochmals.
Ich habe den DMA auch schon mit Hilfe von interrupts zurück gesetzt. 
Dabei habe ich aber immer ankommende Daten verloren, da der DMA nicht 
wieder schnell genug aktiv war. Der Circular-Modus hat abhilfe 
geschafft.

von Andrey (Gast)


Lesenswert?

Hallo Zusammen,

ich bedanke mich für Ihre schnelle Antworten !!!

Ja, das Umschalten von DMA auf Circullar mode hat das Problem teilweise 
gelöst: es werden fast alle Zeichen ohne Verlust empfangen. Leider gehen 
bei längeren Zeichensequenzen, immer noch, ein oder paar Zeichen 
verloren.

Ich bin nicht zufrieden, weil die eingehende Strings bei mir 
unterschiedlich lang sein können und somit erweist sich diser Einsatz 
als unpraktikebel.

Ich werde auf normale Rx Interrupt umsteigen.

Danke noch mals an alle Helfende !!!

Mit freundlichen Grüßen

Andrey

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.