VC + + Serial Communication programming detailed

Source: Internet
Author: User
Tags function prototype readfile

VC + + Serial Communication programming detailed

Reprint Address: http://www.jizhuomi.com/software/309.html

In industrial control, industrial computer (usually based on Windows platform) often need to communicate with the intelligent instrument through the serial port. Serial communication is convenient and easy to use and widely used.
In general, the industrial computer and the intelligent instrument through the RS485 bus communication. RS485 communication mode is half-duplex, can only be used as the main node of the industrial PC in turn polling the network of Intelligent Control Unit sub-nodes. Each communication is by the PC through the serial port to the Intelligent Control Unit issued commands, the Intelligent Control unit after receiving the correct command to make an answer.

Under Win32, you can use two kinds of programming to implement serial communication, one is to use ActiveX control, this method is simple, but less flexible. The second is to call the Windows API function, this method can clearly grasp the mechanism of serial communication, and free and flexible. In this article we only introduce the API serial communication section.

The operation of the serial port can be operated in two ways: synchronous operation mode and overlapping operation mode (also known as asynchronous operation mode). When synchronizing, the API function blocks until the operation is complete (in multithreaded mode, although it does not block the main thread, but still blocks the listener), and the API function returns immediately after the operation is performed in the background, avoiding thread blocking.

This is done in four steps, regardless of the type of operation:

(1) Open the serial port
(2) Configuring the serial port
(3) Read/write serial
(4) Close the serial port

1. Open the serial port


The WIN32 system extends the concept of a file. Whether files, communications devices, named pipes, mail slots, disks, or consoles, are opened or created with API function CreateFile. The prototype of this function is:

C + + code
    1. HANDLE CreateFile ( lpctstr lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, Lpsecurity_attributes    lpSecurityAttributes, DWORD dwcreationdistribution, DWORD dwflagsandattributes, HANDLE htemplatefile);

lpFileName: The logical name of the serial port that will be opened, such as "COM1";
dwDesiredAccess: Specifies the type of serial access, which can be read, write, or both;
dwShareMode: Specifies the shared property, the parameter must be set to 0 because the serial port cannot be shared;
lpSecurityAttributes: Reference security attribute structure, default value is null;
Dwcreationdistribution: Create the flag, the serial port operation of the parameter must be set to open_existing;
dwFlagsAndAttributes: Property Description, which specifies whether the serial port is asynchronous, which is file_flag_overlapped, which represents the use of asynchronous I/O; the value is 0, which indicates synchronous I/O operations;
hTemplateFile: This parameter must be set to NULL for the serial port.

Synchronous I/O opens the sample code for the serial port:

C + + code
  1. HANDLE HCom; //global variable, serial handle
  2. Hcom=createfile ("COM1",//com1 mouth
  3. generic_read| Generic_write, //Allow read and write
  4. 0, //Exclusive mode
  5. Null
  6. Open_existing, //Open instead of Create
  7. 0, //sync mode
  8. NULL);
  9. if (hcom== (HANDLE)-1)
  10. {
  11. AfxMessageBox ("Open com failed!");
  12. return FALSE;
  13. }
  14. return TRUE;

Example code for overlapped I/O opening the serial port:

C + + code
  1. HANDLE HCom; //global variable, serial handle
  2. HCom =createfile ("COM1", //com1 mouth
  3. generic_read| Generic_write, //Allow read and write
  4. 0, //Exclusive mode
  5. Null
  6. Open_existing, //Open instead of Create
  7. file_attribute_normal| file_flag_overlapped, //overlap Mode
  8. NULL);
  9. if (HCom ==invalid_handle_value)
  10. {
  11. AfxMessageBox ("Open com failed!");
  12. return FALSE;
  13. }
  14. return TRUE;

2. Configure the serial port

After opening the communication device handle, it is often necessary to do some initialization configuration work on the serial port. This needs to be done through an DCB structure. The DCB structure contains information such as baud rate, number of data bits, parity, and stop bits. The DCB structure is used as a buffer when querying or configuring the properties of the serial port.

After you open the serial port with CreateFile, you can call the Getcommstate function to get the initial configuration of the serial port. To modify the configuration of the serial port, the DCB structure should be modified before calling the SetCommState function to set the serial port.
DCB structure contains the parameters of the serial port settings, the following are only a few of the variables commonly used in this structure:

typedef struct _dcb{.....

The DWORD baudrate;//baud rate that specifies the transmission rate of the communication device. This member can be either the actual baud rate value or one of the following constant values: cbr_110,cbr_300,cbr_600,cbr_1200,cbr_2400,cbr_4800,cbr_9600,cbr_19200, cbr_38400, CBR_ 56000, cbr_57600, cbr_115200, cbr_128000, cbr_256000, cbr_14400

DWORD fparity; Specifies the parity enable. If this member is 1, allow parity check ...

BYTE ByteSize; Number of bytes of communication, 4-8

BYTE Parity; Specifies the parity method. This member can have the following values: evenparity parity noparity non-checksum markparity mark check oddparity parity check

BYTE stopbits; Specifies the number of bits in the stop bit. This member can have the following values: Onestopbit 1-bit stop bit twostopbits 2-bit stop bit
On 5STOPBITS 1.5-bit stop bit
                                                                                                                                                                               

The Getcommstate function obtains the relevant parameters by obtaining the device control block of the COM port:
BOOL Getcommstate (

HANDLE hfile,//handle that identifies the communication port

LPDCB LPDCB//Pointer to a Device control block (DCB structure);

The SetCommState function sets the device control block for the COM port:

BOOL setcommstate (HANDLE hfile, LPDCB LPDCB);
In addition to the settings in BCD, the program generally needs to set the size and timeout of the I/O buffers. Windows uses I/O buffers to stage data for serial input and output. If the rate of communication is high, you should set a larger buffer. Call the Setupcomm function to set the size of the input and output buffers for the serial port.
BOOL Setupcomm (HANDLE hfile,//Handle of communication device

DWORD Dwinqueue,//size of input buffer (bytes)

DWORD dwoutqueue//output buffer size (number of bytes));
When reading and writing serial ports with ReadFile and WriteFile, you need to consider the timeout problem. The function of a timeout is to not read or send a specified number of characters within a specified amount of time, and the operation of ReadFile or WriteFile will still end.
To query the current time-out setting should call the Getcommtimeouts function, which populates a commtimeouts structure. Calling SetCommTimeouts can set a timeout with the contents of a COMMTIMEOUTS structure.
There are two types of timeouts for read-write serial ports: Interval timeout and total timeout. The interval timeout is the maximum delay between two characters at the time of receipt. The total timeout is the maximum time a read-write operation has taken. The write operation only supports the total timeout, while both the read operation timeout is supported. Use the COMMTIMEOUTS structure to specify the timeout for read and write operations.
The COMMTIMEOUTS structure is defined as:
typedef struct _COMMTIMEOUTS {

DWORD ReadIntervalTimeout; Read Interval timeout

DWORD ReadTotalTimeoutMultiplier; Read Time factor

DWORD ReadTotalTimeoutConstant; Read Time Constants

DWORD WriteTotalTimeoutMultiplier; Write Time factor

DWORD writetotaltimeoutconstant; Write Time constants

} commtimeouts,*lpcommtimeouts;
The members of the COMMTIMEOUTS structure are in milliseconds.

The total timeout is calculated as: Total Timeout = time factor x number of characters required to read/write + time constant
For example, to read in 10 characters, the total timeout for the read operation is calculated as:
Read Total timeout =readtotaltimeoutmultiplierx10+readtotaltimeoutconstant
It can be seen that the settings for interval timeouts and total timeouts are irrelevant, which makes it easy for the communication program to set various timeouts.

If all write timeout parameters are 0, write timeouts are not used. If ReadIntervalTimeout is 0, then the read interval timeout is not used. If both ReadTotalTimeoutMultiplier and ReadTotalTimeoutConstant are 0, the read total timeout is not used. If the read interval timeout is set to Maxdword and the read time factor and the read time constant are 0, the read operation returns immediately after reading the contents of the input buffer, regardless of whether the required characters are read or not.
When the serial port is read and written in overlapping ways, although ReadFile and WriteFile may return before the operation is complete, the timeout still works. In this case, the timeout is defined as the completion time of the operation, not the return time of ReadFile and WriteFile.
Sample code to configure the serial port:
Setupcomm (hcom,1024,1024); Both the input buffer and the output buffer size are 1024

Commtimeouts timeouts; Set Read timeout

timeouts.readintervaltimeout=1000;

timeouts.readtotaltimeoutmultiplier=500;

timeouts.readtotaltimeoutconstant=5000; Set Write timeout

timeouts.writetotaltimeoutmultiplier=500;

timeouts.writetotaltimeoutconstant=2000;

SetCommTimeouts (hcom,&timeouts); Set timeout

DCB DCB;

Getcommstate (HCOM,&DCB);

Dcb. baudrate=9600; Baud rate is 9600

Dcb. bytesize=8; Each byte has 8 bits

Dcb. parity=noparity; No parity bit

Dcb. Stopbits=twostopbits; Two Stop bits

SetCommState (HCOM,&DCB);

PurgeComm (hcom,purge_txclear| Purge_rxclear);
Before reading and writing the serial port, also use the PurgeComm () function to empty the buffer, the function prototype:
BOOL PurgeComm (HANDLE hfile,//serial handle

DWORD dwFlags//operation to be completed);
The parameter dwflags specifies the action to complete, which can be a combination of the following values:
Purge_txabort interrupts all writes and returns immediately, even if the write operation is not completed.

Purge_rxabort interrupts all read operations and returns immediately, even if the read operation has not been completed.

Purge_txclear clear the output buffer

Purge_rxclear clearing the input buffer

3, read and write serial port

We use ReadFile and WriteFile to read and write the serial port, the following is a declaration of two functions:

BOOL ReadFile (HANDLE hfile,//serial port handle

The address of the data store read in,

That is, the data that is read is stored in a memory area that is the first address of the value of the pointer.

LPVOID lpbuffer,

The number of bytes to read into the data

DWORD nNumberOfBytesToRead,

Points to a DWORD value that returns the number of bytes actually read in the read operation

Lpdword Lpnumberofbytesread,

When you overlap an operation, the parameter points to a overlapped structure, which is null when the synchronization operation occurs.

lpoverlapped lpoverlapped);

BOOL WriteFile (HANDLE hfile,//serial port handle

The address of the data store being written to,

That is, the value of the pointer to the first address.

LPCVOID lpBuffer,
The number of bytes of data to write

DWORD nNumberOfBytesToWrite,

Point to a DWORD value that returns the number of bytes actually written

Lpdword Lpnumberofbyteswritten,

When overlapping operations, this parameter points to a overlapped structure,

The parameter is null when the synchronization operation occurs.

lpoverlapped lpoverlapped);

When reading and writing the serial port with ReadFile and WriteFile, it can be executed synchronously or overlapped. When executed synchronously, the function is not returned until the operation is complete. This means that threads are blocked during synchronous execution, resulting in a decrease in efficiency. When overlapping execution, even if the operation is not completed, both functions return immediately, and the time-consuming I/O operation takes place in the background. Whether the
ReadFile and WriteFile functions are synchronous or asynchronous is determined by the CreateFile function, and if the FILE_FLAG_OVERLAPPED flag is specified when the handle is called CreateFile. The operations that call ReadFile and WriteFile on the handle should be overlapping, and the read and write operations should be synchronous if no overlapping flags are specified. The synchronization or asynchrony of the ReadFile and WriteFile functions should be consistent with the CreateFile function. The
ReadFile function simply reads the specified number of characters into the serial input buffer, even if the operation is complete. The WriteFile function is not only to copy the specified number of characters into the output buffer, but also to wait for these characters to be sent out from the serial port to complete the operation.
If the operation succeeds, both functions return true. It is important to note that when ReadFile and WriteFile return false, it is not necessarily the case that the operation failed and the thread should call the GetLastError function to parse the returned results. For example, the function returns False if the action is not completed when the operation is overlapped, and the GetLastError function returns ERROR_IO_PENDING. This indicates that the overlap operation is not yet complete.

Synchronous reading and writing serial port is relatively simple, the following precedent to read and write the serial port code:  
//synchronous read serial  

Char str[100]; 

DWORD wcount;//number of bytes read

BOOL breadstat; 

BREADSTAT=READF Ile (Hcom,str,100,&wcount,null);

if (!breadstat) {AfxMessageBox ("read serial failed!"); return FALSE;} return TRUE;//synchronous write serial port

Char lpoutbuffer[100];

DWORD dwbyteswrite=100;

Comstat comstat; 

DWORD dwerrorflags; 

BOOL bwritestat; 

Clearcommerror (hcom,&dwerrorflags,&comstat);

Bwritestat=writefile (hcom,lpoutbuffer,dwbyteswrite,& dwbyteswrite,null);

if (!bwritestat) {AfxMessageBox ("failed to write serial port!");}

PurgeComm (HCom, purge_txabort| Purge_rxabort| purge_txclear| Purge_rxclear); 

When an overlap operation is performed, the operation is returned without completing the function.

Overlapping I/O is very flexible, it can also be blocked (for example, we can set to read to a data to proceed to the next operation). There are two ways to wait for the operation to complete: One method is to wait for the hevent member of the overlapped structure with a wait function like WaitForSingleObject, and the other is to call the GetOverlappedResult function to wait. A description will be shown later.
Let's briefly talk about the overlapped structure and the GetOverlappedResult function:
OVERLAPPED structure
The overlapped structure contains some information about overlapped I/O, as defined below:
typedef struct _OVERLAPPED {//O

DWORD Internal;

DWORD Internalhigh;

DWORD Offset;

DWORD Offsethigh;

HANDLE hevent;

} OVERLAPPED;
When using ReadFile and WriteFile overlap operations, threads need to create overlapped structures for use by these two functions. The thread obtains the current operational state through the overlapped structure, and the most important member of the structure is hevent. Hevent is a read-write event. When the serial port uses asynchronous communication, the operation may not be completed when the function returns, and the program can check the event to see if the read and write are complete.
When the ReadFile, WriteFile function is called, the member is automatically set to a signal-free State, and when the overlap operation is complete, the member variable is automatically set to the signaled state.
GetOverlappedResult function BOOL GetOverlappedResult (HANDLE hfile,//The handle of the serial port//points to the overlapped structure specified at the beginning of the overlap Operation lpoverlapped lpoverlapped,//points to a 32-bit variable that returns the number of bytes transferred by the actual read-write operation. Lpdword lpnumberofbytestransferred,//This parameter specifies whether the function waits until the overlap operation ends. If this argument is true, the function will not return until the end of the operation. If the argument is False, the function returns directly, and if the operation is not completed,//The call to the GetLastError () function returns ERROR_IO_INCOMPLETE. BOOL bwait);
The function returns the result of the overlapping operation, which is used to determine whether the asynchronous operation is complete, which is accomplished by judging whether the hevent in the overlapped structure is set.

Example code for asynchronous read serial port:

Char lpinbuffer[1024];

DWORD dwbytesread=1024;

Comstat Comstat;

DWORD Dwerrorflags;

OVERLAPPED M_osread;

memset (&m_osread,0,sizeof (OVERLAPPED));

M_osread.hevent=createevent (Null,true,false,null);

Clearcommerror (Hcom,&dwerrorflags,&comstat);

Dwbytesread=min (dwBytesRead, (DWORD) comstat.cbinque);

if (!dwbytesread) return FALSE;

BOOL Breadstatus;

Breadstatus=readfile (Hcom,lpinbuffer, Dwbytesread,&dwbytesread,&m_osread);

if (!breadstatus)

If the ReadFile function returns false

{

if (GetLastError () ==error_io_pending)

The GetLastError () function returns ERROR_IO_PENDING, indicating that the serial port is in the read operation

{

WaitForSingleObject (m_osread.hevent,2000);

Use the WaitForSingleObject function to wait until the read operation completes or the delay has reached 2 seconds

When the serial read operation is completed, the M_osread hevent event will become a signal

PurgeComm (HCom, purge_txabort| Purge_rxabort| purge_txclear| Purge_rxclear);

return dwbytesread;

}

return 0;

}

PurgeComm (HCom, purge_txabort| Purge_rxabort| purge_txclear| Purge_rxclear);

return dwbytesread;
Give a brief explanation of the above code:

You should use the Clearcommerror function to clear the error before you use the ReadFile function for read operations.

The Clearcommerror function is prototyped as follows:
BOOL Clearcommerror (HANDLE hfile,//serial handle

Lpdword lperrors,//pointer to the variable receiving the error code

Lpcomstat LpStat//point to the communication state buffer);
The function obtains the communication error and reports the current state of the serial port, and the function clears the serial port error flag to continue the input and output operation.
The parameter Lpstat points to a COMSTAT structure that returns the serial port status information.

COMSTAT structure COMSTAT structure contains the information of the serial port, the structure is defined as follows:
typedef struct _COMSTAT {//CST DWORD fctshold:1;//TX Waiting for CTS signal DWORD fdsrhold:1;//TX Waiting for DS R signal DWORD frlsdhold:1; Tx waiting for RLSD signal DWORD fxoffhold:1; Tx waiting, XOFF Char rec ' d DWORD fxoffsent:1; Tx waiting, XOFF char sent DWORD feof:1; EOF character sent DWORD ftxim:1; Character waiting for Tx DWORD freserved:25; Reserved DWORD cbinque; Bytes in input buffer DWORD cboutque; Bytes in output buffer} comstat, *lpcomstat;
This article uses only the Cbinque member variable, which represents the number of bytes in the input buffer.

Finally, the input and output buffers of the serial port are emptied with purgecomm function.
This code uses the WaitForSingleObject function to wait for the hevent member of the overlapped structure, and then we show an asynchronous read serial port sample code that calls the GetOverlappedResult function waiting:

Char lpinbuffer[1024];

DWORD dwbytesread=1024;

BOOL Breadstatus;

DWORD Dwerrorflags;

Comstat Comstat;

OVERLAPPED M_osread;

Clearcommerror (Hcom,&dwerrorflags,&comstat);

if (! Comstat.cbinque) return 0;

Dwbytesread=min (dwBytesRead, (DWORD) comstat.cbinque);

Breadstatus=readfile (HCom, Lpinbuffer,dwbytesread, &dwbytesread,&m_osread);

if (!breadstatus)//If the ReadFile function returns false

{if (GetLastError () ==error_io_pending)

{GetOverlappedResult (HCom, &m_osread,&dwbytesread,true);

The last parameter of the GetOverlappedResult function is set to True,

The function waits until the read operation completes or is returned due to an error.

return dwbytesread; }

return 0; }

return dwbytesread;
Example code for asynchronous write serial port:
Char buffer[1024];

DWORD dwbyteswritten=1024;

DWORD Dwerrorflags;

Comstat Comstat;

OVERLAPPED M_oswrite;

BOOL Bwritestat;

Bwritestat=writefile (Hcom,buffer,dwbyteswritten, &dwbyteswritten,&m_oswrite);

if (!bwritestat)

{if (GetLastError () ==error_io_pending)

{WaitForSingleObject (m_oswrite.hevent,1000);

return dwbyteswritten; }

return 0; }

return dwbyteswritten;

4. Close the serial port

Using the API function to close the serial port is very simple, just call CloseHandle using the handle returned by the CreateFile function as a parameter:

BOOL CloseHandle (
HANDLE Hobject; Handle to object to close
);

VC + + Serial Communication programming detailed

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.