Forum: PC-Programmierung RS232 Buffer auslesen bricht bei ASCII 26 ab.komisch


von Peter_D (Gast)


Lesenswert?

Moin Jungs,

versuche seit Tagen ein doch widerliches Problem zu lösen.
Es geht um die Programmierung eines einfachen Tools welches paar Bytes
aus dem RS232 Buffer liest und anzeigt.
Verwendet wird unter anderem Visualstudio 2008 und MFC + .NET 3.5

Man kann in der Konfiguration vom Serialport den Parameter 
ReceivedBytesThreshold einstellen, dieser gibt die Anzahl an Bytes vor, 
die vorhanden sein müssen, bis der EventArg (interrupt) "DataReceived" 
auslöst und mit der Funktion Read(array<Byte>, Int32, Int32) alle x 
Daten ausm RS232 Buffer in mein array kopiert werden.

Läuft auch alles soweit, bis zu dem Punkt:
Sobald das ASCII Zeichen 26 (SUB) bzw. die dezimale Zahl 26 im Buffer 
auftritt, bricht die Funktion "Read(array<Byte>, Int32, Int32)" ab.

Warum unterbricht dieses blöde Zeichen 26 bzw. Zahl 26 meinen 
Readbuffer?
Laut vielen Foren, heißt Ascii 26 "Dateiende". Es wird wohl damit etwas 
zu tun haben. Kennt jemand solch ein Problem?

Wie liest ihr eure Bytepakte vom RS232 Port aus? Denn es belastet den 
Rechner sehr, wenn man jede paar Millisekunden einen DataReceived 
Interrupt Handler aufrufen muss jedes Byte ins Array per Software 
kopieren muss.

Gruß
Peter

von Olaf D. (Firma: O.D.I.S.) (dreyero)


Lesenswert?

Moin,

ja ich kenne solche Probleme. Zumindest hatte ich sie unter Linux auch.
Abhilfe hat gebracht die serielle Schnittstelle im RAW-Modus zu 
betreiben,
d. h. der Treiber interpretiert dann nicht die eintreffenden Daten
bevor er sie zur Applikation weiterreicht.

Unter Windows nutze ich folgendes:
1
    options.fOutxCtsFlow        = false;    //If this member is true, the CTS (clear-to-send) signal is monitored for output flow control. If this member is true and CTS is turned off, output is suspended until CTS is sent again.
2
    options.fOutxDsrFlow        = false;    //If this member is true, the DSR (data-set-ready) signal is monitored for output flow control. If this member is true and DSR is turned off, output is suspended until DSR is sent again.
3
    options.fDsrSensitivity     = false;    //If this member is true, the communications driver is sensitive to the state of the DSR signal. The driver ignores any bytes received, unless the DSR modem input line is high.
4
    options.fOutX               = false;    //Indicates whether XON/XOFF flow control is used during transmission. If this member is true, transmission stops when the XoffChar character is received and starts again when the XonChar character is received.
5
    options.fInX                = false;    //Indicates whether XON/XOFF flow control is used during reception. If this member is true, the XoffChar character is sent when the input buffer comes within XoffLim bytes of being full, and the XonChar character is sent when the input buffer comes within XonLim bytes of being empty.
6
7
    //options.fBinary             = false;    //If this member is true, binary mode is enabled. Windows does not support nonbinary mode transfers, so this member must be true.
8
    //options.fParity             = false;    //If this member is true, parity checking is performed and errors are reported.
9
    //options.fTXContinueOnXoff   = false;    //If this member is true, transmission continues after the input buffer has come within XoffLim bytes of being full and the driver has transmitted the XoffChar character to stop receiving bytes. If this member is false, transmission does not continue until the input buffer is within XonLim bytes of being empty and the driver has transmitted the XonChar character to resume reception.
10
    //options.fErrorChar          = 0;        //Indicates whether bytes received with parity errors are replaced with the character specified by the ErrorChar member. If this member is true and the fParity member is true, replacement occurs.
11
    //options.fNull               = 0;        //If this member is true, null bytes are discarded when received.
12
    //options.fAbortOnError       = false;    //If this member is true, the driver terminates all read and write operations with an error status if an error occurs. The driver will not accept any further communications operations until the application has acknowledged the error by calling the ClearCommError function.
13
    //options.wReserved           = 0;        //Reserved; must be zero.
14
    //options.XonLim              = 0;        //The minimum number of bytes allowed in the input buffer before flow control is activated to inhibit the sender. Note that the sender may transmit characters after the flow control signal has been activated, so this value should never be zero. This assumes that either XON/XOFF, RTS, or DTR input flow control is specified in fInX, fRtsControl, or fDtrControl.
15
    //options.XoffLim             = 0;        //The maximum number of bytes allowed in the input buffer before flow control is activated to allow transmission by the sender. This assumes that either XON/XOFF, RTS, or DTR input flow control is specified in fInX, fRtsControl, or fDtrControl. The maximum number of bytes allowed is calculated by subtracting this value from the size, in bytes, of the input buffer.
16
    //options.XonChar             = 0;        //The value of the XON character for both transmission and reception.
17
    //options.XoffChar            = 0;        //The value of the XOFF character for both transmission and reception.
18
    //options.ErrorChar           = 0;        //The value of the character used to replace bytes received with a parity error.
19
    //options.EofChar             = 0;        //The value of the character used to signal the end of data.
20
    //options.EvtChar             = 0;        //The value of the character used to signal an event.
21
22
    if(!SetCommState(m_fdDevice, &options))
23
    {
24
        qDebug() << "unable to set comport cfg settings";
25
        CloseHandle(m_fdDevice);
26
        return false;
27
    }
Gruß

Olaf

von allan (Gast)


Lesenswert?

Dü könntest mal probieren ob Read(<Byte>,... ) sich anders verhält. Weit 
hergeholt, aber...

von Peter_D (Gast)


Lesenswert?

Hi,

ich habe nun rausgefunden, dass durch das ASCII zeichen 26, heißt soviel 
wie EOF End of File mein Read Buffer unterbrochen wird.
Man kann es mit:

//options.fBinary             = false;    //If this member is true, 
binary mode is enabled. Windows does not support nonbinary mode 
transfers, so this member must be true.

Normalerweise zum Binary umstellen. Leider gibt es diese Einstellung 
unter C++/Cli nicht. Man kann alles setzen, aber gerade diesen wichtigen 
Parameter nicht!

Habe alles versucht und bis jetzt keine Lösung gefunden. Fakt ist, dass 
wenn im Eingangspuffer eine 26 auftaucht, sofort eine Beendigung 
eingeleitet wird.
Bis jetzt bleibt mir nur die Möglichkeit, jedes Byte in einem Interrupt 
abzufangen und jedes Mal bufferpointer erhöhen und empfangenen Wert 
reinkopieren. Totale Resourcen verschwendung. Gut auf einem dicken 
dualcore mit zig Gigabyte Ram jucken diese paar byte nicht.
Aber auf älteren Rechnern können schon 100byte im Serialportpuffer 
nervig sein. Denn die Software wird jedes mal unterbrochen und ein byte 
weggespeichert. Genau wie auf jedem AVR,ect eine RX_Interrupt...

von jack (Gast)


Lesenswert?

Ich bin jetzt in der PC-Programmierung nicht so bewandert, aber du 
kannst auf Interrupts reagieren? Dachte die gehören dem OS.
Oder läuft das dann über Callbacks?

Wenn du auf DotNet verzichten kannst (oder auch "alten" C Code einbinden 
kannst) schau mal hier:

http://stackoverflow.com/questions/9194158/porting-posix-c-code-to-windows

Vielleicht hilft dir das weiter.

von Reinhard Kern (Gast)


Lesenswert?

Peter_D schrieb:
> Habe alles versucht und bis jetzt keine Lösung gefunden.

Nachdem fBinary nicht geht, würde ich zwar den Buffer benutzen, aber 
nach Empfang eines Ctrl-Z die Empfangsroutine einfach nochmal aufrufen.

Gruss Reinhard

von bluppdidupp (Gast)


Lesenswert?

Peter_D schrieb:
> ormalerweise zum Binary umstellen. Leider gibt es diese Einstellung
> unter C++/Cli nicht. Man kann alles setzen, aber gerade diesen wichtigen
> Parameter nicht!

...binär ist bei der SerialPort-Klasse die Standardeinstellung.
fBinary=0 wird von Windows tatsächlich auch gar nicht unterstützt.
fBinary hat allerdings mit EofChar nichts zu tun!

Eigentlich sollte nur SerialData_Received mit EventType=SerialData.Eof 
zusätzlich "eingeschoben" werden, die restlichen Daten müssten 
eigentlich in weiteren SerialData_Received-Events folgen.

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.