This is a simple example to connect a RS232 device. It supports following parameters:
- Com Port: COM1~COM11
- Baud Rate: 110, 300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800 and 921600
- Data Bit: 7 and 8
- Stop Bit: 1, 1.5 and 2
- Parity: no parity, odd, even, mark and space
- Flow Control: hardware, Xon/Xoff and none
// RS232_ConnectionDlg.cpp : implementation file // #include "stdafx.h" #include "RS232_Connection.h" #include "RS232_ConnectionDlg.h" #include "afxdialogex.h" #ifdef _DEBUG #define new DEBUG_NEW #endif struct THREAD_INFO { CString csCMD; //HandlerCallback hCMD; //for CALLBACK function HWND hWnd; }Thread_Info; //--------------------------------------------------------------------------- UINT StartCOMThread(LPVOID param) { THREAD_INFO *Thread_Info = (THREAD_INFO*)param; CRS232_ConnectionDlg *TheDlg = (CRS232_ConnectionDlg*) (Thread_Info->hWnd); TheDlg->ComReceive(Thread_Info->csCMD); return 0; } //--------------------------------------------------------------------------- // CAboutDlg dialog used for App About class CAboutDlg : public CDialogEx { public: CAboutDlg(); // Dialog Data enum { IDD = IDD_ABOUTBOX }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support // Implementation protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx) END_MESSAGE_MAP() // CRS232_ConnectionDlg dialog CRS232_ConnectionDlg::CRS232_ConnectionDlg(CWnd* pParent /*=NULL*/) : CDialogEx(CRS232_ConnectionDlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CRS232_ConnectionDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Control(pDX, IDC_COMBO_ComPort, m_ComPort); DDX_Control(pDX, IDC_COMBO_BaudRate, m_BaudRate); DDX_Control(pDX, IDC_COMBO_DataBit, m_DataBit); DDX_Control(pDX, IDC_COMBO_StopBit, m_StopBit); DDX_Control(pDX, IDC_COMBO_Parity, m_Parity); DDX_Control(pDX, IDC_COMBO_FlowControl, m_FlowControl); DDX_Control(pDX, IDC_CHECK_LineFeed, m_LineFeed); DDX_Control(pDX, IDC_Echo, m_Echo); DDX_Control(pDX, IDC_CHECK_Recv_LineFeed, m_RecvLineFeed); DDX_Control(pDX, IDC_EDIT_SendMessage, m_SendMessage); DDX_Control(pDX, IDC_LIST_SendRecvHistory, m_ListSendRecvHistory); DDX_Control(pDX, IDC_CHECK_RecvDataAuto, m_RecvAuto); DDX_Control(pDX, IDC_BUTTON_Recv, m_BtnRecv); DDX_Control(pDX, IDC_STATIC_img, m_ConnectStatusImg); DDX_Control(pDX, IDC_BUTTON_Connect, m_BtnConnect); DDX_Control(pDX, IDC_BUTTON_Send, m_BtnSend); } BEGIN_MESSAGE_MAP(CRS232_ConnectionDlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_BUTTON_Connect, &CRS232_ConnectionDlg::OnBnClickedButtonConnect) ON_BN_CLICKED(IDC_BUTTON_Send, &CRS232_ConnectionDlg::OnBnClickedButtonSend) ON_BN_CLICKED(IDC_BUTTON_Recv, &CRS232_ConnectionDlg::OnBnClickedButtonRecv) END_MESSAGE_MAP() // CRS232_ConnectionDlg message handlers BOOL CRS232_ConnectionDlg::OnInitDialog() { CDialogEx::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { BOOL bNameValid; CString strAboutMenu; bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX); ASSERT(bNameValid); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon //List Com Port CString csPort; for(int i = 1 ; i < 12 ; i++) { csPort.Format("COM%d", i); m_ComPort.AddString(csPort); } m_ComPort.SetCurSel(0); //List Baud Rate m_BaudRate.AddString("110"); m_BaudRate.AddString("300"); m_BaudRate.AddString("1200"); m_BaudRate.AddString("2400"); m_BaudRate.AddString("4800"); m_BaudRate.AddString("9600"); m_BaudRate.AddString("19200"); m_BaudRate.AddString("38400"); m_BaudRate.AddString("57600"); m_BaudRate.AddString("115200"); m_BaudRate.AddString("230400"); m_BaudRate.AddString("460800"); m_BaudRate.AddString("921600"); m_BaudRate.SetCurSel(5); //List Data Bit m_DataBit.AddString("7"); m_DataBit.AddString("8"); m_DataBit.SetCurSel(0); //List Stop Bit m_StopBit.AddString("1"); m_StopBit.AddString("1.5"); m_StopBit.AddString("2"); m_StopBit.SetCurSel(0); //List Parity m_Parity.AddString("No parity"); m_Parity.AddString("Odd"); m_Parity.AddString("Even"); m_Parity.AddString("Mark"); m_Parity.AddString("Space"); m_Parity.SetCurSel(0); //List Flow Control m_FlowControl.AddString("Hardware"); m_FlowControl.AddString("Xon/Xoff"); m_FlowControl.AddString("None"); m_FlowControl.SetCurSel(0); //Insert ListControl Column m_ListSendRecvHistory.InsertColumn(0,"<->",LVCFMT_LEFT,40); m_ListSendRecvHistory.InsertColumn(1,"Time",LVCFMT_LEFT,120); m_ListSendRecvHistory.InsertColumn(2,"Message",LVCFMT_LEFT,240); m_RecvAuto.SetCheck(true); return TRUE; // return TRUE unless you set the focus to a control } void CRS232_ConnectionDlg::EnableCOMSetting(bool enable) { m_ComPort.EnableWindow(enable); m_BaudRate.EnableWindow(enable); m_DataBit.EnableWindow(enable); m_StopBit.EnableWindow(enable); m_Parity.EnableWindow(enable); m_FlowControl.EnableWindow(enable); m_LineFeed.EnableWindow(enable); m_RecvLineFeed.EnableWindow(enable); m_BtnSend.EnableWindow(!enable); m_RecvAuto.EnableWindow(enable); } bool CRS232_ConnectionDlg::ComOpen(int iComNo, int iBaudRate, int iDataBit, int iStopBit, int iParityCheck) { if(m_hComm != NULL) ComClose(); iComNo++; if(iComNo < 1 && iComNo > 10) iComNo = 1; switch(iBaudRate) { case 0: iBaudRate = 110; break; case 1: iBaudRate = 300; break; case 2: iBaudRate = 1200; break; case 3: iBaudRate = 2400; break; case 4: iBaudRate = 4800; break; case 5: iBaudRate = 9600; break; case 6: iBaudRate = 19200; break; case 7: iBaudRate = 38400; break; case 8: iBaudRate = 57600; break; case 9: iBaudRate = 115200; break; case 10: iBaudRate = 230400; break; case 11: iBaudRate = 460800; break; case 12: iBaudRate = 921600; break; default: iBaudRate = 9600; break; } switch(iDataBit) { case 0: iDataBit = 7; break; default: iDataBit = 8; break; } DCB PortDCB; COMMTIMEOUTS CommTimeouts; CString cs; cs.Format("COM%d", iComNo); // Open the serial port. m_hComm = CreateFile(cs, // Pointer to the name of the port GENERIC_READ | GENERIC_WRITE, // Access (read/write) mode 0, // Share mode NULL, // Pointer to the security attribute OPEN_EXISTING,// How to open the serial port 0, // Port attributes NULL); // Handle to port with attribute if(m_hComm == INVALID_HANDLE_VALUE) { MessageBox("Open com port fails.","Error", MB_ICONERROR | MB_OK); return FALSE; } PortDCB.DCBlength = sizeof (DCB); // Get the default port setting information. GetCommState (m_hComm, &PortDCB); // Change the DCB structure settings. PortDCB.BaudRate = iBaudRate; // Current baud PortDCB.ByteSize = iDataBit; // Number of bits/bytes, 4-8 PortDCB.Parity = iParityCheck; // 0-4=no,odd,even,mark,space PortDCB.StopBits = iStopBit; // 0,1,2 = 1, 1.5, 2 if(iParityCheck > 0) PortDCB.fParity = TRUE; // Enable parity checking. else PortDCB.fParity = FALSE; // Disable parity checking. PortDCB.fBinary = FALSE; // Binary mode; no EOF check PortDCB.fOutxCtsFlow = FALSE; // No CTS output flow control PortDCB.fOutxDsrFlow = FALSE; // No DSR output flow control PortDCB.fDtrControl = DTR_CONTROL_DISABLE; // DTR flow control type PortDCB.fDsrSensitivity = FALSE; // DSR sensitivity PortDCB.fTXContinueOnXoff = FALSE; // XOFF continues Tx PortDCB.fOutX = FALSE; // No XON/XOFF out flow control PortDCB.fInX = FALSE; // No XON/XOFF in flow control PortDCB.fErrorChar = FALSE; // Disable error replacement. PortDCB.fNull = TRUE; // Disable null stripping. PortDCB.fRtsControl = RTS_CONTROL_HANDSHAKE;//RTS_CONTROL_DISABLE; // RTS flow control PortDCB.fAbortOnError = FALSE; // Do not abort reads/writes on error. // Configure the port according to the specifications of the DCB structure. if (!SetCommState (m_hComm, &PortDCB)) { MessageBox("Setting com DCB structure fails.","Error", MB_ICONERROR | MB_OK); ComClose(); return false; } // Retrieve the time-out parameters for all read and write operations on the port. GetCommTimeouts(m_hComm, &CommTimeouts); // Change the COMMTIMEOUTS structure settings. CommTimeouts.ReadIntervalTimeout = MAXDWORD; CommTimeouts.ReadTotalTimeoutMultiplier = 0; CommTimeouts.ReadTotalTimeoutConstant = 0; CommTimeouts.WriteTotalTimeoutMultiplier = 10; // 10 CommTimeouts.WriteTotalTimeoutConstant = 1000; // 1000 // Set the time-out parameters for all read and write operations on the port. if (!SetCommTimeouts(m_hComm, &CommTimeouts)) { MessageBox("Setting com timeout parameters fails.","Error", MB_ICONERROR | MB_OK); ComClose(); return false; } EscapeCommFunction(m_hComm, SETDTR); EscapeCommFunction(m_hComm, SETRTS); ComClear(); return true; } bool CRS232_ConnectionDlg::IsComOpen() { if(m_hComm != NULL) return true; else return false; } bool CRS232_ConnectionDlg::ComSend(char *buffer, int iSize) { unsigned long iLength = 0; int iErrorCount=0; bool status = true; while(WriteFile(m_hComm, buffer, iSize, &iLength, NULL) == 0) { //retransmission iErrorCount++; if(iErrorCount>5) { status = false; break; } Sleep(100); } return status; } //--------------------------------------------------------------------------- bool CRS232_ConnectionDlg::ComReceive(CString &recvData) { bool bResult; while(IsComOpen()) { unsigned long ulNumRead = 0; char *buffer=new char[128]; memset(buffer,0,128); bResult = ::ReadFile(m_hComm,buffer, 128, &ulNumRead, NULL); if (!bResult && ulNumRead == 0) bResult = false; else recvData.Format("%s",buffer); delete [] buffer; if(!bResult) { break; } Sleep(50); } return bResult; } //--------------------------------------------------------------------------- void CRS232_ConnectionDlg::ComClear() { PurgeComm(m_hComm, PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_RXABORT); } //--------------------------------------------------------------------------- bool CRS232_ConnectionDlg::ComClose() { if(m_hComm == INVALID_HANDLE_VALUE || m_hComm == NULL) { m_hComm = NULL; return true; } bool b = ::CloseHandle(m_hComm) == 0 ? false : true; if(b) m_hComm = NULL; return b; } void CRS232_ConnectionDlg::OnBnClickedButtonConnect() { if(m_LineFeed.GetCheck()) { //Line Feed LF \n //Carriage Return CR \r csLineFeed = "\n"; csCarrierReture = "\r"; } else { csLineFeed = ""; csCarrierReture = ""; } if(m_Echo.GetCheck()) { bEcho = true; } else bEcho = false; if(m_RecvLineFeed.GetCheck()) { csRecvLineFeed = "\n\r"; } else { csRecvLineFeed = ""; } //++++++++++Setting UI++++++++++ if(m_RecvAuto.GetCheck()) bAutoRecv = true; else bAutoRecv = false; m_BtnRecv.ShowWindow(!bAutoRecv); time_t tSysTime; struct tm* ptm_time; char bufTime[2048]; time(&tSysTime); ptm_time = localtime(&tSysTime); strftime(bufTime, sizeof(bufTime), "%Y/%m/%d %H:%M:%S\n", ptm_time); m_ListSendRecvHistory.InsertItem(0,"<->"); //----------Setting UI---------- CString csBtnCaption; m_BtnConnect.GetWindowTextA(csBtnCaption); CBitmap ResultPic; if(csBtnCaption == "Connect") { //++++++++++Connect to RS232++++++++++ bool status; CString csMsg=""; status = ComOpen( m_ComPort.GetCurSel(), //ComNo m_BaudRate.GetCurSel(), //BaudRate m_DataBit.GetCurSel(), //DataBit m_StopBit.GetCurSel(), //StopBit m_Parity.GetCurSel() //ParityCheck ); //----------Connect to RS232---------- if(status) { ResultPic.LoadBitmapA(IDB_BITMAP_CONNECT); m_ConnectStatusImg.SetBitmap(HBITMAP(ResultPic)); m_BtnConnect.SetWindowTextA("Disconnect"); EnableCOMSetting(false); m_ListSendRecvHistory.SetItemText(0,1,bufTime); m_ListSendRecvHistory.SetItemText(0,2,"Connect"); } else { m_ListSendRecvHistory.SetItemText(0,1,bufTime); m_ListSendRecvHistory.SetItemText(0,2,"Connect Fail"); } } else if(csBtnCaption == "Disconnect") { //++++++++++Disconnect RS232++++++++++ bool status = ComClose(); //----------Disconnect RS232---------- if(status) { ResultPic.LoadBitmapA(IDB_BITMAP_DISCONNECT); m_ConnectStatusImg.SetBitmap(HBITMAP(ResultPic)); m_BtnConnect.SetWindowTextA("Connect"); EnableCOMSetting(true); m_ListSendRecvHistory.SetItemText(0,1,bufTime); m_ListSendRecvHistory.SetItemText(0,2,"Disconnect"); } else { m_ListSendRecvHistory.SetItemText(0,1,bufTime); m_ListSendRecvHistory.SetItemText(0,2,"Disconnect Fail"); } } } void CRS232_ConnectionDlg::OnBnClickedButtonSend() { CString csMessage; time_t tSysTime; struct tm* ptm_time; char bufTime[2048]; time(&tSysTime); ptm_time = localtime(&tSysTime); strftime(bufTime, sizeof(bufTime), "%Y/%m/%d %H:%M:%S\n", ptm_time); m_SendMessage.GetWindowTextA(csMessage); m_ListSendRecvHistory.InsertItem(0," ->"); m_ListSendRecvHistory.SetItemText(0,1,bufTime); m_ListSendRecvHistory.SetItemText(0,2,csMessage+csLineFeed+csCarrierReture); if(m_RecvAuto.GetCheck()) bAutoRecv = true; else bAutoRecv = false; m_BtnRecv.ShowWindow(!bAutoRecv); } void CRS232_ConnectionDlg::OnBnClickedButtonRecv() { if(m_hComm != NULL) { //Thread_Info.csCMD = csRecvMsg; //Thread_Info.hCMD = AddMessage; Thread_Info.hWnd = (HWND)theApp.m_hInstance; AfxBeginThread(StartCOMThread, (LPVOID)&Thread_Info, THREAD_PRIORITY_NORMAL); } }