Three ways to realize serial communication with VC 6.0
Shanghai Institute of Optics and Precision Machinery, Chinese Academy of Sciences (201800) Wang Ying
Forehead
---- 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 with a single chip microcomputer. The result of collecting the host in a serial mode, sends a sampling data to the host every 10 seconds, and the host sends related control commands to the single-chip microcomputer. Realize serial data reception, processing, recording, display, and real-time drawing curve. The serial communication program development environment is VC 6.0.
Serial communication under Windows
---- 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 the communication device has a total of 7 CommConfig, CommProp, CommTimeouts, Comst, DCB, ModemDevcaps, MODEMSETTINGS. There are 26 Windows API functions related to communication. Details can refer to the MSDN help file. The following will be combined with examples, three methods for realizing serial communication will be given.
Three methods for realizing serial communication
----
Method 1: Serial Communication Controls provided using VC MSCOMM
---- First, create a communication control in the dialog box, if the control is missing in the Control toolbar, you can insert the control from the menu Project → Add to Project → Components and Control, pull the control from the toolbox to the conversation In the 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
COM1.
Settings set and return to Pott in the form of strings
Rate, parity, data bit, stop bit.
Portopen settings and returns the status of the communication port, or
Turn the port to open and close 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 each time INPUT, lack
The value is 0, indicating the full service of the receiving buffer
Ministry content.
InbufferCount Returns the character received in the receiving buffer
Number, set it 0 to clear the receiving buffer.
InputMode Defines the way the input property gets the data (for
0: Text method; 1: binary method).
---- 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, and then returns a handle, which will be used for subsequent communication operations and runs throughout the 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 the 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 wait time. For example, 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 a byte and put it in the input
Buffer.
EV_TXEMPTY: The last word in the output buffer
Send it out.
EV_RXFLAG: Receive event characters (DCB structure
Evtchar member), 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 3: 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 =
AFXBEGINTHREAD (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);
// set synchronous event objects to non-signal
:: PostMessage (csampleview, id_com1_data, 0, 0);
// Send a notification message
}
}
---- Use postMessage () to send a notification message to the message queue of the specified window, accordingly, the message is required to establish a message between the message and the member function, and the message is associated with the member function name with ON_MESSAGE. 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 works 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.
Conclusion
---- Three ways to achieve serial communications are all advantageous and disadvantages with VC 6.0.
---- Select the appropriate method according to different needs, will reach the effect of half the power. In the temperature monitoring system, the author uses method two, running stable on Windows 98, Windows 95, has achieved good results.