Win32 serial programming Jinbei
I. Basic knowledge
Win32 has a great difference between serial communication with 16-bit serial port. In Win32, serial communication can be implemented in two programming methods, one is called the Windows API function, and its second is to use the ActiveX control. Using the API call, you can clearly grasp the mechanism of serial communication, familiar with various configurations and free flexibility using different flow control for serial communication. The basic knowledge of serial operation is described below.
Open the serial port: Use the CreateFile () function to open the serial port. There are two ways to open the serial port, one is a synchronous mode (nonoverlapped), another asynchronous mode (Overlapped). When using Overlapped, the appropriate method is:
Handle hcomm; hcomm = cretefile (gszport, generic_read | generic_write, 0, 0, open_existing, file_flag_overlapped, 0); if (hcomm == invalid_handle_value) // error opening port; Abort Configure serial port:
1.DCB configuration
The DCB (Device Control Block structure defines the control settings of the serial communication device. Many important settings are set in the DCB structure, there are three ways to initialize DCB.
(1) The initial value of the DCB is obtained by the getcommstate () function, which is:
DCB DCB = {0}; if (! GetCommState (HCOMM, & DCB)) // Error Getting Current DCB SettingSelse // DCB is Ready for USE.
(2) Use the buildcommdcb () function to initialize the DCB structure, the function fills the baud rate, parity type, data bit, and stop bit of DCB. The default value is set for the flow control member function. Its usage is:
DCB DCB; FillMemory (& DCB, SIZEOF (DCB), 0); DCB.dcblength = SizeOf (DCB); if (! Buildcommdcb ("9600, N, 8, 1", & DCB) {// COULDN'T Build The DCB. Usually a problem // with the communications specification string.return false;} else // DCB is Ready for use.
(3) Manually set the initial value of the DCB with the setcommstate () function. Usage is as follows:
DCB DCB; FillMemory (& DCB, SIZEOF (DCB), 0); if (! Getcommstate (hcomm, & dcb)) // Get Current DCB // Error In getcommstatereturn false; // update dcb rate.dcb.baudrate = CBR_9600; / / Set new state.if (! Setcommstate (hcomm, & dcb)) // error in setcommstate. POSSIBLY A Problem with The Communications // Port Handle OR A Problem with The DCB Structure Itself.
When you manually set the DCB value, the meaning of the members of the DCB structure can see MSDN Help.
2. Flow control settings
Hardware flow control: Hardware flow control in serial port communications has two, DTE / DSR mode, and RTS / CTS mode, which is related to the initialization of DCB structure, OutxCTSFlow, FDSRSITIVITY, FRTXDSRFLOW, FDSRSITIVITY, FRTSCONTSROL, FDTRCONTROL in DCB structure The initial value is critical. Different values represent different fluid controls, and they can also set up flow control themselves, but it is recommended to adopt standard popular flow control methods. When using hardware flow control, DTE, DSR, RTS, and CTS logical bits directly affect the data read / write and the buffer control of the transmission and reception data. Software flow control: Special characters XON and XOFF are used as the transmission and reception of serial port data in serial port communication. DCB members associated with this are: Fout, Finx, Xoffchar, Xonchar, Xofflim, and Xonlim. See MSDN Help.
Serial port reading and writing: There are two ways to read and write in serial port: a nonoverlapped and an asynchronous mode (Overlapped). Synchronous mode means that read and write operations must be completed, the function returns, which may cause the program to die, because if there is an error in reading and writing, it will never return, it will be mistaken, and it may always wait. The asynchronous method is much flexible. Once read and write is unsuccessful, the read-write hangs will be returned directly, and the function can be read directly by the GetLastError function, so asynchronous mode is often used.
Reading: The readFile () function is used to complete the read operation. Ready operations in asynchronous methods are:
DWORD dwRead; BOOL fWaitingOnRead = FALSE; OVERLAPPED osReader = {0}; // Create the overlapped event Must be closed before exiting // to avoid a handle leak osReader.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL)..; if (osReader.hEvent == NULL) // Error creating overlapped event;.. abort if (! fWaitingOnRead) {// Issue read operation if (! ReadFile (hComm, lpBuf, READ_BUF_SIZE, & dwRead, & osReader)) {if (GetLastError ()! = Error_io_pending) // r in c c;}}}}}}}}}}}}}}
If the read operation is suspended, you can call the waitforsingleObject () function or waitformuntIlpleObjects () function Waiting for the read operation or timeout, and then call GetoverLappedResult () to get the desired information.
Write action: Similar to the read operation, so that the calling the API function is: WriteFile function.
Serial port status:
(1) Communication event: Use the setcommmask () function to set the mask of the communication event you want to get, and then call the waitcommmevent () function to detect the occurrence of the communication event. The mask that can be set (ie, setcommmask () functions set) can have EV_BREAK, EV_CTS, EV_DSR, EV_ERR, EV_RING, EV_RLSD, EV_RXCHAR, EV_RXFLAG, EV_TXEMPTY. Note: 1 For the setting of the EV_RING flag, Win95 does not return EV_RING events because Win95 does not detect the event. 2 Set EV_RXCHAR, you can detect characters arrival, but when binding this event and readfile () function, you may have an error, causing less reading bytes, and the specific cause is aware of MSDN Help. You can use a loop read method, another better solution is to call the ClearcomMError () function, determine the number of bytes written in the buffer in the buffer in a read operation.
(2) Error handling and communication status: In serial port communication, there may be a lot of errors, using the clearcommorror () function to detect errors and clear the error condition.
(3) MODEM Status: Use setcommmask () can contain many event flags, but these event flags only indicate the voltage change in the serial line. Call the getcommmodemstatus () function can get the real voltage state on the line.
Extended Functions: If the application wants to use its own flow control, you can use the EscapeCommFunction () function to set the level of DTR and RTS lines.
Communication timeout: In communication, the timeout is a very important consideration, because if a timeout control mechanism is not taken during the data receiving process, if the timeout control mechanism is not taken, the I / O thread will be suspended or unlimited. block. The timeout setting in the serial port is divided into two steps, first set the five variables of the COMMTIMEOUTS structure, and then call setcommtimeouts () to set the timeout value. For operations read and written in asynchronous mode, if the operation hangs, asynchronous successfully completed the read and write, waitforSingleObject () or waitformultipleObjects () function will return to Wait_Object_0, and getOverlappedResult () Returns TRUE. In fact, you can also use getcommtimeouts () to get the system initial value.
Turn off the serial port: The program ends or needs to release the serial resource, the serial port should be correctly turned off, and close the serial port is relatively simple, using the API call closehandle () Close the handle of the serial port.
The call method is: CloseHandle (HCOMM);
However, it is worth noting that the read and write serial thread must be exited before turning off the serial port, otherwise it will cause misuse, the general use method is to use the event driver mechanism, start an event, notify the serial read and write thread to force exit, before the thread exits Notify the main thread to turn off the serial port.
Second, achieve 1. Program design ideas
For different applications, although the interface is different, if communication between the serial port and the host is substantially similar, it is nothing more than the serial port transmitting and receiving data, and the data received by the serial port is handed over to the upper software processing display. For the data to be sent to the serial port for forwarding. However, in actual programming, the serial settings are also different due to the communication methods and flow control, which involves the initialization problem of DCB and reading and writing serial ports. The overall idea of the serial communication application design is: First, determine the serial port name, baud rate, parity method, data bit, stop bit to open, pass to the createfile () function to open a specific serial port; In order to protect the initial setting of the system to the serial port, call getcommtimeouts () to get the original timeout setting of the serial port; then initialize the DCB object, call setcommstate () to set the DCB, call setcommtimeouts () Set the serial port timeout control; again, call setupcomm () settings The serial port receives the buffer size of the transmitted data, and the setting of the serial port is basically completed, and then the read-write thread can be started. In general, the read and write of the serial port is completed by the serial read and write thread, which avoids the main program deadlock when reading and writing blockages. For all-duplex serial read and write, the reading thread and write thread should be opened separately; for half-duo and single work, it is recommended to turn on one thread. In the thread, in accordance with a predetermined communication handshake, the serial port state is properly detected, and the serial port data is sent.
2. Implement details
In the case of half-duplex, first complete the necessary serial port configuration, successfully open the serial port, DCB settings, timeout settings; then turn on thread, such as: cwinthread hserialthread = (cwinthread *) AFXBEGINTHREAD (SerialOperation, hwnd, thread_priority_normal); Threads are serialopertons, priority is ordinary.
Serial port programming in full-duplex, different from single work, difference is only to start the double thread, the reading thread and write thread, the reading thread, according to different events or messages, by constantly querying the active data received by the serial port, completed Reading operation; Write thread Sends to the serial port by receiving the transmission data event of the main thread and the data to be transmitted.