Three methods for implementing serial communication using vc6.0

Source: Internet
Author: User
Serial Communication in Windows
Unlike the serial communication programs in DOS, Windows does not recommend that applications directly control the hardware, but transmits data through the device driver provided by the Windows operating system. The serial port is processed as a file in Win 32, rather than directly operating on the port. For serial communication, Win 32 provides the corresponding file I/O functions and communication functions, by understanding the use of these functions, You can compile a communication program that meets different needs. The communication device-related structures include commconfig, commp drop, commtimeouts, COMSTAT, DCB, modemdevcaps, and modemsettings. There are 26 communication-related Windows API functions, for more information, see the msdn help file. The following three methods are provided to implement serial communication based on the instance.
Three methods for implementing serial communication
Method 1: Use the serial communication control MSComm provided by VC ++. First, create a communication control in the dialog box. If this control is missing in the control toolbar, you can insert the control from the menu project --> Add to project --> components and control, and then pull the control from the toolbox to the dialog box. In this case, you only need to care about the API functions provided by the control for the Windows communication driver. In other words, you only need to set and monitor attributes and events of the MSComm control.
Define the member object (cmscomm m_serial) for the newly created communication control in classwizard. With this object, you can set the serial port attributes. the MSComm control has 27 attributes, here we will only introduce several common attributes:
Set and return the communication port number in comport. The default value is com1.
Settings is set as a string and returns the baud rate, parity, data bit, stop bit.
Set the port and return the status of the communication port. You can also enable or disable the port.
Input returns and deletes characters from the receiving buffer.
Output writes a string to the sending buffer.
Inputlen sets the number of characters that each input reads. The default value is 0, indicating that all content in the receiving buffer area is read.
Inbuffercount: returns the number of received characters in the receiving buffer. Setting it to 0 can clear the receiving slow-forward area.
Inputmode defines how the INPUT attribute obtains data (0: text; 1: Binary ).
The rthreshold and sthreshold attributes indicate the number of characters that can be received in the receiving or sending buffer before an oncomm event occurs.
The following example initializes the serial port by setting control properties:
Bool csampledlg: portopen ()
{
Bool m_opened;
......
M_serial.setcommp ORT (2); // specify the serial port number
M_serial.setsettings ("4800, N, 8, 1"); // communication parameter settings
M_serial.setinbuffersize (1024); // specify the size of the receiving buffer.
M_serial.setinbuffercount (0); // clear the receiving buffer
M_serial.inputmode (1); // sets the data acquisition mode.
M_serial.setinputlen (0); // you can specify the Read mode.
M_opened = m_serail.setportopen (1); // open the specified serial port
Return m_opened;
}
After opening the required serial port, you need to consider the serial port communication time. In the process of receiving or sending data, you may need to monitor and respond to some events and errors. Therefore, event-driven is a very effective method for handling serial port interactions. Capture and check the values of communication events and errors using the oncomm event and commevent attributes. When a communication event or error occurs, the oncomm event is triggered, and the value of the commevent attribute is changed. The application checks the attribute value of commevent and responds accordingly. In the program, use classwizard to add the oncomm message processing function for the cmscomm control:
Void csampledlg: oncomm ()
{
......
Switch (m_serial.getcommevent ())
{
Case 2:
// Receives and processes data from the serial port;
}
}
Method 2: Implement custom serial communication in a single thread
The control is easy to use, but it must be used in the dialog box. In some applications that require communication in the thread, the use of the control is too slow. At this time, if you can customize the flexible Serial Communication Class according to different needs, it will make up for the lack of the control, the following describes how to create a custom communication class in a single thread.
The Communication Class csimplecomm needs to manually add the header file and source file. Its base class is cobject. The general creation steps are as follows:
(1) Open the serial port and obtain the serial port resource handle
The communication program specifies the serial device and related operation properties from the createfile. A handle is returned, which is used for subsequent communication operations and runs through the entire communication process. The createfile () function has several notable parameter settings: the serial port sharing mode should be set to 0, and the serial port is a non-shared device; The creation method must be open_existing to open the existing serial port. For the dwflagandattried parameter, the meaningful value for the serial port is file_flag_overlapped. This indicates that the serial port adopts the asynchronous communication mode and can be overlapped. If the value is null, the synchronous communication mode is used, in synchronous mode, the application will always control the program flow until the program ends. In case of communication failure or other factors, the application will wait permanently. Therefore, asynchronous communication is generally used.
(2) Serial Port Settings
After the serial port is opened, its property is set to the default value. According to the specific needs, you can call getcommstate (hcomm, & DCB) to read the current Device Control Block DCB (Device Control Block) settings, after modification, use setcommstate (hcomm, & DCB) to write it. Pay attention to the timeout control settings of asynchronous read/write. Set the timeout through the commtimeouts structure and call setcommtimeouts (hcomm, & Timeouts) to write the result. The following are the serial port initialization member functions in the temperature monitoring program:
Bool csimplecomm: open ()
{
DCB;
M_hidcomdev = createfile ("com2 ",
Generic_read | generic_write,
0, null, open_existing, file_attribute _
Normal | file_flag_ove rlapped, null );
// Enable the serial port and perform asynchronous operations
If (m_hidcomdev = NULL) Return (false );
DCB. dcblength = sizeof (DCB );
Getcommstate (m_hidcomdev, & DCB); // obtain the default port settings
DCB. baudrate = cbr_4800;
DCB. bytesize = 8;
DCB. Parity = noparity;
DCB. stopbits = (byte) onestopbit;
......}
(3) Serial Port read/write operations
It mainly uses the readfile () and writefile () API functions. For Asynchronous Communication, the last parameter of the two functions is a non-null pointer pointing to the overlapped structure, when the returned value of the read/write function is false, call the getlasterror () function. The returned value is error_io_pending, indicating that the I/O operation is suspended, that is, the operation is transferred to the background for further execution. In this case, you can use waitforsingleobject () to wait for the end signal and set the maximum wait time. For example:
Bool breadstatus;
Breadstatus = readfile (m_hidcomdev, buffer,
Dwbytesread, & dwbytesread, & m_overlappedread );
If (! Breadstatus)
{
If (getlasterror () = error_io_pending)
{
Waitforsingleobject (m_overlappedread.hevent, 1000 );
Return (INT) dwbytesread );
}
Return (0 );
}
Return (INT) dwbytesread );
Define the global variable m_serial as the object for creating a Communication Class csimplecomm. Call the member function of the class to implement the required serial communication function. Compared with method 1, method 2 provides great flexibility for the design of serial communication programs. You can select a simple query type for reading and writing ports, you can also set a timer with the same time interval as the peripheral data sending time: settimer (1, timecycle, null) to regularly read or send data.
Csampleview: ontimer (uint nidevent)
{
Char inputdata [30];
M_serial.readdata (inputdata, 30 );
// Data Processing
}
If you have strict response time requirements on port data, you can use event-driven I/O read/write. In Windows, nine types of serial communication events are defined, which are commonly used:
Ev_rxchar: receives a byte and puts it in the input buffer.
Ev_txempty: The last character in the output buffer is sent out.
Ev_rxflag: receives event characters (evtchar members in the DCB structure) and puts them in the input buffer.
After setcommmask () is used to specify a useful event, the application can call waitcommevent () to wait for the event to occur. Setcommmask (hcomm, 0) can abort waitcommevent.
Method 3 multi-thread Implementation of Serial Communication
Method 1 and method 2 are applicable to single-thread communication. In many industrial control systems, multiple peripherals are often connected through an extended serial port. The frequency of data duplication between each peripheral device is different, and the backend must capture, collect, process, and record data on each port in real time, in this case, you need to create a port monitoring thread in the Custom serial communication class to send a notification message to the corresponding window when the specified event occurs.
For details about the basic concepts of threads, see the VC ++ bibliography. The preemptible scheduling program in Windows allocates CPU time between active threads. Win 32 distinguishes two different types of threads, one is the user interface thread (UI), which contains message loops or message pumps for processing received messages, and the other is the work thread ), it has no message loop and is used to execute background tasks. The thread used to monitor serial events is the working thread.
The multi-thread Communication Class is written in the port configuration. The connection part is the same as the single-thread Communication Class. After the port configuration is complete, the most important thing is to establish synchronization objects between multiple threads according to the actual situation, for details, such as signal lights, critical sections, and events, see synchronization classes in VC ++.
After everything is ready, start the working thread:
Cwinthrea * commthread = afxbegin
Thread (commwatchthread, // thread function name
(Lpvoid) m_pttyinfo, // passed Parameter
Thread_priority_above_normal, // sets the thread priority.
(Uint) 0, // maximum stack size
(DWORD) create_suincluded, // create a flag
(Lpsecurity_attributes) null); // Security Flag

At the same time, in the serial port event monitoring thread:
If (waitcommevent (pttyinfo-> idcomdev, & dwevtmask, null ))
{
If (dwevtmask & pttyinfo-> dwevtmask) = pttyinfo-> dwevtmask)
{
Waitforsingleobject (pttyinfo-> hpostevent, 0 xffffffff );
Resetevent (pttyinfo-> hpostevent); // sets the synchronization event object to a non-signal state.
: Postmessage (csampleview, id_com1_data,); // send a notification message
}
}
Use postmessage () to send a notification message to the message queue in the specified window. Accordingly, you need to establish a ing between the message and the member function in the window and associate the message 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, the serial port data is received and processed in each member function, but it must be ensured that all intermediate processing work can be completed before the next time data is detected. Otherwise, data may be captured incorrectly.
Multi-threaded implementation can make each port independent and accurately implement serial communication, so that serial communication has a wider range of flexibility and rigor, and fully utilizes the CPU time. However, in a real-time monitoring system, how to coordinate multiple threads and how to implement synchronization between threads is also a difficulty in implementing multi-thread serial communication programs.
Using VC ++ 6.0 as a tool, three methods of serial communication have their own advantages and disadvantages,
Select an appropriate method based on your needs to get twice the result with half the effort. In the temperature monitoring system, the author adopted method 2 to run stably on Windows 98 and Windows 95, and achieved good results.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.