He leído muchos problemas con la lectura y escritura del puerto serie. Ninguno hasta ahora me ha ayudado a descubrir qué falta en mi código. El ejemplo de msdn para c ++ tiene variables indefinidas y faltan corchetes, por lo que, aunque puedo agregar corchetes, todavía no funciona. Esto es lo que tengo en este momento. Parece que puedo abrir el puerto y realizar la configuración, pero no puedo leer un byte / char de datos. Realmente solo quiero una lectura / escritura en serie asíncrona simple para que un programa lea desde un Arduino.

class MY_SERIAL
{

HANDLE serialinstance;

DWORD      dwStoredFlags;
DWORD      dwRes;
DWORD      dwCommEvent;
OVERLAPPED osStatus = {0};
BOOL       fWaitingOnStat;
//dwStoredFlags = EV_BREAK | EV_CTS   | EV_DSR | EV_ERR | EV_RING | EV_RLSD | EV_RXCHAR |      EV_RXFLAG | EV_TXEMPTY ;


DCB dcb;
COMMTIMEOUTS timeouts;

COMMCONFIG serialconfig;



public:
char inBuffer[1000];
char outBuffer[100];

PDWORD noBytes;

void close_serial()
{
    CloseHandle(serialinstance);
}
//----------------------------------------------------
bool open_serial(LPCSTR portNumber)   // serial port name use this format  "\\\\.\\COM10"
{

    serialinstance = CreateFile(portNumber, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
    if(serialinstance == INVALID_HANDLE_VALUE)
    {
        int error = GetLastError();
        printf("ERROR opening serial port  %s\r\n", portNumber);
        if(error == 0x2){printf("ERROR_FILE_NOT_FOUND\r\n");}
        if(error == 0x5){printf("ERROR_ACCESS_DENIED\r\n");}
        if(error == 0xC){printf("ERROR_INVALID_ACCESS\r\n");}
        if(error == 0x6){printf("ERROR_INVALID_HANDLE\r\n");}
        printf("error code %d\r\n", error);
        return false;
    }
    if(GetCommState(serialinstance, &dcb)!= true)
    {
        printf("ERROR getting current state of COM   %d \r\n", GetLastError());
        return false;
    }
    else{printf("debug   read current comstate\r\n");}


    FillMemory(&dcb, sizeof(dcb), 0); //zero initialize the structure
    dcb.DCBlength = sizeof(dcb);      //fill in length

    dcb.BaudRate = CBR_115200;     //  baud rate
    dcb.ByteSize = 8;             //  data size, xmit and rcv
    dcb.Parity   = NOPARITY;      //  parity bit
    dcb.StopBits = ONESTOPBIT;

    if(SetCommState(serialinstance, &dcb) != true)
    {
        printf("ERROR setting new state of COM   %d \r\n", GetLastError());
        return false;
    }
    else{printf("debug   set new comstate\r\n");}
    /*
    if (!BuildCommDCB("115200,n,8,1", &dcb)) //fills in basic async details
    {
        printf("ERROR getting port comstate\r\n");
        return FALSE;
    }
    */
    if (!SetCommMask(serialinstance, EV_RXCHAR))
    {
        printf("ERROR setting new COM MASK   %d \r\n", GetLastError());
        return false;
    }
    else{printf("debug   commmask set\r\n");}
    timeouts.ReadIntervalTimeout = MAXDWORD;
    timeouts.ReadTotalTimeoutMultiplier = 20;
    timeouts.ReadTotalTimeoutConstant = 0;
    timeouts.WriteTotalTimeoutMultiplier = 0;
    timeouts.WriteTotalTimeoutConstant = 0;

    if (!SetCommTimeouts(serialinstance, &timeouts))
    {
        printf("ERROR setting timeout parameters\r\n");
        return false;
    }
    else{printf("debug   timeouts set\r\n");}
    osStatus.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (osStatus.hEvent == NULL)
    {// error creating event; abort
        printf("ERROR creating Serial EVENT\r\n");
        return false;
    }
    else{printf("debug   event created set\r\n");}
    osStatus.Internal = 0;
    osStatus.InternalHigh = 0;
    osStatus.Offset = 0;
    osStatus.OffsetHigh = 0;
    assert(osStatus.hEvent);
    printf("debug   com port setting complete\r\n");






    return true;
}
//---------------------------------------------------------

bool read_serial_simple()
{
    char m[1000];
    LPDWORD bytesRead;



    if (WaitCommEvent(serialinstance, &dwCommEvent, &osStatus))
    {
        if(dwCommEvent & EV_RXCHAR)
        {
            ReadFile(serialinstance, &m, 1, bytesRead, &osStatus);
            printf("data read =   %d,       number bytes read =     %d  \r\n", m, bytesRead);
            return true;
        }
        else
        {
            int error = GetLastError();
            if(error == ERROR_IO_PENDING){printf(" waiting on incomplete IO\r\n");}
            else{printf("ERROR %d\r\n", error);}
            return false;
        }
    }
    return false;
}

};

Así que eliminé la función de lectura. Ahora obtengo un carácter e informa la lectura de 1 byte, pero el valor del carácter es incorrecto. Obtengo una serie de 48, 13, 10 y ocasionalmente un valor de 50 para el byte. Sin embargo, el Arduino está enviando una serie a 0 y luego a 128 como se verificó con TerraTerm. ¿Qué más necesito aquí?

bool read_serial_simple()
{
    unsigned char m = 0;
    DWORD bytesRead;
    if(ReadFile(serialinstance, &m, 1, &bytesRead, &osStatus) == true)
    {
        printf("data read =   %d,       number bytes read =     %d  \r\n", m, bytesRead);
        return true;
    }
    else{
        int error = GetLastError();
        if(error == ERROR_IO_PENDING){printf(" waiting on incomplete IO\r\n");}
        else{printf("ERROR %d\r\n", error);}
        return false;
    }

}

Entonces ahora puedo leer un byte de datos pero no puedo escribir un byte o más en el puerto. Solo obtengo ERROR_IO_PENDING. ¿Alguien puede ayudar con esto también? Escriba la función de mi clase a continuación.

bool write(DWORD noBytesToWrite)
{
    if(WriteFile(serialinstance, outBuffer, noBytesToWrite, NULL, &osStatus) == true)
    {
        printf("message sent\r\n");
        return true;
    }
    else
    {
        int error = GetLastError();
        if(error != ERROR_IO_PENDING){LastError();}
        return false;
    }
}

Estoy llamando a ambas funciones desde main de la siguiente manera

myserial.open_serial(COM12);
myserial.outBuffer[0] = 'H';
myserial.outBuffer[1] = 'e';
myserial.outBuffer[2] = 'L';
myserial.outBuffer[3] = 'l';
myserial.outBuffer[4] = 'O';
for(int n=0; n<5; n++){printf("%c", myserial.outBuffer[n]);}
printf("\r\n");

while(1)
{
    myserial.read();
    myserial.write(5);
    //system("PAUSE");
}

Actualmente, el arduino está configurado para leer bytes y repetirlos en la PC. Lo está haciendo bien en el monitor serial IDE de arduino, así que ahora solo necesito que este programa de PC escriba.

ตอบ

Su bytesReadvariable es un puntero no inicializado. Estás pasando una dirección no válida ReadFile()para escribir.

Reemplazar LPDWORD bytesReadcon DWORD bytesRead, luego pasarlo a ReadFile()usar &bytesRead.

Editar: también elimine el FILE_FLAG_OVERLAPPED. No lo está manejando correctamente, y no tiene sentido usarlo si lo está WaitForSingleObject()antes de leer.