wince serial port programming

The operation of the serial port is generally divided into opening the serial port, configuring the serial port, reading and writing the serial port and closing the serial port.

1. Open the serial port CreateFile

Function prototype:

HANDLE CreateFile(LPCTSTR lpFileName, 
DWORD dwDesiredAccess, 
DWORD dwShareMode, 
LPSECURITY_ATTRIBUTES lpSecurityAttributes, 
DWORD dwCreationDistribution, 
DWORD dwFlagsAndAttributes, 
HANDLE hTemplateFile);

参数说明:
lpFileName:指向一个以NULL结束的字符串,该串指定了要创建、打开或截断的文件。
当用createFile打开串口时,这个参数可用”COM1“指定串口1,用”COM2“指定串口2。
dwDesiredAccess:指定对文件访问的类型,可以是读取、写入或二者并列(GENERIC_READ、GENERIC_WRITE)
dwShareMode:指定此文件可以怎样被共享,由于串口不能共享,因此是独占方式,即该参数必须置为0。
共享属性(FILE_SHARE_READ、FILE_SHARE_WRITE)
lpSecurityAttributes:定义安全性属性,一般不用,可设置为NULL;
dwCreationDistribution:定义文件创建方式,对串口操作必须置为OPEN_EXISTING(打开而不是创建);
dwFlagsAndAttributes:定义文件的属性和标志,用于指定该串口是否进行异步操作,
该值为FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,表示使用异步的I/O;
该值为0(FILE_ATTRIBUTE_NORMAL),表示同步I/O操作;
hTemplateFile:指向一个模板文件的句柄。串口无模板可言,因此对串口而言该参数必须置为NULL;
返回值:串口被成功打开时,返回其句柄,否则返回INVALID_HANDLE_VALUE(0XFFFFFFFF)

2. Configure the serial port function

1. _DCB Description
After opening the communication device handle, it is often necessary to perform some initial configuration work on the serial port, which needs to be done through a DCB structure.
The DCB structure contains information such as baud rate, data bits, parity, and stop bits. When querying or configuring the properties of the serial port, the DCB structure must be used as a buffer.
Generally, after opening the serial port with CreateFile, you can call the GetCommState function to obtain the initial configuration of the serial port. To modify the configuration of the serial port, you should first modify the DCB structure, and then call the SetCommState function to set the serial port.
The DCB structure contains the parameter settings of the serial port:

typedef struct _DCB{
	DWORD DCBlength;          
	//DCB结构体大小,即sizeof(_DCB),在调用SetCommState来更新DCB前必须作设置
	DWORD BaudRate;
	//波特率,指定通信设备的传输速率。这个成员可以是实际波特率值或者下面的常量值之一:
	//CBR_110,CBR_300,CBR_600,CBR_1200,CBR_2400,CBR_4800,CBR_9600,CBR_19200,     
    //CBR_38400,CBR_56000, CBR_57600, CBR_115200, CBR_128000, CBR_256000
	DWORD fBinary:1;
	//指定是否允许二进制模式。Win32 API不支持非二进制模式传输,应设置为true
	DWORD fParity:1;
	//指定是否允许奇偶校验。若此成员为1,允许奇偶校验检查,具体采用何种校验根据Parity成员的设置
	DWORD fOutxCtsFlow:1; 
	//是否监控CTS(clear-to-send)信号来做输出流控(指定cts是否用于检测发送控制)。
    //当设置为true时:若CTS为低电平/off,则数据发送将被挂起,直至CTS变为高。 
	DWORD fOutxDsrFlow:1;
	//是否监控DSR (data-set-ready) 信号来做输出流控。
    //当设置为true时:若DSR为低电平,则数据发送将被挂起,直至DSR变为高。DSR的信号一般由DCE来控制
	DWORD fDtrControl:2;
	//DTR (data-terminal-ready)流控,可取值如下: 
    //DTR_CONTROL_DISABLE 打开设备时置DTR信号为低电平,应用程序可通过调用EscapeCommFunction函数来改变DTR线电平状态 
    //DTR_CONTROL_ENABLE 打开设备时置DTR信号为高电平,应用程序可通过调用 EscapeCommFunction     函数来改变DTR线电平状态 
    //DTR_CONTROL_HANDSHAKE 允许DTR信号握手,此时应用程序不能调用EscapeCommFunction函数 
	DWORD fDsrSensitivity:1;
	// 当该值为TRUE时DSR为OFF时接收的字节被忽略
	DWORD fTXContinueOnXoff:1;
	//TRUE时,不管接收端是否Xoff, 本方发送端持续发送。
    //(也就是本方的发送端, 与本方接收端Xon/Xoff是相互独立的)。
	//若为False 时,则当接收端buffer 达到XoffLim时,发送端发送完Xoff字符后,就停止发送。 
	DWORD fOutX:1; 
	//Xon和Xoff流量控制在发送时是否可用。
    //如果为true,当XOFF 值被收到的时候,发送停止;当 XON 值被收到的时候,发送继续。
	DWORD fInX:1; 
	//Xon和Xoff流量控制在接收时是否可用。
    //如果为TRUE, 当输入缓冲区已接收满XoffLim 字节时,发送XOFF字符;
    //当输入缓冲区已经有XonLim 字节的空余容量时,发送XON字符 
	DWORD fErrorChar:1; 
	//该值为TRUE,则用ErrorChar指定的字符代替奇偶校验错误的接收字符。
	DWORD fNull:1;
	//true时,接收时去掉空(0值)字节
	DWORD fRtsControl:2;
	//设置RTS (request-to-send)流控,若为0则缺省取 RTS_CONTROL_HANDSHAKE。可取值及其意义: 
    //RTS_CONTROL_DISABLE 打开设备时置RTS信号为低电平,应用程序可通过调用EscapeCommFunction函数来改变RTS线电平状态 
    //RTS_CONTROL_ENABLE 打开设备时置RTS信号为高电平,应用程序可通过调用EscapeCommFunction函数来改变RTS线电平状态 
    //RTS_CONTROL_HANDSHAKE 允许RTS信号握手,此时应用程序不能调用EscapeCommFunction函数。 
    //当输入缓冲区已经有足够空间接收数据时,驱动程序置RTS为高以允许DCE来发送;反之置RTS为低以阻止DCE发送数据。 
    //RTS_CONTROL_TOGGLE 有字节要发送时RTS变高,当所有缓冲字节已被发送完毕后,RTS变低。
	DWORD fAbortOnError:1;
	//true时,当发生错误时停止读写
	DWORD fDummy2:17;
	//保留,未启用
	WORD wReserved;
	//未启动,必须设置为0
	WORD XonLim;
	//在XON字符发送前接收缓冲区内可允许的最小字节数。
    //当接收Buffer中的字符减少到XonLim规定的字符数, 就发送Xon字符,让对方继续发送。
	WORD XoffLim;
	//在XOFF字符发送前接收缓冲区内可允许的最大字节数。
    //当接收Buffer达到XoffLim规定的字符数, 就发送Xoff字符, 让对方停止发送
	BYTE ByteSize;
	//通信数据位数,4-8
	BYTE Parity;
	//指定奇偶校验方法。此成员可以有下列值:
	//EVENPARITY 偶校验 
	//NOPARITY 无校验
	//MARKPARITY 标记校验 
	//ODDPARITY 奇校验
	BYTE StopBits;
	//指定停止位的位数。此成员可以有下列值:
	//ONESTOPBIT 1位停止位 
	//TWOSTOPBITS 2位停止位
	//ONE5STOPBITS 1.5位停止位
	char XonChar;
	//指定Xon字符
	char XoffChar;
	//指定Xoff字符
	char ErrorChar;
	//指定ErrorChar字符,奇偶校验发生错误时使用的字节
    //(本字符用来代替接收到的奇偶校验发生错误时的值)
	char EofChar;
	//EOF替代字符(当没有使用二进制模式时,用来标识数据结束的字符)
	char EvtChar;
	//事件触发字符,即接收到此字符时会产生一个事件
	WORD wReserved1;
	//保留,未启用
}DCB;

Note:
1) Flow control is divided into hardware flow control and software flow control. Among them: hardware flow control is divided into rts/cts and dtr/dsr, and software flow control is divided into Xon/Xoff.
2) Software flow control Xon/Xoff related parameters: fOutX, fInX, XonLim, XoffLim, XonChar, XoffChar
fOutX: The sender supports Xon/Xoff. Receive Xoff to stop sending, receive Xon to restart
fInX: the receiving end supports Xon/Xoff. Send Xoff when the bytes in the FIFO exceed XoffLim, send Xon when the bytes in the FIFO are less than XonLim XonLim
: When the characters in the receiving Buffer are reduced to the number of characters specified by XonLim, send Xon characters to let the other party continue to send
XoffLim: The receiving Buffer reaches When the number of characters specified by XoffLim, Xoff characters are sent to let the other party stop sending
XonChar: Xon characters
charXoffChar: Xoff characters
fTXContinueOnXoff:; When TRUE, regardless of whether the receiving end is Xoff, the sending end of the local party continues to send. (That is, the sending end of the local party is independent from the receiving end Xon/Xoff of the local party).
If it is False, when the buffer of the receiving end reaches XoffLim, the sending end will stop sending after sending the Xoff character.
3) DTR/DSR hardware flow control:
3.1) When fOutxDsrFlow: true, DSR flow control is supported. When DSR is off, stop sending
3.2) fDtrControl: DTR setting, with the following values:
fDTRControlDTR_CONTROL_Disable: Make DTR off
DTR_CONTROL_Enable: Make DTR on
DTR_CONTROL_HANDSHAKE: DTR hardware flow control
3.3) fDsrSensitivity: true, when DSR is OFF, the receiving end ignores all characters.
4) RTS/CTS hardware flow control:
4.1) fOutxCtsFlow: true, support ctsl flow control, when cts is off, stop sending
4.2) fRtsControl: rts setting, with the following values:
fRTSControlRTS_CONTROL_DISABLE: keep RTS
off Keep on
RTS_CONTROL_HANDSHAKE: RTS hardware flow control
RTS_CONTROL_TOGGLE: 485 communication RTS automatic flow control

2. GetCommState and SetCommState functions
Function prototype:
BOOL GetCommState(HANDLE hFile, LPDCB lpDCB);
BOOL SetCommState(HANDLE hFile, LPDCB lpDCB);
Get/set the device control block of the COM port, so as to obtain related parameters.
Parameter description:
hFile: handle identifying the communication port
lpDCB: pointer to a device control block (DCB structure)

3. SetupComm function
Function prototype:
BOOL SetupComm(HANDLE hFile, DWORD dwInQueue, DWORD dwOutQueue);
set the size of the input and output buffers of the serial port
hFile: the handle of the communication device
dwInQueue: the size of the input buffer (number of bytes)
dwOutQueue: the size of the output buffer (number of bytes)
Note:
In addition to the settings in BCD, the program generally needs to set the size and timeout of the I/O buffer. Windows uses the I/O buffer to temporarily store data input and output through the serial port.
If the communication rate is high, a larger buffer should be set. Call the SetupComm function to set the size of the input and output buffers of the serial port.

4. GetCommTimeouts and SetCommTimeouts functions Function
prototype:
BOOL GetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts);
BOOL SetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts);
Parameter description:
hFile: The handle of the communication device
lpCommTimeouts: Set the timeout time
to query/set the current timeout set, the function populates a COMMTIMEOUTS structure.
The function of timeout is that if the specified number of characters are not read or sent within the specified time, the operation of ReadFile or WriteFile will still end.
There are two kinds of timeouts for reading and writing serial ports: interval timeout and total timeout.
Interval timeout is the maximum delay between two characters when received. The total timeout refers to the maximum time spent in total for read and write operations. Only the total timeout is supported for write operations, while both timeouts are supported for read operations. The timeout for read and write operations can be specified with the COMMTIMEOUTS structure.
The members of the COMMTIMEOUTS structure are all in milliseconds.
The COMMTIMEOUTS structure is defined as

typedef struct _COMMTIMEOUTS {
DWORD ReadIntervalTimeout; //读间隔超时
DWORD ReadTotalTimeoutMultiplier; //读时间系数
DWORD ReadTotalTimeoutConstant; //读时间常量
DWORD WriteTotalTimeoutMultiplier; // 写时间系数
DWORD WriteTotalTimeoutConstant; //写时间常量
} COMMTIMEOUTS,*LPCOMMTIMEOUTS;

Note: The formula
for calculating the total timeout is : total timeout = time coefficient × number of
characters required to be read/written + time constant 10+ReadTotalTimeoutConstant Note: 1) The settings of interval timeout and total timeout are irrelevant 2) The write operation only supports the total timeout, while the read operation supports both timeouts




5. PurgeComm function
Function prototype:
BOOL PurgeComm(HANDLE hFile, DWORD dwFlags);
Clear buffer
Parameter description:
hFile: handle of communication device
dwFlags: operation to be completed, which can be a combination of the following values:
PURGE_TXABORT interrupt all write operations and immediately Returns, even if the write operation has not yet completed.
PURGE_RXABORT aborts all read operations and returns immediately, even if the read operation has not yet completed.
PURGE_TXCLEAR Clear the output buffer
PURGE_RXCLEAR Clear the input buffer

6. EscapeCommFunction function
Prototype of function:
BOOL EscapeCommFunction( HANDLE hFile, DWORD dwFunc);
can set hardware signal ON or OFF, simulate XON or XOFF
Parameter description:
hFile: handle of communication device
dwFunc Event mask:
CLRDTR DTR OFF
CLRRTS RTS OFF
SETDTR STR ON
SERTTS TRS ON
SETXOFF Simulate reception of XOFF characters
SETXON Simulate reception of XON characters
SETBREAK Generate a break during transmission
CLRBREAK Clear break during transmission

7. ClearCommError function
Function prototype:
BOOL ClearCommError(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat);
clear serial port errors, read the current state of the serial port (clear the error flag of the serial port to continue input and output operations), Windows system Use this function to clear hardware communication errors and obtain the current status of communication devices.
Parameter description:
hFile: handle of the communication device
lpErrors: received error code variable type, the error constants are as follows:
CE_BREAK: break signal detected
CE_DNS: Windows95 dedicated, unselected parallel port
CE_FRAME: frame error
CW_IOE: general I/O error , often accompanied by a more detailed error flag
CE_MODE: The requested mode is not supported
CE_OVERRUN: The next character will be lost if the buffer exceeds the limit
CE_RXOVER: The receive buffer exceeds the limit
CE_RXPARITY: Parity error
CE_TXFULL: The send buffer is full
CE_DNS: None Select the parallel device
CE_PTO: the parallel device has timed out
CE_OOP: the parallel device is out of paper
lpStat: the pointer of the communication status buffer, pointing to a COMSTAT structure, which returns the status information of the serial port.
The COMSTAT structure contains information about the serial port, and the structure is defined as follows:

typedef struct _COMSTAT { // cst 
		DWORD fCtsHold : 1; 
        // Tx waiting for CTS signal(为真时,等待cts信号开启传输)
		DWORD fDsrHold : 1; 
        // Tx waiting for DSR signal (为真时,等待dsr信号时开启传输)
		DWORD fRlsdHold : 1; 
        // Tx waiting for RLSD signal 
		DWORD fXoffHold : 1; 
        // Tx waiting, XOFF char rec’’d (为真时,等待接收到xoff时开始传输)
		DWORD fXoffSent : 1; 
        // Tx waiting, XOFF char sent 
		DWORD fEof : 1; 
        // EOF character sent (为真时,eof字符可以被收到)
		DWORD fTxim : 1; 
        // character waiting for Tx 
		DWORD fReserved : 25; 
        // reserved (保留)
		DWORD cbInQue; 
        // bytes in input buffer //串口接收缓冲区的字节数,它们还没有来得及被ReadFile操作读走
		DWORD cbOutQue; 
        // bytes in output buffer  //串口发送缓冲区的字节数
}

8. GetCommMask and SetCommMask functions
Function prototype:
BOOL GetCommMask(HANDLE hFile, LPDWORD lpEvtMask);
BOOL SetCommMask(HANDLE hFile, DWORD dwEvtMask);
Set/get monitoring event
Parameter description:
hFile: handle of communication device
EvtMask: event mask, identification Communication events to be monitored. If this parameter is set to 0, it means that all events are prohibited. If not 0, the mask can be as follows:

EV_BREAK 检测到输入为止
EV_CTS CTS(清除发送)信号改变状态
EV_DSR DSR(数据设置就绪)信号改变状态
EV_ERR 发生了线路状态错误.
CE_FRAME(帧错误)
CE_OVERRUN(接收缓冲区超限)
CE_RXPARITY(奇偶校验错误)
EV_RING 检测到振铃
EV_RLSD RLSD(接收线路信号检测)信号改变状态
EV_EXCHAR 接收到一个字符,并放入输入缓冲区
EV_RXFLAG 接收到事件字符(DCB成员的EvtChar成员),度放入输入缓冲区
EV_TXEMPTY 输出缓冲区中最后一个字符发送出去
//在用SetCommMask指定了有用的事件后,应用程序可调用WaitCommEvent()来等待事件发生.

9. WaitCommEvent function
Function prototype:
BOOL WaitCommEvent(HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped);
Waiting for the monitored event to occur
Parameter description:
hFile: handle of the communication device
lpEvtMask: points to a 32-bit variable, receives the event mask, and identifies what happened
lpOverlapped: points to an OVERLAPPED structure, if the FILE_FLAG_OVERLAPPED flag is specified when opening the communication device represented by hFile, this parameter is ignored . If asynchronous operation is not required, this parameter does not need to be set.

3. Serial port read and write functions
1. Read
function Function prototype:
BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped);
read serial port data
Parameter description:
hFile: serial port handle
lpBuffer: read data storage address, that is, the read-in data will be stored in a
piece of memory area with the value of the pointer as the first
address Number of sections
lpOverlapped: In overlapping (asynchronous) operation, this parameter points to an OVERLAPPED structure; in synchronous operation, this parameter is NULL.

2. Write function
Function prototype:
BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped);
Write serial port
function Function description:
hFile: serial port handle
lpBuffer: nNumberOfBytesTo with the value of the pointer as the first address Bytes of data will be written into the send data buffer of the serial port.
nNumberOfBytesToWrite: the number of bytes of the data to be written
lpNumberOfBytesWritten: points to a DWORD value, which returns the actual number of bytes written
lpOverlapped: in overlapping (asynchronous) operations, this parameter points to an OVERLAPPED structure is NULL.

OVERLAPPED用于记录了当前正在操作的文件一些相关信息,OVERLAPPED结构说明:
typedef struct _OVERLAPPED {
	DWORD Internal;
    //保存已处理的I/O请求的错误码/状态码
	DWORD InternalHigh;
    //当异步I/O请求完成的时候,这个成员用来保存已传输的字节数。
	DWORD Offset;
    //该文件的位置是从文件起始处的字节偏移量。调用进程设置这个成员之前调用ReadFile或WriteFile函数。当读取或写入命名管道和通信设备时这个成员被忽略设为零。
	DWORD OffsetHigh;
    //指定文件传送的 字节 偏移量的高位字。当读取或写入命名管道和通信设备时这个成员被忽略设为零。
	HANDLE hEvent;
    //在转移完成时处理一个事件设置为有信号状态。
    //调用进程集这个成员在调用ReadFile、 WriteFile、TransactNamedPipe、 ConnectNamedPipe函数之前。
} OVERLAPPED;

3. GetOverlappedResult function
Function prototype:
BOOL WINAPI GetOverlappedResult(HANDLE hFile, LPOVERLAPPED lpOverlapped, LPDWORD lpNumberOfBytesTransferred, BOOL bWait);
Obtain the status/result of the overlapping operation according to the OVERLAPPED structure, and use it to judge whether the asynchronous operation is completed, it is by judging the OVERLAPPED structure Whether hEvent in is set or not
Parameter description:
hFile: handle of the serial port
lpOverlapped: points to the OVERLAPPED structure specified at the beginning of the overlapping operation
lpNumberOfBytesTransferred: points to a 32-bit variable whose value returns the number of bytes transferred by the actual read and write operation
bWait : This parameter is used to specify whether the function waits until the end of the overlapping operation. If this parameter is TRUE, the function will not return until the operation ends;
if this parameter is FALSE, the function returns directly, and if the operation is not completed at this time, ERROR_IO_INCOMPLETE will be returned by calling the GetLastError() function.

Note:
1) The ReadFile function completes the operation as long as it reads the specified number of characters in the serial port input buffer; while the WriteFile function not only copies the specified number of characters into the output buffer, but also waits for these characters to be read from the serial port. The operation is not completed until it is sent out.
2) Both functions return TRUE if successful. When ReadFile and WriteFile return FALSE, it does not necessarily mean that the operation failed, and the thread should call the GetLastError function to analyze the returned results.
For example, if the function returns before the operation is completed during the overlapping operation, then the function returns FALSE, and the GetLastError function returns ERROR_IO_PENDING, which means that the overlapping operation has not been completed.
3) When using ReadFile and WriteFile overlapping operations, the thread needs to create an OVERLAPPED structure for use by these two functions. The thread obtains the current operating state through the OVERLAPPED structure, and the most important member of the structure is hEvent.
hEvent is a read and write event. When the serial port uses asynchronous communication, the operation may not be completed when the function returns, and the program can check whether the reading and writing is completed by checking this event.
When the ReadFile and WriteFile functions are called, the member will be automatically set to the unsignaled state; when the overlapping operation is completed, the member variable will be automatically set to the signaled state.

Guess you like

Origin blog.csdn.net/qq_33782617/article/details/122388095