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
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.
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
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
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?
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.