/* ------ + ------
An example of serial Programming
To help you better understand serial programming, We will compile two routines (see the source code section ),
Both routines implement serial communication between the industrial computer and the Baxter display instrument through the RS485 interface. Where
The first routine uses synchronous serial port operations, and the second routine uses asynchronous serial port operations.
We will only introduce the software, but do not introduce the RS485 interface wiring method. Interested readers can refer to the relevant information.
/* ------ + ----*/
/* ------ +
Open VC ++ 6.0, create a dialog-based project RS485Comm, and in the main dialog box window idd_rs485comm_dicomm
Add two buttons, ID: IDC_SEND and IDC_RECEIVE, and title: "send" and "receive" respectively. Add one
Static text box IDC_DISP, used to display the content received by the serial port.
------ + -------*/
// Add the global variable to the RS485CommDlg. cpp file:
HANDLE hCom; // global variable, serial port HANDLE
// Add the following code to the OnInitDialog () function in the RS485CommDlg. cpp file:
// TODO: Add extra initialization here
HCom = CreateFile ("COM1", // COM1 port
GENERIC_READ | GENERIC_WRITE, // read and write are allowed.
0, // exclusive mode
NULL,
OPEN_EXISTING, // open rather than create
0, // synchronous Mode
NULL );
If (hCom = (HANDLE)-1)
{
AfxMessageBox ("failed to open COM! ");
Return FALSE;
}
SetupComm (hCom, 100,100); // the size of the input buffer and output buffer is 1024
COMMTIMEOUTS TimeOuts;
// Set read timeout
TimeOuts. ReadIntervalTimeout = MAXDWORD;
TimeOuts. ReadTotalTimeoutMultiplier = 0;
TimeOuts. ReadTotalTimeoutConstant = 0;
// After reading the content of the input buffer, the read operation will return immediately,
// Whether or not the required characters are read.
// Set write timeout
TimeOuts. WriteTotalTimeoutMultiplier = 100;
TimeOuts. WriteTotalTimeoutConstant = 500;
SetCommTimeouts (hCom, & TimeOuts); // set timeout
DCB dcb;
GetCommState (hCom, & dcb );
Dcb. BaudRate = 9600; // The 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 );
// Double-click the IDC_SEND button and the IDC_RECEIVE button respectively to add the response functions of the two buttons:
Void CRS485CommDlg: OnSend ()
{
/* ------ + -------
| TODO: Add your control notification handler code here |
| Here we need to briefly introduce the communication protocol of Baxter XMA5000: |
| The RS485 communication of the meter is broadcast by the host. |
| Serial half-duplex, 11-bit frame, 1 start bit (0), 8 data bits, 2 Stop bits (1) |
| For example, the instantaneous value displayed by the reading instrument. sent by the Host: DC1 aaa bb etx |
| DC1 is a control symbol of the standard ASCII code. The code value is 11 H (17 in decimal format). |
| In the XMA5000 communication protocol, DC1 indicates the read instantaneous value |
| AAA is the address code of the slave machine, that is, the address of the XMA5000 display meter. |
| BB indicates the channel number. The value is 01 when the instantaneous value is read. |
| ETX is also a control symbol of the standard ASCII code. The code value is 03 H. |
| In the XMA5000 communication protocol, ETX indicates the host Terminator |
------ + */
Char lpOutBuffer [7];
Memset (lpOutBuffer, ''\ 0'', 7); // the first seven bytes are cleared first.
LpOutBuffer [0] = ''\ x11''; // The 1st bytes of the sending buffer are DC1.
LpOutBuffer [1] = '0'; // 2nd bytes are 0 (30 H) characters)
LpOutBuffer [2] = '0'; // 3rd bytes are 0 (30 H) characters)
LpOutBuffer [3] = '1'; // 4th bytes are characters 1 (31 H)
LpOutBuffer [4] = '0'; // 5th bytes are 0 (30 H) characters)
LpOutBuffer [5] = '1'; // 6th bytes are characters 1 (31 H)
LpOutBuffer [6] = ''\ x03''; // 7th bytes are the character ETX
// The code in this section shows that the instrument communication address is 001.
DWORD dwBytesWrite = 7;
COMSTAT ComStat;
DWORD dwErrorFlags;
BOOL bWriteStat;
ClearCommError (hCom, & dwErrorFlags, & ComStat );
BWriteStat = WriteFile (hCom, lpOutBuffer, dwBytesWrite, & dwBytesWrite, NULL );
If (! BWriteStat)
{
AfxMessageBox ("failed to write the serial port! ");
}
}
Void CRS485CommDlg: OnReceive ()
{
// TODO: Add your control notification handler code here
Char str [100];
Memset (str, ''\ 0 ', 100 );
DWORD wCount = 100; // number of bytes read
BOOL bReadStat;
BReadStat = ReadFile (hCom, str, wCount, & wCount, NULL );
If (! BReadStat)
AfxMessageBox ("failed to read the serial port! ");
PurgeComm (hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );
M_disp = str;
UpdateData (FALSE );
}
// You can observe the returned string, which is the same as the display value of the instrument. You can perform corresponding string operations to retrieve the display value of the instrument.
// Open ClassWizard, add the CString type variable m_disp to the static text box IDC_DISP, and add the corresponding function of WM_CLOSE:
Void CRS485CommDlg: OnClose ()
{
// TODO: Add your message handler code here and/or call default
CloseHandle (hCom); // close the serial port when the program exits
CDialog: OnClose ();
}
// Configure //--------------------------------------------------------------------------------------------------
// Configure //--------------------------------------------------------------------------------------------------
// The corresponding part of the program has been described in detail in the code. Connect the hardware part, compile and run the program, and carefully understand the serial synchronous operation part.
// Routine 2
/* ------ + -------
Open VC ++ 6.0, create a project RS485Comm Based on the dialog box, and add two buttons in the idd_rs485comm_dicomm window of the Main Dialog Box,
The IDS are IDC_SEND and IDC_RECEIVE, And the titles are "send" and "receive" respectively. Add a static text box IDC_DISP for display.
Content received by the serial port. Add the global variable to the RS485CommDlg. cpp file:
/* ------ + ------*/
HANDLE hCom; // global variable,
// Add the following code to the OnInitDialog () function of the serial port handle in the RS485CommDlg. cpp file:
HCom = CreateFile ("COM1", // COM1 port
GENERIC_READ | GENERIC_WRITE, // read and write are allowed.
0, // exclusive mode
NULL,
OPEN_EXISTING, // open rather than create
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, // overlap Mode
NULL );
If (hCom = (HANDLE)-1)
{
AfxMessageBox ("failed to open COM! ");
Return FALSE;
}
SetupComm (hCom, 100,100); // the size of the input buffer and output buffer is 100
COMMTIMEOUTS TimeOuts;
// Set read timeout
TimeOuts. ReadIntervalTimeout = MAXDWORD;
TimeOuts. ReadTotalTimeoutMultiplier = 0;
TimeOuts. ReadTotalTimeoutConstant = 0;
// After reading the content of the input buffer, the read operation will return immediately,
// Whether or not the required characters are read.
// Set write timeout
TimeOuts. WriteTotalTimeoutMultiplier = 100;
TimeOuts. WriteTotalTimeoutConstant = 500;
SetCommTimeouts (hCom, & TimeOuts); // set timeout
DCB dcb;
GetCommState (hCom, & dcb );
Dcb. BaudRate = 9600; // The 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 );
// Double-click the IDC_SEND button and the IDC_RECEIVE button respectively to add the response functions of the two buttons:
Void CRS485CommDlg: OnSend ()
{
// TODO: Add your control notification handler code here
OVERLAPPED m_osWrite;
Memset (& m_osWrite, 0, sizeof (OVERLAPPED ));
M_osWrite.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL );
Char lpOutBuffer [7];
Memset (lpOutBuffer, ''\ 0'', 7 );
LpOutBuffer [0] = ''\ x11 '';
LpOutBuffer [1] = '0 '';
LpOutBuffer [2] = '0 '';
LpOutBuffer [3] = '1 '';
LpOutBuffer [4] = '0 '';
LpOutBuffer [5] = '1 '';
LpOutBuffer [6] = ''\ x03 '';
DWORD dwBytesWrite = 7;
COMSTAT ComStat;
DWORD dwErrorFlags;
BOOL bWriteStat;
ClearCommError (hCom, & dwErrorFlags, & ComStat );
BWriteStat = WriteFile (hCom, lpOutBuffer,
DwBytesWrite, & dwBytesWrite, & m_osWrite );
If (! BWriteStat)
{
If (GetLastError () = ERROR_IO_PENDING)
{
WaitForSingleObject (m_osWrite.hEvent, 1000 );
}
}
}
Void CRS485CommDlg: OnReceive ()
{
// TODO: Add your control notification handler code here
OVERLAPPED m_osRead;
Memset (& m_osRead, 0, sizeof (OVERLAPPED ));
M_osRead.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL );
COMSTAT ComStat;
DWORD dwErrorFlags;
Char str [100];
Memset (str, ''\ 0 ', 100 );
DWORD dwBytesRead = 100; // number of bytes read
BOOL bReadStat;
ClearCommError (hCom, & dwErrorFlags, & ComStat );
DwBytesRead = min (dwBytesRead, (DWORD) ComStat. cbInQue );
BReadStat = ReadFile (hCom, str,
DwBytesRead, & dwBytesRead, & m_osRead );
If (! BReadStat)
{
If (GetLastError () = ERROR_IO_PENDING) // The GetLastError () function returns ERROR_IO_PENDING, indicating that the serial port is reading
{
WaitForSingleObject (m_osRead.hEvent, 2000 );
// Use the WaitForSingleObject function to wait until the read operation is completed or the delay has reached 2 seconds.
// After the serial port read operation is complete, the hEvent event of m_osRead will become a signal
}
}
PurgeComm (hCom, PURGE_TXABORT |
PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );
M_disp = str;
UpdateData (FALSE );
}
// Open ClassWizard, add the CString type variable m_disp to the static text box IDC_DISP, and add the corresponding function of WM_CLOSE:
Void CRS485CommDlg: OnClose ()
{
// TODO: Add your message handler code here and/or call default
CloseHandle (hCom); // close the serial port when the program exits
CDialog: OnClose ();
}
// You can carefully compare the two routines to see the differences between synchronous and asynchronous operations on the serial port.
Author: "Love forever"