深入浅出Win32多线程程序设计之综合实例

来源:网络

点击:1801

A+ A-

所属频道:新闻中心

关键词: Win32,多线程程序设计,多线程

    本章我们将以工业控制和嵌入式系统中运用极为广泛的串口通信为例讲述多线程的典型应用。

    而网络通信也是多线程应用最广泛的领域之一,所以本章的最后一节也将对多线程网络通信进行简短的描述。

    1.串口通信

    在工业控制系统中,工控机(一般都基于PC Windows平台)经常需要与单片机通过串口进行通信。因此,操作和使用PC的串口成为大多数单片机、嵌入式系统领域工程师必须具备的能力。

    串口的使用需要通过三个步骤来完成的:

    (1) 打开通信端口;

    (2) 初始化串口,设置波特率、数据位、停止位、奇偶校验等参数。为了给读者一个直观的印象,下图从Windows的"控制面板->系统->设备管理器->通信端口(COM1)"打开COM的设置窗口:

     



    (3) 读写串口。

    在WIN32平台下,对通信端口进行操作跟基本的文件操作一样。

    创建/打开COM资源

    下列函数如果调用成功,则返回一个标识通信端口的句柄,否则返回-1:
     

    HADLE CreateFile(PCTSTR lpFileName, //通信端口名,如"COM1"
               WORD dwDesiredAccess, //对资源的访问类型
               WORD dwShareMode, //指定共享模式,COM不能共享,该参数为0
               PSECURITY_ATTRIBUTES lpSecurityAttributes,
               //安全描述符指针,可为NULL
               WORD dwCreationDisposition, //创建方式
               WORD dwFlagsAndAttributes, //文件属性,可为NULL
               HANDLE hTemplateFile //模板文件句柄,置为NULL
               );


    获得/设置COM属性

    下列函数可以获得COM口的设备控制块,从而获得相关参数:
     

    BOOL WINAPI GetCommState(
               HANDLE hFile, //标识通信端口的句柄
               LPDCB lpDCB //指向一个设备控制块(DCB结构)的指针
               );


    如果要调整通信端口的参数,则需要重新配置设备控制块,再用WIN32 API SetCommState()函数进行设置:
     

    BOOL SetCommState(
               HANDLE hFile, //标识通信端口的句柄
               LPDCB lpDCB //指向一个设备控制块(DCB结构)的指针
               );


    DCB结构包含了串口的各项参数设置,如下:
     

    typedef struct _DCB
               {
               // dcb
               DWORD DCBlength; // sizeof(DCB)
               DWORD BaudRate; // current baud rate
               DWORD fBinary: 1; // binary mode, no EOF check
               DWORD fParity: 1; // enable parity checking
               DWORD fOutxCtsFlow: 1; // CTS output flow control
               DWORD fOutxDsrFlow: 1; // DSR output flow control
               DWORD fDtrControl: 2; // DTR flow control type
               DWORD fDsrSensitivity: 1; // DSR sensitivity
               DWORD fTXContinueOnXoff: 1; // XOFF continues Tx
               DWORD fOutX: 1; // XON/XOFF out flow control
               DWORD fInX: 1; // XON/XOFF in flow control
               DWORD fErrorChar: 1; // enable error replacement
               DWORD fNull: 1; // enable null stripping
               DWORD fRtsControl: 2; // RTS flow control
               DWORD fAbortOnError: 1; // abort reads/writes on error
               DWORD fDummy2: 17; // reserved
               WORD wReserved; // not currently used
               WORD XonLim; // transmit XON threshold
               WORD XoffLim; // transmit XOFF threshold
               BYTE ByteSize; // number of bits/byte, 4-8
               BYTE Parity; // 0-4=no,odd,even,mark,space
               BYTE StopBits; // 0,1,2 = 1, 1.5, 2
               char XonChar; // Tx and Rx XON character
               char XoffChar; // Tx and Rx XOFF character
               char ErrorChar; // error replacement character
               char EofChar; // end of input character
               char EvtChar; // received event character
               WORD wReserved1; // reserved; do not use
               } DCB;

    读写串口

    在读写串口之前,还要用PurgeComm()函数清空缓冲区,并用SetCommMask ()函数设置事件掩模来监视指定通信端口上的事件,其原型为:
     

    BOOL SetCommMask(
               HANDLE hFile, //标识通信端口的句柄
               DWORD dwEvtMask //能够使能的通信事件
               );


    串口上可能发生的事件如下表所示:

    事件描述
    EV_BREAKA break was detected on input.
    EV_CTSThe CTS (clear-to-send) signal changed state.
    EV_DSRThe DSR(data-set-ready) signal changed state.
    EV_ERRA line-status error occurred. Line-status errors are CE_FRAME, CE_OVERRUN, and CE_RXPARITY.
    EV_RINGA ring indicator was detected.
    EV_RLSDThe RLSD (receive-line-signal-detect) signal changed state.
    EV_RXCHARA character was received and placed in the input buffer.
    EV_RXFLAGThe event character was received and placed in the input buffer. The event character is specified in the device''''s DCB structure, which is applied to a serial port by using the SetCommState function.
    EV_TXEMPTYThe last character in the output buffer was sent.


    在设置好事件掩模后,我们就可以利用WaitCommEvent()函数来等待串口上发生事件,其函数原型为:

    BOOL WaitCommEvent(
               HANDLE hFile, //标识通信端口的句柄
               LPDWORD lpEvtMask, //指向存放事件标识变量的指针
               LPOVERLAPPED lpOverlapped, // 指向overlapped结构
               );


    我们可以在发生事件后,根据相应的事件类型,进行串口的读写操作:

    BOOL ReadFile(HANDLE hFile, //标识通信端口的句柄
               LPVOID lpBuffer, //输入数据Buffer指针
               DWORD nNumberOfBytesToRead, // 需要读取的字节数
               LPDWORD lpNumberOfBytesRead, //实际读取的字节数指针
               LPOVERLAPPED lpOverlapped //指向overlapped结构
               );
               BOOL WriteFile(HANDLE hFile, //标识通信端口的句柄
               LPCVOID lpBuffer, //输出数据Buffer指针
               DWORD nNumberOfBytesToWrite, //需要写的字节数
               LPDWORD lpNumberOfBytesWritten, //实际写入的字节数指针
               LPOVERLAPPED lpOverlapped //指向overlapped结构
               );

     

     

     

    (审核编辑: 智汇小新)

    声明:除特别说明之外,新闻内容及图片均来自网络及各大主流媒体。版权归原作者所有。如认为内容侵权,请联系我们删除。