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

来源:互联网 发布:vb通用对话框 编辑:程序博客网 时间:2024/05/01 08:10
本章我们将以工业控制和嵌入式系统中运用极为广泛的串口通信为例讲述多线程的典型应用。而网络通信也是多线程应用最广泛的领域之一,所以本章的最后一节也将对多线程网络通信进行简短的描述。1.串口通信在工业控制系统中,工控机(一般都基于PC Windows平台)经常需要与单片机通过串口进行通信。因此,操作和使用PC的串口成为大多数单片机、嵌入式系统领域工程师必须具备的能力。串口的使用需要通过三个步骤来完成的:(1) 打开通信端口;(2) 初始化串口,设置波特率、数据位、停止位、奇偶校验等参数。为了给读者一个直观的印象,下图从Windows的"控制面板->系统->设备管理器->通信端口(COM1)"打开COM的设置窗口:

(3) 读写串口。在WIN32平台下,对通信端口进行操作跟基本的文件操作一样。创建/打开COM资源下列函数如果调用成功,则返回一个标识通信端口的句柄,否则返回-1: HADLE CreateFile(PCTSTR lpFileName, //通信端口名,如"COM1"WORD dwDesiredAccess, //对资源的访问类型WORD dwShareMode, //指定共享模式,COM不能共享,该参数为0PSECURITY_ATTRIBUTES lpSecurityAttributes,//安全描述符指针,可为NULLWORD dwCreationDisposition, //创建方式WORD dwFlagsAndAttributes, //文件属性,可为NULLHANDLE 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{// dcbDWORD DCBlength; // sizeof(DCB)DWORD BaudRate; // current baud rateDWORD fBinary: 1; // binary mode, no EOF checkDWORD fParity: 1; // enable parity checkingDWORD fOutxCtsFlow: 1; // CTS output flow controlDWORD fOutxDsrFlow: 1; // DSR output flow controlDWORD fDtrControl: 2; // DTR flow control typeDWORD fDsrSensitivity: 1; // DSR sensitivityDWORD fTXContinueOnXoff: 1; // XOFF continues TxDWORD fOutX: 1; // XON/XOFF out flow controlDWORD fInX: 1; // XON/XOFF in flow controlDWORD fErrorChar: 1; // enable error replacementDWORD fNull: 1; // enable null strippingDWORD fRtsControl: 2; // RTS flow controlDWORD fAbortOnError: 1; // abort reads/writes on errorDWORD fDummy2: 17; // reservedWORD wReserved; // not currently usedWORD XonLim; // transmit XON thresholdWORD XoffLim; // transmit XOFF thresholdBYTE ByteSize; // number of bits/byte, 4-8BYTE Parity; // 0-4=no,odd,even,mark,spaceBYTE StopBits; // 0,1,2 = 1, 1.5, 2char XonChar; // Tx and Rx XON characterchar XoffChar; // Tx and Rx XOFF characterchar ErrorChar; // error replacement characterchar EofChar; // end of input characterchar EvtChar; // received event characterWORD wReserved1; // reserved; do not use} DCB; 读写串口在读写串口之前,还要用PurgeComm()函数清空缓冲区,并用SetCommMask ()函数设置事件掩模来监视指定通信端口上的事件,其原型为: BOOL SetCommMask(HANDLE hFile, //标识通信端口的句柄DWORD dwEvtMask //能够使能的通信事件); 串口上可能发生的事件如下表所示: 值 事件描述 EV_BREAK A break was detected on input. EV_CTS The CTS (clear-to-send) signal changed state. EV_DSR The DSR(data-set-ready) signal changed state. EV_ERR A line-status error occurred. Line-status errors are CE_FRAME, CE_OVERRUN, and CE_RXPARITY. EV_RING A ring indicator was detected. EV_RLSD The RLSD (receive-line-signal-detect) signal changed state. EV_RXCHAR A character was received and placed in the input buffer. EV_RXFLAG The 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_TXEMPTY The 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结构);
原创粉丝点击