Wang Ying, Chinese Academy of Sciences
---- Abstract: This paper introduces the implementation mechanism of serial communication under the Windows platform, discusses three methods for designing serial communication programs in Visual C , and implements reception monitoring of temperature data according to different conditions .
---- In laboratory and industrial applications, the serial port is a commonly used data transmission channel between computer and external serial devices. Since serial communication is convenient, it is widely used. Flexible programming control for serial port is what we need according to different conditions.
---- In the optical lens coating process, multi-channel temperature data acquisition control is performed by a single chip microcomputer. The result of collecting the host in a serial mode, and sends a sampling data to the host every 10s, and the host sends related control commands to the single-chip microcomputer. Serial data reception, processing, recording, display, real-time drawing curve. The serial communication program development environment is VC 6.0.
---- Windows serial communication
---- Different from the serial communication program under DOS, Windows does not advocate the application directly control hardware, but through the device driver provided by the Windows operating system to perform data delivery. The serial port is processed as a file in Win 32, not directly to the port, for serial communication, Win 32 provides the corresponding file I / O function and communication function, by understanding these functions, A communication program that meets different needs can be prepared. The structure related to communication devices has 7 CommConfig, CommProp, CommTimeouts, Comst, DCB, ModemDevcaps, ModemSettings, with a total of 26 Windows API functions, and detail refer to the MSDN help file. The following will be combined with examples, three methods for realizing serial communication will be given.
---- Three ways to achieve serial communication
---- Method 1: Use the serial communication controls provided by VC First, create a communication control in the dialog box, if the control is missing in the Control toolbar, can pass the menu Project -> Add to Project -> Components and Control insert, then pull the control from the toolbox to the dialog box. At this point, you only need to care about the interface of the API function supplied to the Windows Communication Driver. In other words, only the properties and events of the MSCOMM control are required to be set and monitored.
---- In ClassWizard, define member objects for newly created communication controls. You can set the serial attributes through this object. The MSCOMM control has a total of 27 attributes. Here only several common properties:
---- CommPort Settings and returns the communication port number, default is COM1.
--- settings Set and return the baud rate, parity, data bit, stop bit in the form of a string.
---- Portopen settings and returns the status of the communication port, or you can turn the port.
---- INPUT returns and deletes characters from the received buffer.
---- OUTPUT writes a string to the send buffer.
---- Inputlen Sets the number of characters read in the input, the default value is 0, indicating that the full content in the receiving buffer is read.
---- InBufferCount Returns the number of characters received in the receiving buffer, set it 0 to clear the reception buffer.
---- InputMode Defines the way the input property is obtained (0: text mode; 1: binary).
---- Rthreshold and Sthreshold properties, indicating that the number of characters that can be received in the receiving buffer or send buffer before the ONCOMM event occurs.
---- The following is an example of initializing the serial port by setting the control attribute:
Bool csampledlg :: portopen ()
{
Bool m_opet;
......
m_serial.setcommport (2); // Specify the serial number
m_serial.setSettings ("4800, N, 8, 1"); // Communication parameter setting
m_serial.setinbuffersize (1024); / / Specify the reception buffer size
m_serial.setinbuffercount (0); / / Clear receiving buffer
m_serial.inputmode (1); // Set data acquisition method
m_serial.setInputlen (0); // Setting the reading method
m_pened = m_serail.setportopen (1); // Open the specified serial port
Return M_Opened;
}
---- After opening the desired serial port, you need to consider the timing of serial port communication. During receiving or sending data, you may need to monitor and respond to some events and errors, so event-driven is a very effective way to handle serial port interactions. Use the OnComm event and the commevent attribute to capture and check the value of the communication event and the error. When a communication event or error occurs, the ONCOMM event will be triggered. The value of the Commevent property will be changed, the application checks the commevent attribute value and makes the corresponding reaction. Add an ONCOMM message processing function to the CMSCOMM control in the program:
Void csampledlg :: oncomm ()
{
......
Switch (m_serial.getcommEvent ())
{
Case 2:
// Serial port data reception, processing;
}
}
---- Method 2: Realize custom serial communication class in a single thread
---- Control is easy to use, but since it must be used in the dialog box, some of the use of the controls need to be communicated in the thread, the use of the control is stretched. At this point, if you can customize the flexible serial port communication class in different needs, you will make up for the insufficient control, and here will be described with how to create a custom communication class in a single thread.
---- This communication class CSIMPLECOMM needs to manually join the header file and the source file, the base class is COBJECT, and the roughly established steps are as follows:
---- (1) Open the serial port and get the serial resource handle
---- Communication program Specifies the serial port device and related operational properties from createfile. Returns a handle, the handle will be used for subsequent communication operations and run through the entire communication process. Several value parameter settings in the createfile () function: serial port sharing mode should be 0, the serial port is a non-shared device; the creation method must be open_existing, that is, open the existing serial port. For the dwflagandattribute parameter, the value that makes sense for the serial port is file_flag_overlapped, which indicates that the serial port uses asynchronous communication mode to overlap operation; if the value is null, it is synchronous communication mode, in synchronization mode, the application will always control the program flow Until the end of the program, if the communication failure is encountered, it will cause the application's permanent wait, so it is generally used to use asynchronous communication.
---- (2) Serial port setting
---- The serial port is opened, its attribute is set to the default value, according to the specific needs, read the current serial device control block DCB (DCB) settings by calling GetCommState (HCOMM, & DCB), and modifies through SetCommstate (HCOMM, & DCB) Write it. Pay attention to the timeout control settings for asynchronous read and write, set the setcommtimeouts (hcomm, & timeouts) to write the result. The following is the serial initialization member function in the temperature monitor: BOOL CSIMPLECOMM :: Open ()
{
DCB DCB;
m_hidcomdev = CreateFile ("COM2",
Generic_read | generic_write,
0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_
Normal | file_flag_ove rlapped, null);
/ / Open the serial port, asynchronously
IF (M_HIDCOMDEV == Null) Return (false);
DCB.DCBLENGTH = SIZEOF (DCB);
GetcommState (M_HIDCOMDEV, & DCB); // Get port default settings
Dcb.baudrate = CBR_4800;
DCB.BYTESIZE = 8;
DCB.PARITY = NOPARITY
DCB.Stopbits = (byte) onestopbit;
......}
---- (3) Serial port reading operation
---- Mainly use the readFile () and WriteFile () API function, if as an asynchronous communication method, the last parameter in the two functions is a non-empty pointer to the Overlapped structure, when the read and write function returns value is false, call GetLasterror () function, return value is ERROR_IO_PENDING, indicating that I / O operation is suspended, that is, the operation is transferred to the background to continue execution. At this point, WaitForsingleObject () can be used to wait for the end signal and set the longest waiting time, as follows:
Bool breadstatus;
Breadstatus = readfile (M_HidComDev, Buffer,
DWBYTESREAD, & DWBYTESREAD, & M_OVERLAPPEDREAD;
IF (! BreadStatus)
{
IF (getLastError () == Error_io_pending)
{
WaitforsingleObject (m_overlappedreadyad.hevent, 1000);
Return (INT) DWBYTESREAD;
}
Return (0);
}
Return (INT) DWBYTESREAD;
---- Defining the global variable m_serial as an object of the new communication class CSIMpleComm, you can implement the desired serial communication function by calling a member function of the class. Compared to the method, the method two gives the serial communication program to design a large flexibility, the port read / write can choose a simpler query, or the same timer as the same as the peripheral data transmission time interval TimeCycle: SETTIMER 1. Timecycle, NULL, timed, read or transmitted.
Csampleview :: ONTIMER (uint nidevent)
{
CHAR INPUTDATA [30];
m_serial.readdata (InputData, 30); // Data Processing
}
---- If the response time requirements for port data are strict, event-driven I / O read-write, Windows defines 9 serial port communication events, more commonly used:
---- EV_RXCHAR: Receive one byte and put it into the input buffer.
---- EV_TXEMPTY: The last character in the output buffer is sent out.
---- EV_RXFLAG: Receive event characters (member members in the DCB structure), put into the input buffer.
---- After specifying useful events with setcommmask (), the application can call WaitCommEvent () to wait for the incident. SetCommmask (hcomm, 0) can abort WaitCommEvent ().
---- Method three-multi-thread implementation serial communication
---- Method 1, II Suitable for single-threaded communication. In many industrial control systems, often through extended serial ports, each peripheral sends data is different, requires the background real-time no error capture, acquisition, processing, record each port data, which needs to be customized. A port monitoring thread is created in the serial communication class to send a notification message to the related window when the specified event occurs.
---- The basic concept of threads can be found in the VC reference book, the first schedule of Windows assigns the CPU time between the active thread, and Win 32 divides two different types of threads, one is the user interface thread UI (User Interface thread), which contains a message loop or message pump for processing the received message; another is Work Thread, which does not have a message loop for performing background tasks. The thread used to monitor the serial entry is the working thread.
---- Multi-threaded communication class in the configuration of the port, the connection section is the same as the single-threaded communication class, and after the port is configured, the most important thing is based on the actual situation, the synchronization object between multi-threads, such as signal lights, Critical areas, events, etc., related details can be referred to the synchronization class in VC .
---- Once you are ready, you can start the working thread:
CWINTHREA * Commthread = afxbegin
Thread (Commwatchthread, // thread function name
(Lpvoid) M_PTTYINFO, / / Parameters
Thread_priority_above_normal, // Set thread priority
(Uint) 0, // maximum stack size
(DWORD) CREATE_SUSPENDED, // Create a flag
(Lpsecurity_attributes) null); // Security Sign
---- At the same time, in the serial entry event monitoring thread:
IF (Waitcommevent (PTTYINFO-> IDCOMDEV, & DWEVTMASK, NULL)
{
IF (DWEVTMASK & PTTYINFO-> DWEVTMASK) == PTTYINFO-> DWEVTMASK)
{
WaitforsingleObject (PTTYINFO-> HPOSTEVENT, 0xFFFFFFF);
ResetEvent (PTTYINFO-> HPOSTEVENT); // Send synchronous event object is non-signal
:: PostMessage (csampleview, id_com1_data, 0, 0); // € € 通 消}
}
---- Use postMessage () to send a notification message to the message queue of the specified window, accordingly, you need to establish a message between the message and the member function, and use on_Message to associate the message with the member letter.
Begin_MESSAGE_MAP (CsampleView, CView)
// {{AFX_MSG_MAP (CsampleView)
ON_MESSAGE (ID_com1_data, onprocesscom1data)
ON_MESSAGE (ID_com2_data, onprocesscom2data)
.....
//}} AFX_MSG_MAP
END_MESSAGE_MAP ()
---- Then complete the reception processing of each serial port data in each member function, but must ensure that all intermediate processing work can be completed before the next monitoring has arrived next time. Otherwise, the data will be captured.
---- Multi-threading implementation allows all ports to realize serial communication independently, enabling serial communication with more extensive flexibility and strictness, and takes advantage of CPU time. However, how to coordinate multiple threads in a specific real-time monitoring system, how to achieve synchronization between threads is also difficult to implement in multi-threaded serial communication procedures.
---- Three ways to achieve serial communication with VC 6.0, all three methods of serial communication,
---- Select the appropriate method according to different needs, will reach the effect of half the power. In the temperature monitoring system, the author adopted a method. In Window 98, the Windows 95 is running stable, and good results have been achieved in WINDOW 98.