串口通讯
msdn 串口总体描述
book: C Programmer’s Guide to Serial Communications
Nonoverlapped I/O vs Overlapped I/O
Overlapped I/O 是异步的,Nonoverlapped I/O 是同步的,
同步操作,调用线程会被阻塞,通常使用多个线程来操作,但是如果一个线程中 readFile 阻塞,那么另一个线程的 writeFile 也会被阻塞。
异步,同步接口的选择依据主要是可移植性。
Overlapped I/O
更具有灵活性和效率,允许多线程在阻塞等待时同时处理不同的I/O操作,允许单线程在阻塞时在后台执行多个请求
等待有两种方式:
- 等待 hEvent member of the OVERLAPPED structure 使用 WaitForSingleObject
- wait for the call to the GetOverlappedResult function
Serial Status
两种方式:
- 使用事件 mask
- 使用 polling (低效,不推荐)
SetCommMask 订阅事件通知
WaitCommEvent 等待事件发生,同步等待时,会阻塞
async:
If SetCommMask sets a new event mask, any pending WaitCommEvent will complete successfully, and the event mask produced by the operation is NULL.
sync:
WaitCommEvent will be blocked until an event occurs. If another thread calls SetCommMask to set a new event mask, that thread will be blocked on the call to SetCommMask. The reason is that the original call to WaitCommEvent in the first thread is still executing. The call to SetCommMask blocks the thread until the WaitCommEvent function returns in the first thread. This side effect is universal for ports open for nonoverlapped I/O. If a thread is blocked on any communications function and another thread calls a communications function, the second thread is blocked until the communications function returns in the first thread.
Error Handling and Communications Status
EV_ERR 用来处理错误,同时可以查看缓冲区未读取的字节数
Modem Status (a.k.a. Line Status)
The call to SetCommMask may include the flags EV_CTS, EV_DSR, EV_RING, and EV_RLSD. These flags indicate changes in the voltage on the lines of the serial port. There is no indication of the actual status of these lines, just that a change occurred. The GetCommModemStatus function retrieves the actual state of these status lines by returning a bit mask indicating a 0 for low or no voltage and 1 for high voltage for each of the lines.
Please note that the term RLSD (Receive Line Signal Detect) is commonly referred to as the CD (Carrier Detect) line.
Changes in these lines may also cause a flow-control event. The ClearCommError function reports whether transmission is suspended because of flow control. If necessary, a thread may call ClearCommError to detect whether the event is the cause of a flow-control action. Flow control is covered in the “Flow Control” section later in this article.
Here is some code that demonstrates how to call GetCommModemStatus:
DWORD dwModemStatus; |
Extended Functions
The driver will automatically change the state of control lines as necessary. Generally speaking, changing status lines is under the control of a driver. If a device uses communications port control lines in a manner different from RS-232 standards, the standard serial communications driver will not work to control the device. If the standard serial communications driver will not control the device, a custom device driver is necessary.
There are occasions when standard control lines are under the control of the application instead of the serial communications driver. For instance, an application may wish to implement its own flow control. The application would be responsible for changing the status of the RTS and DTR lines. EscapeCommFunction directs a communications driver to perform such extended operations. EscapeCommFunction can make the driver perform some other function, such as setting or clearing a BREAK condition.
Flow Control
Flow control in serial communications provides a mechanism for suspending communications while one of the devices is busy or for some reason cannot do any communication. There are traditionally two types of flow control: hardware and software.
A common problem with serial communications is write operations that actually do not write the data to the device. Often, the problem lies in flow control being used when the program did not specify it. A close examination of the DCB structure reveals that one or more of the following members may be TRUE: fOutxCtsFlow, fOutxDsrFlow, or fOutX. Another mechanism to reveal that flow control is enabled is to call ClearCommError and examine the COMSTAT structure. It will reveal when transmission is suspended because of flow control.
Before discussing the types of flow control, a good understanding of some terms is in order. Serial communications takes place between two devices. Traditionally, there is a PC and a modem or printer. The PC is labeled the Data Terminal Equipment (DTE). The DTE is sometimes called the host. The modem, printer, or other peripheral equipment is identified as the Data Communications Equipment (DCE). The DCE is sometimes referred to as the device.
Hardware flow control
Hardware flow control uses voltage signals on control lines of the serial cable to control whether sending or receiving is enabled. The DTE and the DCE must agree on the types of flow control used for a communications session. Setting the DCB structure to enable flow control just configures the DTE. The DCE also needs configuration to make certain the DTE and DCE use the same type of flow control. There is no mechanism provided by Windows to set the flow control of the DCE. DIP switches on the device, or commands sent to it typically establish its configuration. The following table describes the control lines, the direction of the flow control, and the line’s effect on the DTE and DCE.
The need for flow control is easy to recognize when the CE_RXOVER error occurs. This error indicates an overflow of the receive buffer and data loss. If data arrives at the port faster than it is read, CE_RXOVER can occur. Increasing the input buffer size may cause the error to occur less frequently, but it does not completely solve the problem. Input flow control is necessary to completely alleviate this problem. When the driver detects that the input buffer is nearly full, it will lower the input flow-control lines. This should cause the DCE to stop transmitting, which gives the DTE enough time to read the data from the input buffer. When the input buffer has more room available, the voltage on flow-control lines is set high, and the DCE resumes sending data.
A similar error is CE_OVERRUN. This error occurs when new data arrives before the communications hardware and serial communications driver completely receives old data. This can occur when the transmission speed is too high for the type of communications hardware or CPU. This can also occur when the operating system is not free to service the communications hardware. The only way to alleviate this problem is to apply some combination of decreasing the transmission speed, replacing the communications hardware, and increasing the CPU speed. Sometimes third-party hardware drivers that are not very efficient with CPU resources cause this error. Flow control cannot completely solve the problems that cause the CE_OVERRUN error, although it may help to reduce the frequency of the error.
Software flow control
Software flow control uses data in the communications stream to control the transmission and reception of data. Because software flow control uses two special characters, XOFF and XON, binary transfers cannot use software flow control; the XON or XOFF character may appear in the binary data and would interfere with data transfer. Software flow control befits text-based communications or data being transferred that does not contain the XON and XOFF characters.
In order to enable software flow control, the fOutX and fInX members of the DCB must be set to TRUE. The fOutX member controls output flow control. The fInX member controls input flow control.
One thing to note is that the DCB allows the program to dynamically assign the values the system recognizes as flow-control characters. The XoffChar member of the DCB dictates the XOFF character for both input and output flow control. The XonChar member of the DCB similarly dictates the XON character.
For input flow control, the XoffLim member of the DCB specifies the minimum amount of free space allowed in the input buffer before the XOFF character is sent. If the amount of free space in the input buffer drops below this amount, then the XOFF character is sent. For input flow control, the XonLim member of the DCB specifies the minimum number of bytes allowed in the input buffer before the XON character is sent. If the amount of data in the input buffer drops below this value, then the XON character is sent.
If software flow control is enabled for input control, then the fTXContinueOnXoff member of the DCB takes effect. The fTXContinueOnXoff member controls whether transmission is suspended after the XOFF character is automatically sent by the system. If fTXContinueOnXoff is TRUE, then transmission continues after the XOFF is sent when the receive buffer is full. If fTXContinueOnXoff is FALSE, then transmission is suspended until the system automatically sends the XON character. DCE devices using software flow control will suspend their sending after the XOFF character is received. Some equipment will resume sending when the XON character is sent by the DTE. On the other hand, some DCE devices will resume sending after any character arrives. The fTXContinueOnXoff member should be set to FALSE when communicating with a DCE device that resumes sending after any character arrives. If the DTE continued transmission after it automatically sent the XOFF, the resumption of transmission would cause the DCE to continue sending, defeating the XOFF.
There is no mechanism available in the Windows API to cause the DTE to behave the same way as these devices. The DCB structure contains no members for specifying suspended transmission to resume when any character is received. The XON character is the only character that causes transmission to resume.
One other interesting note about software flow control is that reception of XON and XOFF characters causes pending read operations to complete with zero bytes read. The XON and XOFF characters cannot be read by the application, since they are not placed in the input buffer.
A lot of programs on the market, including the Terminal program that comes with Windows, give the user three choices for flow control: Hardware, Software, or None. The Windows operating system itself does not limit an application in this way. The settings of the DCB allow for Software and Hardware flow control simultaneously. In fact, it is possible to separately configure each member of the DCB that affects flow control, which allows for several different flow-control configurations. The limits placed on flow-control choices are there for ease-of-use reasons to reduce confusion for end users. The limits placed on flow-control choices may also be because devices used for communications may not support all types of flow control.
Communications Time-outs
// 下面代码是设置 readFile 返回 0 字节,立即返回,使用事件通知的方式必须设置 |
Reading and Writing
数据终端准备(DTR)
请求发送(RTS)
DCD :载波检测。主要用于Modem通知计算机其处于在线状态,即Modem检测到拨号音, 处于在线状态。
RXD :此引脚用于接收外部设备送来的数据;在你使用Modem时,你会发现RXD指示灯在闪烁,说明RXD引脚上有数据 进入。
TXD :此引脚将计算机的数据发送给外部设备;在你使用Modem时,你会发现TXD指示灯在闪烁,说明计算机正在通过TXD引脚发送数据。
DTR :(Data terminal ready)数据终端就绪;当此引脚高电平时,通知Modem可以进行数据传输,计算机已经准备好。
GND :信号地;此位不做过多解释。
DSR :(Data set ready) 数据设备就绪;此引脚高电平时,通知计算机Modem已经准备好,可以进行数据通讯了。
RTS :(Request to send) 请求发送;此脚有计算机来控制,用以通知Modem马上传送数据至计算机;否则,Modem将收到的数据暂时放入缓冲区中。
CTS :(clear to send) 清除发送;此脚由Modem控制,用以通知计算机将欲传的数据送至Modem。
RI :Modem通知计算机有呼叫进来,是否接听呼叫由计算机决定
串口通信握手协议–XON/XOFF方法
PC机中常用的两种流控制是硬件流控制(包括RTS/CTS、DTR/CTS等)和软件流控制XON/XOFF(继续/停止)
char XonChar; //请求发送方继续发送时的字符 0x11
char XoffChar; //请求发送方停止发送时的字符 0x13
WORD XonLim; //指定在XON字符发送之前接收缓冲区中空缓冲区可允许的最小字节数
WORD XoffLim; //指定在XOFF字符发送这前接收缓冲区中数据缓冲可允许的最小字节数
on,off 都是 接收方->发送方的
RTS_CONTROL_ENABLE
fRtsControl
异步通讯
设置监控事件
SetCommMask
Mask: RXCHAR CTS DSR RLSD BREAK ERR RING
等待事件发生,如果没设置 FILE_FLAG_OVERLAPPED 则阻塞。
WaitCommEvent
ClearCommError
获取尚未读取的字节,
COMSTAT
DWORD cbInQue; // 尚未读取的字节
BOOL ReadFile(
HANDLE hFile,
LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead,
LPOVERLAPPED lpOverlapped
);
串口的超时设置
COMMTIMEOUTS结构如下: |
ReadIntervalTimeout: MAXDWORD 并且 ReadTotalTimeoutConstant and ReadTotalTimeoutMultiplier 都是 0, 则携带已接收数据立即返回,即使没有数据也返回。
COMMTIMEOUTS comTimeOut; |