Ошибка WaitCommTimeout () 87 «неверный параметр» и другие вопросы - PullRequest
0 голосов
/ 02 марта 2020

Я проектирую класс, который обрабатывает последовательную связь.

Вот класс:

#include <stdio.h>
#include <Windows.h>
#include <process.h>
#include "port_class.h"

DCB            blank_dcb = {0};
OVERLAPPED     blank_ovl = {0};

com_port_cl::com_port_cl()
{
    int jcs, jt;
    int port_startup_error[4];    
   /*
    * Open the port
    */
    port_startup_error[0] = 0;
    port_startup_error[1] = 0;
    port_startup_error[2] = 0;
    port_startup_error[3] = 0;

    port_h = CreateFile("COM1",GENERIC_READ|GENERIC_WRITE,
                          0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
                          0);
    if(INVALID_HANDLE_VALUE == port_h)
    {
        port_startup_error[1] = (int) GetLastError();
    }

    port_wce_flag = CreateEvent(NULL,TRUE,FALSE,NULL);
    port_shutdown_flag = CreateEvent(NULL,TRUE,FALSE,NULL);
    port_tx_ready_flag = CreateEvent(NULL,TRUE,FALSE,NULL);
    if(NULL == port_tx_ready_flag)
    {
        printf("CreateEvent() failed for port_tx_ready_flag\n");
    }
    port_rx_xpect_flag = CreateEvent(NULL,TRUE,FALSE,NULL);
    if(NULL == port_rx_xpect_flag)
    {
        printf("CreateEvent() failed for port_rx_xpect_flag\n");
    }
    port_ha_t_r[1] = port_tx_ready_flag;
    port_ha_t_r[2] = port_rx_xpect_flag;
    port_ha_t_r[3] = NULL;
   /*
    * Configure the port
    */
    dcb = blank_dcb;
    dcb.DCBlength = sizeof(DCB);
    dcb.BaudRate =  9600;
    dcb.ByteSize =  8;
    dcb.fRtsControl = RTS_CONTROL_DISABLE;  
    dcb.Parity = NOPARITY;
    dcb.StopBits = ONESTOPBIT;
    dcb.fBinary = TRUE;

   /*
    * Set up the DCB
    */
    jcs = (int) SetCommState(port_h,&dcb);
    if(0 == jcs)
    {
        port_startup_error[2] = (int) GetLastError();
    }

   /*
    * Set up the comm mask.
    */ 
    SetCommMask(port_h,0);

   /*
    * Set the port's timeouts (Times in millisec.)
    */  
    port_timeouts.ReadIntervalTimeout = MAXDWORD;
    port_timeouts.ReadTotalTimeoutConstant = 0;
    port_timeouts.ReadTotalTimeoutMultiplier = 0;

    port_timeouts.WriteTotalTimeoutConstant = 0;
    port_timeouts.WriteTotalTimeoutMultiplier = 0;

    jt = SetCommTimeouts(port_h,&port_timeouts);
    if(0 == jt)
    {
         port_startup_error[3] = (int) GetLastError();
    }

    if(0 == (port_startup_error[1]|port_startup_error[2]|port_startup_error[3]))
    {
        printf("Successfully set up port.\n");
    }
    else
    {
        printf("Error in port setup.\n");
    }

   /*
    * Launch the worker thread.
    */
    ui = (unsigned int) _beginthreadex(NULL,128,thread_t_r, (void *) this, 
                                       0,&work_thread_id);
    if(0 == ui)
    {
        printf("Error starting up auxiliary thread: %d\n",errno);
    }
    else
    {
        printf("Launched auxiliary thread\n");
    }
}

com_port_cl::~com_port_cl()
{
     CloseHandle(port_wce_flag);
     CloseHandle(port_rx_xpect_flag);
     CloseHandle(port_tx_ready_flag);
     CloseHandle(port_shutdown_flag);
     CloseHandle(port_h);
}

unsigned int __stdcall thread_t_r(void *arglist)
{
    int          jwce, jwfso, jwfmo, n;
    int          shut_down;
    DWORD        comm_event_word;
    OVERLAPPED   ovlx;
    com_port_cl *port;    

    port = (com_port_cl *) arglist;
    ovlx = blank_ovl;
    ovlx.hEvent = port->port_wce_flag;
    shut_down = 0;
    comm_event_word = 0;

    while(0 == shut_down)
    {
       /*
        * Check for shutdown.
        */
        jwfso = WaitForSingleObject(port->port_shutdown_flag,500);
        if(WAIT_OBJECT_0 == jwfso)
        {
            shut_down = 1;
            printf("Auxiliary thread shutting down.\n");
        }
        else
        {
           /*
            * Wait for an event.
            */
            port->port_ha_t_r[0] = ovlx.hEvent;
            jwce = WaitCommEvent(port->port_h,&comm_event_word,&ovlx);
            if(0 == jwce)
            {
                n = (int) GetLastError();
                if(997 != n)
                {
                    printf("WaitCommEvent() error: %d\n",n);
                }
            }
            jwfmo = WaitForMultipleObjects(3,port->port_ha_t_r,FALSE,5000);
           /*
            * Process the event.
            */
            if((WAIT_OBJECT_0 + 1) == jwfmo)
            {
                printf("Thread detected port->port_tx_ready_flag\n");
                ResetEvent(port->port_tx_ready_flag);
            }
            else if((WAIT_OBJECT_0 + 2) == jwfmo)
            {
                printf("Thread detected port->port_rx_xpect_flag\n");
                ResetEvent(port->port_rx_xpect_flag);
            }
            else if(WAIT_OBJECT_0 == jwfmo)
            {
                printf("Thread detected event on serial port: ");
                if(0 != (comm_event_word&EV_RXCHAR))
                {
                    printf("EV_RXCHAR\n");
                }
                if(0 != (comm_event_word&EV_TXEMPTY))
                {
                    printf("EV_TXEMPTY\n");
                }
                if(0 == comm_event_word)
                {
                    printf("\n");
                }
                ResetEvent(port->port_wce_flag);
            }
            else if(WAIT_TIMEOUT == jwfmo)
            {
                printf("WaitForMultipleObjects() timed out\n");
            }
            else
            {
                printf("Wait abandoned or other situation\n");
            }
        }
    }
    _endthreadex(1);
    return 1;
}

Вот port_class.h:

unsigned int __stdcall thread_t_r(void *);
class com_port_cl
{
public:
    com_port_cl();
   ~com_port_cl();

    HANDLE       port_h;
    HANDLE       port_wce_flag;
    HANDLE       port_shutdown_flag;
    HANDLE       port_tx_ready_flag;
    HANDLE       port_rx_xpect_flag;
    HANDLE       port_ha_t_r[4];                

protected:
    COMMTIMEOUTS port_timeouts;
    DCB          dcb;
    unsigned int ui, work_thread_id;
};

А здесь является основной программой:

#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include <process.h>
#include "port_class.h"

int main()
{
    com_port_cl port;

    if(0 == SetEvent(port.port_rx_xpect_flag))
    {
        printf("SetEvent() error: %d\n",GetLastError());
    }
    Sleep(2500);
    if(0 == SetEvent(port.port_tx_ready_flag))
    {
        printf("SetEvent() error: %d\n",GetLastError());
    }
    Sleep(2500);
    if(0 == SetEvent(port.port_shutdown_flag))
    {
        printf("SetEvent() error: %d\n",GetLastError());
    }
    Sleep(2500);
    printf("\npress any key to exit.\n");
    _getche();   
}

Когда я использую встроенный последовательный порт, я получаю следующий вывод:

Successfully set up port.
Launched auxiliary thread
WaitCommEvent() error: 87
Thread detected port->port_rx_xpect_flag
WaitCommEvent() error: 87
Thread detected port->port_tx_ready_flag
WaitCommEvent() error: 87

press any key to exit.
WaitForMultipleObjects() timed out
Auxiliary thread shutting down.

Когда я переключаюсь на Prolifi c USB- к последовательному порту я получаю следующий вывод:

Successfully set up port.
Launched auxiliary thread
Thread detected event on serial port:
Thread detected event on serial port:
Thread detected event on serial port:
Thread detected event on serial port:
Thread detected event on serial port:
Thread detected event on serial port:
Thread detected event on serial port:
Thread detected event on serial port:
Thread detected event on serial port:
Auxiliary thread shutting down.

press any key to exit.

Вопросы: почему WaitCommEvent () показывает ошибку 87, «недопустимый параметр», когда я использую встроенный последовательный порт? Я не могу найти ничего плохого в любом из аргументов в вызове WaitCommEvent ().

Почему порт USB-последовательный порт Prolifi c видит событие на порту, когда данные не отправляются на или из порта? Почему порт USB-последовательный порт не видит события port_tx_ready_flag и port_rx_xpect_flag?

У меня установлены последние версии драйверов для обоих портов.

1 Ответ

0 голосов
/ 03 марта 2020

Одна и та же инструкция является ответом на оба вопроса:

SetCommMask(port->port_h,EV_RING);

, помещенные в начале процедуры рабочего потока. Установка маски связи на ненулевое значение подавляло ошибки, генерируемые WaitCommEvent(), и подавляло ложное событие, обнаруженное портом Prolifi c USB-to-comm. Установка маски связи на EV_RING ничего не мешает программе, поскольку индикатор вызова не используется.

...