Am 15.05.22 um 00:32 schrieb Sebastian Reinhardt:
Am 14.05.22 um 23:07 schrieb Tobias Schlemmer:
Hallo Sebastian,

nutzt Du eine Hardware-UART? Dann solltest Du mal versuchen, die
High-Level-Funktionen zu nutzen. Das heißt in dem Fall ist es
vermutlich günstiger, Du gehst über den Linux-Treiber, genauso wie
das minicom tut. Das sollte ausreichend dokumentiert sein. Such
einfach nicht nach Pi + UART, sondern nach linux serial io. Ich würde
mal vermuten, dass gpioSerialRead eine Software-UART implementiert,
das heißt, sie liest das GPIO-Pin direkt und spielt selber UART.

Was Du nicht machen solltest, ist, Software-UART und Hardware-UART
über denselben Pin laufen zu lassen. Dann muss der Pin nämlich zwei
Herren dienen. Und jeder, der das mal versucht hat, weiß, dass es
früher oder später zu Konflikten führt. Grundsätzlich kann ein Pin zu
jedem Zeitpunkt maximal eine Funktion ausführen: GPIO oder UART oder
... (je nachdem, was im Datenblatt steht).

Was auch nicht funktioniert: minicom und Dein Programm gleichzeitig
auf /dev/ttyS0 – oder was auch immer es ist – zuzugreifen. Die
Datenströme werden nicht dupliziert.

Eine Weitere Fehlerquelle besteht darin, wenn Du das ganze im Polling
betreibst und nicht im Interrupt. Wenn Dein Prozess aus irgendeinem
Grund zu spät aufwacht (und das ist meist erlaubt), dann kann es
passieren, dass der Empfangspuffer schon überschrieben wurde, bevor
er ausgelesen wurde (das sollte aber andere Probleme bringen). An der
Stelle solltest Du auch immer im Hinterkopf haben, dass Linux kein
Echtzeit-System ist.

Wie stellst Du sicher, dass das erste Zeichen im read_buf auch das
erste Zeichen einer neuen Zeile ist?
Wenn Du Kauderwelsch empfängst solltest Du davon ausgehen, dass die
Übertragung gestört war und warten, bis eine <Start of
Record>-Nachricht kommt (das ist hier in dem Fall gleich dem <End of
Record> und wird durch das Zeichen CR ausgedrückt).

Viele Grüße

Tobias



Hallo Tobias,

Ich will nat. nicht gleichzeitig mit dem C++-Programm und minicom auf
die Schnittstelle zugreifen. Das habe ich dann nur mal zur Kontrolle
gemacht, nachdem ich das "Kauderwelsch" bekommen habe.

Die Funktion "gpioSerialRead
<https://abyz.me.uk/rpi/pigpio/cif.html#gpioSerialRead>" aus der Lib:
[1] macht die Abfrage im BitBang-Modus. D.h., die lauscht nur. Ich
will ja auch nichts schreiben, sondern nur den Messdaten "lauschen".

Dann solltest Du

a) die entsprechende Serielle Schnittstelle deaktivieren, und darauf
achten, dass der pin auf GPIO geschaltet ist.

b) einen freien GPIO benutzen, auf dem kein Treiber lauscht

c) wie gesagt die Finger vom BitBang-Modus lassen und den Linux-Treiber
benutzen

Übrigens: b) und c) lassen sich auch kombinieren, indem Du eine
Drahtbrücke zwichen RX und dem GPIO-Pin schaltest. Oder du machst die
Brücke und hängst minicom an serial0 und gpioSerialRead an den GPIO pin.


Nun bin ich mir eben unsicher, ob ich die kompletten Routinen für die
serielle Kommunikation, die es ja im Netz gibt, benötige. Ich möchte
das so einfach, wie möglich halten. Oder befinde ich mich hier auf dem
Holzweg? Übersehe ich was ?

Brauchst Du nicht. Must nur 9600 N 1 setzen (das sind 3 Parameter) und
dann kannst Du selber von von /dev/serial0 lesen.

Aber wenn ich mir

https://blog.mbedded.ninja/programming/operating-systems/linux/linux-serial-ports-using-c-cpp/

durchlese, dann kannst Du den Code parallel zur Erklärung in Deinen
Quelltext kopieren und denke, innerhalb von einer halben Stunde läufts.

Das meiste kannst Du erstmal übernehmen,

VMIN=1 und VTIME=0

erlaubt Dir

int get_R(FILE * serial_port) {

std::vector<char> chars;

char buffer;

chars.reserve(8); (etwas mehr, als gebraucht);

bool do_loop = true;

bool error = false;

while(do_loop) {

    int n = read(serial_port,&buffer, 1);

    switch (buffer) {

        case '\r' : if (error) error=false; else do_loop = false; break;

       case 'R' : chars.clear(); break;

       case '0':

        ...

       case '9':

               chars.push_back(buffer);

                break;

       default:

             printf("Unknown character, waiting for CR\n");

              break;

    }

}

chars.push_back(0);

return atoi(chars.data());

}

Oder so ähnlich (nicht getestet).

Viele Grüße

Tobias






switch state





----

[1] https://abyz.me.uk/rpi/pigpio/cif.html#gpioSerialRead




Antwort per Email an