Estoy usando la comunicación del puerto serial com sincrónicamente con WinApi. Y quiero dividir los mensajes con 13 (CR). ¿Cómo puedo usar la función ReadFile para que regrese cuando lea un 13?


La estructura DCB tiene un campo llamado EofCharpero la función continúa leyendo hasta que llena el búfer. Si envío solo 3 bytes con un 13, continúa esperando los otros 2 bytes. ¿Es realmente posible hacer que ReadFile lea menos bytes de los que el búfer proporciona y especifica nNumberOfBytesToRead?
  • Bytes dec entrantes: 12 12 13 15 18 19 ...
  • Bytes de dec. Deseados: 12 12 13(pero longitud desconocida)


Código:
// 2. reading:
DWORD bytesRead;
char* buffer = new char[5];
ReadFile(handle, buffer, 5, &bytesRead, NULL);
// bytesRead should be 3 in the example above

// 1. connecting:
HANDLE handle = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
DCB dcb;
COMSTAT stat;
if (GetCommState(handle, &dcb))
{
    dcb.BaudRate          = 57600;      // baud rate
    dcb.ByteSize          = 7;          // number of bits/byte, 4-8 
    dcb.Parity            = EVENPARITY; // 0-4=no,odd,even,mark,space 
    dcb.StopBits          = ONESTOPBIT; // 0,1,2 = 1, 1.5, 2  V2.12 0 -> ONESTOPBIT
    dcb.fBinary           = TRUE;       // binary mode, no EOF check 
    dcb.fParity           = TRUE;       // enable parity checking 
    dcb.fOutxCtsFlow      = FALSE;      // CTS output flow control 
    dcb.fOutxDsrFlow      = FALSE;      // DSR output flow control 
    dcb.fDtrControl       = 0;          //DTR_CONTROL_DISABLE; // DTR flow control type
    dcb.fRtsControl       = 0;          //RTS_CONTROL_DISABLE; // RTS flow control 
    dcb.fDsrSensitivity   = FALSE;      // DSR sensitivity 
    dcb.fTXContinueOnXoff = FALSE;      // XOFF continues Tx 
    dcb.fOutX             = FALSE;      // XON/XOFF out flow control 
    dcb.fInX              = FALSE;      // XON/XOFF in flow control 
    dcb.fErrorChar        = FALSE;      // enable error replacement V2.12 TRUE -> FALSE
    dcb.fAbortOnError     = TRUE;       // abort reads/writes on error 
    dcb.XonChar           = 0x00;       // Tx and Rx XON character 0x01
    dcb.XoffChar          = 0x00;       // Tx and Rx XOFF character 0x02
    dcb.ErrorChar         = 0x1f;       // error replacement character  
    dcb.EofChar           = 0x0d;       // end of input character 0x00
    dcb.EvtChar           = 0x00;       // received event character 0x0d

    if (SetCommState(handle, &dcb))
    {
        EscapeCommFunction(handle, SETRTS);
        EscapeCommFunction(handle, SETDTR);
        EscapeCommFunction(handle, CLRRTS);
        EscapeCommFunction(handle, CLRDTR);
        PurgeComm(handle, PURGE_TXCLEAR | PURGE_RXCLEAR);
        return true;
    }
}
ตอบ

No, eso es muy poco probable que funcione. Windows en sí no hace nada con el DCB.EofChar que especifique. O para el caso, cualquiera de los otros caracteres especiales en el DCB. Lo pasa directamente al controlador de dispositivo, el ioctl subyacente es IOCTL_SERIAL_SET_CHARS . Dejando totalmente en manos del conductor la implementación.

La mayoría de los proveedores de hardware que escriben controladores de puerto serie (emuladores USB sobre todo en estos días), utilizan el código de controlador de muestra que se incluye en el WDK. Que no hace nada con SERIAL_CHARS.EofChar. Entonces, el resultado inevitable es que nadie lo implementa. Personalmente, nunca me he encontrado con uno, de todos modos a sabiendas.

Por tanto, se espera que no tenga ningún efecto.

Por lo general, puede esperar que DCB.EvtChar funcione, alimenta la opción EV_RXFLAG para WaitCommEvent (). En otras palabras, si lo configura en el terminador de línea, puede darle una señal de que ReadFile () devolverá al menos una línea completa.

Pero dijiste explícitamente que no querías hacer esto. Todo el mundo resuelve esto simplemente almacenando en búfer los datos adicionales que devuelve ReadFile (). O leyendo un byte a la vez, lo cual está bien porque los puertos serie son lentos de todos modos.