连接界面:

界面初始操作:
m_ComboBaudrate.AddString(_T("9600")); m_ComboBaudrate.AddString(_T("38400")); m_ComboBaudrate.AddString(_T("57600")); m_ComboBaudrate.AddString(_T("115200")); m_ComboBaudrate.SetCurSel(0);
连接串口,获取系统中可用的COM:
void CMyDialog::EnumerateSerialPorts(CUIntArray& ports, CUIntArray& portse, CUIntArray& portsu) { ports.RemoveAll(); portse.RemoveAll(); portsu.RemoveAll(); for(int i = 1; i < 256; i++) { CString sPort; sPort.Format(_T("\\\\.\\COM%d"), i); //Try to open the port BOOL bSuccess = FALSE; HANDLE hPort = ::CreateFile(sPort, GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); if(hPort == INVALID_HANDLE_VALUE) { DWORD dwError = GetLastError(); if(dwError == ERROR_ACCESS_DENIED) { bSuccess = TRUE; portsu.Add(i); //已占用的串口 } } else { //成功打开端口 bSuccess = TRUE; portse.Add(i); //关闭端口 CloseHandle(hPort); } //增加端口到数组 if(bSuccess) ports.Add(i); } } void CMyDialog::AddComm() { EnumerateSerialPorts(ports, portse, portsu); unsigned short uicounter; unsigned short uisetcom; CString str; //获取可用串口个数 uicounter = portse.GetSize(); //如果个数大于0 if(uicounter > 0) { //初始化串口列表框 for(int i = 0; i < uicounter; i++) { uisetcom = portse.ElementAt(i); str.Format(_T("COM%d "), uisetcom); m_ComboSerial.AddString(str); } } m_ComboSerial.SetCurSel(0); }
commComPort类中需要的函数:
写串口:
RetCode CCommPort::ComWriteString(BYTE *pReadBuffer) { RetCode res; DWORD iWriteMaxLength; DWORD iWriteLength; iWriteMaxLength = strlen( (char*)pReadBuffer ); res = WriteData( pReadBuffer, iWriteMaxLength, &iWriteLength ); return res; }
//其中有分析异步同步的操作,不需要异步的可以删掉
RetCode CCommPort::WriteData(BYTE* pBuffer,DWORD iNumberBytesToWrite,DWORD* iNumberBytesWritten) { if(!m_bSyncComm && (m_hReadEvent==NULL || m_hStopEvent==NULL)) { return ERROR_ASYNCCOMMNOTPREPARED; } if(pBuffer==NULL || iNumberBytesToWrite<=0) { return ERROR_BUFFERISNULL; } BOOL bResult; DWORD dwLastError; m_olWriteOverlapped.Offset = 0; m_olWriteOverlapped.OffsetHigh = 0; m_olWriteOverlapped.hEvent = NULL; OVERLAPPED* pOverlapped=(!m_bSyncComm) ? &m_olReadOverlapped : NULL; DWORD tttt; bResult = WriteFile( m_hCommPort,pBuffer,iNumberBytesToWrite,&tttt,pOverlapped ); if ( bResult == FALSE ) { dwLastError = GetLastError(); if ( dwLastError == ERROR_IO_PENDING ) { bResult = GetOverlappedResult( m_hCommPort,pOverlapped,&tttt,TRUE); if ( bResult == FALSE ) { return ERROR_GETASYNCWRITERES; } } else { return ERROR_SERIALPORTWRITE; } } if(iNumberBytesWritten!=NULL) *iNumberBytesWritten=tttt; return Result_OK; }
其中RetCode定义为:
enum RetCode{ Result_OK, ERROR_ASYNCCOMMNOTPREPARED, ERROR_USERABORT, ERROR_COMNOTOPEN, ERROR_OPENCOMFAIL, ERROR_READCOMFAIL, ERROR_READTIMEOUT, ERROR_SERIALPURGE, ERROR_BUFFERISNULL, ERROR_SETUPCOMFAIL, ERROR_RESETREADEVENT, ERROR_GETCOMSTATEFAIL, ERROR_SETCOMSTATEFAIL, ERROR_SERIALPORTWRITE, ERROR_GETASYNCWRITERES, ERROR_CLEARCOMERRORFAIL, ERROR_SETCOMTIMEOUTFAIL, ERROR_NOTREADENOUGHDATA, ERROR_READOPEREXCEPTION
};
读串口信息:
RetCode CCommPort::ComReadString(BYTE *pReadBuffer, DWORD iReadMaxLength, DWORD* piReadLength, DWORD n_Timeout) { RetCode res; memset(pReadBuffer, '\0', iReadMaxLength + 1); res = ReadData( pReadBuffer, iReadMaxLength, piReadLength, n_Timeout ); pReadBuffer[*piReadLength] = '\0'; return res; }
RetCode CCommPort::ReadData(BYTE* pBuffer,DWORD iNumberBytesToRead,DWORD* iNumberBytesRead,DWORD n_Timeout) { if(!m_bSyncComm && (m_hReadEvent==NULL || m_hStopEvent==NULL)) { return ERROR_ASYNCCOMMNOTPREPARED; } if(pBuffer==NULL || iNumberBytesToRead<=0) { return ERROR_BUFFERISNULL; } if(!m_bSyncComm) { if ( ResetEvent( m_hReadEvent ) == FALSE ) { return ERROR_RESETREADEVENT; } } if(iNumberBytesRead!=NULL) *iNumberBytesRead=0; m_olReadOverlapped.Offset = 0; m_olReadOverlapped.OffsetHigh = 0; m_olReadOverlapped.hEvent = m_hReadEvent; OVERLAPPED* pOverlapped=(!m_bSyncComm) ? &m_olReadOverlapped : NULL; DWORD tttt; BOOL res= ReadFile( m_hCommPort, pBuffer, iNumberBytesToRead, &tttt, pOverlapped ); if ( res == FALSE ) { DWORD dwLastError = GetLastError(); if ( dwLastError != ERROR_IO_PENDING ) { return ERROR_READCOMFAIL; } } if(m_bSyncComm)//如果同步通信则直接返回 { if(iNumberBytesRead!=NULL) *iNumberBytesRead=tttt; if(tttt != 0) { return Result_OK; } /* if(tttt==iNumberBytesToRead) return Result_OK; else return ERROR_NOTREADENOUGHDATA; */ } HANDLE ahEventTable[2]; ahEventTable[0] = m_hReadEvent; ahEventTable[1] = m_hStopEvent; DWORD dwResult = WaitForMultipleObjects( 2, ahEventTable, FALSE, n_Timeout ); if ( dwResult == WAIT_TIMEOUT )//读取超时 { CancelIo(m_hCommPort); return ERROR_READTIMEOUT; } else { DWORD dwSignalledHandleIndex = dwResult - WAIT_OBJECT_0; switch ( dwSignalledHandleIndex ) { case 0://读取到数据 GetOverlappedResult(m_hCommPort, &m_olReadOverlapped, &tttt,FALSE); if ( tttt != iNumberBytesToRead ) { CancelIo(m_hCommPort); return ERROR_NOTREADENOUGHDATA; } if(iNumberBytesRead!=NULL) *iNumberBytesRead=tttt; CancelIo(m_hCommPort); return Result_OK; case 1://终止读取 CancelIo(m_hCommPort); return ERROR_USERABORT; default: CancelIo(m_hCommPort); return ERROR_READOPEREXCEPTION; } } }
主类界面操作:

发送消息到串口:
m_StringSendInfo为发送端的CEdit消息内容
m_StringRecvInfo为发送端的CEdit消息内容
void CSerial_ComputerDlg::SendMessage() { int i; BYTE* pBuffer; pBuffer = (BYTE*)malloc(MAX_BYTES + 1); memset(pBuffer, '\0', MAX_BYTES + 1); UpdateData(TRUE); if(m_StringSendInfo == "") { MessageBox(_T("不能发送空数据")); free(pBuffer); return; } for(i = 0; i < m_StringSendInfo.GetLength(); i++) { pBuffer[i] = m_StringSendInfo[i]; } RetCode ret; ret = commComPort.ComWriteString(pBuffer); if(ret != Result_OK) { MessageBox(_T("写入数据失败")); } else { CTime time; time = CTime::GetCurrentTime(); CString temp; if(m_StringRecvInfo != "") { m_StringRecvInfo += "\r\n"; m_StringRecvInfo += "\r\n"; } temp = "发送: "; m_StringRecvInfo += temp; m_StringRecvInfo += time.Format("%Y-%m-%d %H:%M:%S"); m_StringRecvInfo += "\r\n"; temp = pBuffer; m_StringRecvInfo += temp; m_StringSendInfo = ""; UpdateData(FALSE); } free(pBuffer); }
从串口接收消息:
int CSerial_ComputerDlg::RecvMessage() { RetCode ret; DWORD iNumberBytesRead = 0; BYTE *pBuffer; CString tempStr; ret = commComPort.ComWriteString((BYTE*)"\n"); CString temp(""); CTime time; time = CTime::GetCurrentTime(); UpdateData(TRUE); if(m_StringRecvInfo.GetLength() >= MAX_BYTES) { m_StringRecvInfo.Right(m_StringRecvInfo.GetLength() / 2); } pBuffer = (BYTE*)malloc(MAX_BYTES + 1); memset(pBuffer, '\0', MAX_BYTES + 1); //ret = pThisDlg->commComPort.ComWriteString((BYTE*)" "); ret = commComPort.ComReadString(pBuffer, MAX_BYTES, &iNumberBytesRead,100); if(ret != Result_OK) { cprintf(" Release For ret != Result_OK\n"); MessageBox(_T("Read Message Failed!")); free(pBuffer); return -1; } temp = pBuffer; temp.Remove(' '); temp.Remove('\n'); temp.Remove('\r'); if(temp.GetLength() != 0) { m_StringRecvInfo += "\r\n\r\n"; temp = "接收: "; m_StringRecvInfo += temp; temp = time.Format("%Y-%m-%d %H:%M:%S"); m_StringRecvInfo += temp; m_StringRecvInfo += "\r\n"; temp = pBuffer; m_StringRecvInfo += temp; UpdateData(FALSE); m_EditRecvInfo.LineScroll(m_EditRecvInfo.GetLineCount());//保证接收端的滚动条一直在最下 MSG msg; while(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } } free(pBuffer); return 0; }
此代码不支持后台循环读,由于串口的读写具有阻塞性,而尝试过线程去循环读总是阻塞在读上,因此放弃,只实现了发送一次接收一次。
浙公网安备 33010602011771号