Forum: Mikrocontroller und Digitale Elektronik STM32 DMA Buffer kopieren


von Roman R. (reiter86)


Lesenswert?

Hallo,

Versuche Daten mittels einem Nucleo32 mit der Funktion 
HAL_UARTEx_ReceiveToIdle_DMA zu empfangen, was funktioniert. Jedoch 
werden die Daten immer ab der Position gespeichert wo die vorherige 
aufhörte.

Kann den Buffer nur 1 zu 1 kopieren, aber ich kann die Daten nicht 
bearbeiten, d.h. ich kann z.B. den String: "\0\0\0\0AT+CIPSEND...\0" 
nicht sortieren zu "AT+CIPSEND...\0\0\0\0\0". Hat wer eine Ahnung wieso 
das nicht funktioniert?

Habe schon eigene Sortieralgorithmen geschrieben, aber wie gesagt, kann 
ich die Daten nicht verändern!?

von Walter Tarpan (Gast)


Lesenswert?

Roman R. schrieb:
> Jedoch werden die Daten immer ab der Position gespeichert wo die
> vorherige aufhörte.

Genau das ist doch den Sinn eines Buffers.

von Sortier-Tier (Gast)


Lesenswert?

Roman R. schrieb:
> Habe schon eigene Sortieralgorithmen geschrieben, aber wie gesagt, kann
> ich die Daten nicht verändern!?

Welchen Datentyp hat denn dein Buffer? Und wie sehen deine 
Sortieralgorithmen aus? Etwas Code würde hier einiges erklären ...
Grundsätzlich kannst du natürlich jeden Buffer den du in eigenen 
globalen/lokalen Variablen angelegt hast bearbeiten, darum wäre gut mal 
etwas Code zu sehen um das eigentliche Problem zu finden.

Eine andere konzeptionelle Frage: Warum willst du diese Daten 
**sortieren**? Normalerweise würde man diese \0 bytes eher überspringen 
wollen und sie höchstens als Trenner für den nächsten Befehl sehen.

von Roman R. (reiter86)


Lesenswert?

ja, das Problem ist wenn ich das in einem Editor mit einem "pseudo 
string" mache funktioniert es ja. Wenn ich das aber dann implementiere 
und ausführe wurde laut Debugger der RxBuffer 1:1 in Rx kopiert.

Ich möchte sortieren, dass ich eingehende Nachrichten auf gewissen 
Inhalten abfragen kann.

DMA-Empgangspuffer:
1
#define RxBuf_SIZE   100
2
uint8_t RxBuffer[RxBuffer_SIZE]={0};

Puffer, indem ich Daten sortiere:
1
#define MessageBuffer_SIZE 30 
2
char Rx [MessageBuffer_SIZE];

Sortierfunktion, sucht das 'A' kopiert die Zeichen bis zum Pufferende 
und fügt die Zeichen vor dem 'A' am Schluss hinzu.
1
void new_cop(char * new_str, char * str){
2
3
    char pos_A = pos(str,'A');
4
5
    memcpy( new_str, str+pos_A , MessageBuffer_SIZE-pos_A );
6
7
    if(pos_A>0)
8
    {
9
        memcpy( new_str+MessageBuffer_SIZE-pos_A), str , pos_A);
10
    }
11
}

Die Callback und Einstellungen sind nach dieser Vorlage 
https://controllerstech.com/uart-dma-with-idle-line-detection/

von STK500-Besitzer (Gast)


Lesenswert?

Roman R. schrieb:
> Sortierfunktion, sucht das 'A' kopiert die Zeichen bis zum Pufferende
> und fügt die Zeichen vor dem 'A' am Schluss hinzu.

Wozu?

von PittyJ (Gast)


Lesenswert?

Roman R. schrieb:
> Sortierfunktion, sucht das 'A' kopiert die Zeichen bis zum Pufferende
> und fügt die Zeichen vor dem 'A' am Schluss hinzu.void new_cop(char *
> new_str, char * str){
>     char pos_A = pos(str,'A');
>     memcpy( new_str, str+pos_A , MessageBuffer_SIZE-pos_A );
>     if(pos_A>0)
>     {
>         memcpy( new_str+MessageBuffer_SIZE-pos_A), str , pos_A);
>     }
> }

Cool dann braucht man nur noch 25 andere, um alle Buchstaben voll zu 
haben.

von Sortier-Tier (Gast)


Lesenswert?

Roman R. schrieb:
> Ich möchte sortieren, dass ich eingehende Nachrichten auf gewissen
> Inhalten abfragen kann.

Was soll das genau bedeuten? Ein echtes Sortieren sehe ich hier nicht, 
nur ein bisschen herumschieben von 0-Bytes die anscheinend keine 
Bedeutung spielen.

Auch wie die Funktion new_cop aufgerufen wird sehe ich da nicht ... 
sobald man irgendetwas anderes als "new_cop(Rx, RxBuffer);" benutzt 
gibt's schon Probleme, denn hier werden die größen der beiden Strings 
nicht übergeben, sondern angenommen. Wenn in RxBuffer erst 31 \0-Bytes 
stehen und dann der Befehl kommt gibt's Probleme, denn die Länge vom 1. 
memcpy wird unschön.

Wenn du am Ende in Rx nur die Befehle haben willst (getrennt durch EIN 
0-Byte, denn die Anzahl scheint ja egal zu sein), solltest du erstmal 
die Position des ersten nicht-0-Byte finden und von da bis zum nächsten 
0-Byte (oder Bufferende!) kopieren und dahinter EIN 0-Byte schreiben.

von STK500-Besitzer (Gast)


Lesenswert?

PittyJ schrieb:
> Cool dann braucht man nur noch 25 andere, um alle Buchstaben voll zu
> haben.

+ Groß-/ und Kleinschreibung und Sonderzeichen...

von Sortier-Tier (Gast)


Lesenswert?

Übrigens, zusätzlich zu den vielen Problemen mit der new_cop Funktion: 
Wenn die pos-Funktion (von der ich keine Ahnung habe was sie 
zurückliefert) 0 zurückliefert, wird RxBuffer einfach in Rx kopiert ... 
ich denke das passiert in deinem Fall, da pos schlecht implementiert 
ist.

von STK500-Besitzer (Gast)


Lesenswert?

Einfache Frage: Was soll das werden?
"AT"-Kommandos lassen auf irgendwelche Modem-Geschichten schließen.
Normalerweise kommen dann doch Fragen, ob jemand sowas nicht schon 
fertig in der Schublade hat.

von W.S. (Gast)


Lesenswert?

Roman R. schrieb:
> Versuche Daten mittels einem Nucleo32 mit der Funktion
> HAL_UARTEx_ReceiveToIdle_DMA zu empfangen, was funktioniert. Jedoch
> werden die Daten immer ab der Position gespeichert wo die vorherige
> aufhörte.

Es nervt. So ein UART ist ein Ding, was normalerweise zum seriellen 
Übertragen von Informationen - zumeist Text - benutzt wird. Und das 
erfolgt asynchron und seriell. Genau deshalb sollte ein Treiber (egal 
auf welcher Seite) eben diese Informationen nacheinander liefern (bzw. 
zum Senden entgegennehmen). Stück für Stück, Zeichen für Zeichen.

Nein, ich will hier nicht auf die Sinnfälligkeit von DMA zu sprechen 
kommen, sondern das Thema ist der Pufferspeicher, der in jede der 
Richtungen (senden, empfangen) notwendig ist. Normalerweise ist das 
etwas, das der Treiber selber verwaltet und sonst niemand darin 
herumzuwurschteln hat.

Um die Zeichen nacheinander vom Treiber zu kriegen, gibt es 
normalerweise Funktionen des Treibers, die einem ansagen, ob es was zu 
holen gibt bzw. das nächste Zeichen liefern. Was also soll das 
Hineingrätschen in die Interna des Treibers? Die gelieferten 
Empfangszeichen stopft man in eine separate Empfangszeile und dekodiert 
diese, wenn das Zeilenende erreicht ist.

OK, es gibt auch andere Kommunikationsmodelle über eine Serielle. Aber 
alle solche Vorgehensweisen grapschen NICHT in die Eingeweide des 
Treibers.

W.S.

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.