基本信息
源码名称:c++ 串口通信
源码大小:12.55M
文件格式:.rar
开发语言:C/C++
更新时间:2020-11-26
友情提示:(无需注册或充值,赞助后即可获取资源下载链接)
嘿,亲!知识可是无价之宝呢,但咱这精心整理的资料也耗费了不少心血呀。小小地破费一下,绝对物超所值哦!如有下载和支付问题,请联系我们QQ(微信同号):813200300
本次赞助数额为: 2 元×
微信扫码支付:2 元
×
请留下您的邮箱,我们将在2小时内将文件发到您的邮箱
源码介绍
#include "StdAfx.h" #include "SerialComm.h" CSerialComm::CSerialComm(void) { m_recvData = ""; m_bConnected = FALSE; m_pThread = NULL; } CSerialComm::~CSerialComm(void) { if(m_bConnected) //程序结束时删除线程、关闭串口操作 closeConnection(); if(m_hPostMsgEvent) //删除事件句柄 CloseHandle(m_hPostMsgEvent); if(m_osRead.hEvent) CloseHandle(m_osRead.hEvent); if(m_osWrite.hEvent) CloseHandle(m_osWrite.hEvent); } BOOL CSerialComm::openConnection(CString commno, UINT8 baud, UINT8 datalen, UINT8 stopbit, UINT8 parity) { if((baud > COMM_BAUD_115200) || (datalen > COMM_DATA_LEN_8) || (stopbit > COMM_STOP_BIT_2) || (parity > COMM_SPACE_PARITY)) { m_bConnected = FALSE; AfxMessageBox(_T("串口参数设置错误")); return FALSE; } m_hPostMsgEvent = CreateEvent(NULL, TRUE, TRUE, NULL); if(m_hPostMsgEvent == NULL) return FALSE; memset(&m_osRead, 0, sizeof(OVERLAPPED)); memset(&m_osWrite, 0, sizeof(OVERLAPPED)); m_osRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); //为重叠读创建事件对象,手工重置,初始化为无信号 if(m_osRead.hEvent == NULL) return FALSE; m_osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); //为重叠写创建事件对象,手工重置,初始化为无信号 if(m_osWrite.hEvent == NULL) return FALSE; m_hComm = CreateFile(commno, //打开串口 GENERIC_READ | GENERIC_WRITE, //允许对设备进行读写访问 0, //独占方式 NULL, // OPEN_EXISTING, //打开而不是创建 FILE_FLAG_OVERLAPPED, //使用异步通信 NULL); if(m_hComm == (HANDLE)-1) { m_bConnected = FALSE; AfxMessageBox(_T("打开串口失败")); return FALSE; } else { SetupComm(m_hComm, MAXBLOCK, MAXBLOCK); //输入缓冲区和输出缓冲区的大小都是1024 SetCommMask(m_hComm, EV_RXCHAR | EV_TXEMPTY ); //设置事件驱动的类型 COMMTIMEOUTS TimeOuts; TimeOuts.ReadIntervalTimeout = MAXDWORD; //时间间隔设为最大,设为0会导致ReadFile立即返回并完成操作 TimeOuts.ReadTotalTimeoutMultiplier = 0; TimeOuts.ReadTotalTimeoutConstant = 0; TimeOuts.WriteTotalTimeoutMultiplier = 50; //设置写超时用于GetOverlapperResult函数的等待时间 TimeOuts.WriteTotalTimeoutConstant = 2000; SetCommTimeouts(m_hComm, &TimeOuts); //设置超时 //PurgeComm(m_hComm, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ); //清干净输入、输出缓冲区 if(!configureConnection(commno, baud, datalen, stopbit, parity)) { CloseHandle(m_hComm); return FALSE; } return TRUE; } } BOOL CSerialComm::configureConnection(CString commno, UINT8 baud, UINT8 datalen, UINT8 stopbit, UINT8 parity) { DCB dcb; if(!GetCommState(m_hComm, &dcb)) //读串口原来的参数设置 return false; switch(baud) //波特率 { case COMM_BAUD_2400: dcb.BaudRate = 2400; break; case COMM_BAUD_4800: dcb.BaudRate = 4800; break; case COMM_BAUD_9600: dcb.BaudRate = 9600; break; case COMM_BAUD_19200: dcb.BaudRate = 19200; break; case COMM_BAUD_38400: dcb.BaudRate = 38400; break; case COMM_BAUD_115200: dcb.BaudRate = 115200; break; default: break; } switch(datalen) //字节数 { case COMM_DATA_LEN_5: dcb.ByteSize = 5; break; case COMM_DATA_LEN_6: dcb.ByteSize = 6; break; case COMM_DATA_LEN_7: dcb.ByteSize = 7; break; case COMM_DATA_LEN_8: dcb.ByteSize = 8; break; default: break; } switch(stopbit) //停止位 { case COMM_STOP_BIT_1: dcb.StopBits = ONESTOPBIT; break; case COMM_STOP_BIT_1_5: dcb.StopBits = ONE5STOPBITS; break; case COMM_STOP_BIT_2: dcb.StopBits = TWOSTOPBITS; break; default: break; } switch(parity) //校验 { case COMM_NONE_PARITY: dcb.Parity = NOPARITY; break; case COMM_ODD_PARITY: dcb.Parity = ODDPARITY; break; case COMM_EVEN_PARITY: dcb.Parity = EVENPARITY; break; case COMM_MARK_PARITY: dcb.Parity = MARKPARITY; break; case COMM_SPACE_PARITY: dcb.Parity = SPACEPARITY; break; default: break; } return SetCommState(m_hComm, &dcb); } void CSerialComm::closeConnection() { if(!m_bConnected) return ; m_bConnected = FALSE; SetEvent(m_hPostMsgEvent); //结束commProc线程中WaitSingleObject函数的等待 SetCommMask(m_hComm, 0); //结束commProc线程中WaitCommEvent的等待 WaitForSingleObject(m_pThread->m_hThread, INFINITE); //等待辅助线程终止 m_pThread = NULL; CloseHandle(m_hComm); } DWORD CSerialComm::writeComm(char *buf, DWORD len) { BOOL ret; DWORD length = len; DWORD errorflags; COMSTAT comstat; ClearCommError(m_hComm, &errorflags, &comstat); ret = WriteFile(m_hComm, buf, length, &length, &m_osWrite); if(!ret) { if(GetLastError() == ERROR_IO_PENDING) { GetOverlappedResult(m_hComm, &m_osWrite, &length, TRUE); //等待 } else { length = 0; } } return length; } DWORD CSerialComm::readComm(char *pbuf, DWORD len) { DWORD length = 0; DWORD errorflags; COMSTAT comstat; ClearCommError(m_hComm, &errorflags, &comstat); length = min(len, comstat.cbInQue); ReadFile(m_hComm, pbuf, length, &length, &m_osRead); return length; } void CSerialComm::enumerateSerialPorts(CUIntArray& ports) { //Make sure we clear out any elements which may already be in the array ports.RemoveAll(); //Determine what OS we are running on OSVERSIONINFO osvi; osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); BOOL bGetVer = GetVersionEx(&osvi); //On NT use the QueryDosDevice API if (bGetVer && (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)) { //Use QueryDosDevice to look for all devices of the form COMx. This is a better //solution as it means that no ports have to be opened at all. TCHAR szDevices[65535]; DWORD dwChars = QueryDosDevice(NULL, szDevices, 65535); if (dwChars) { int i = 0; for ( ;; ) { //Get the current device name TCHAR* pszCurrentDevice = &szDevices[i]; //If it looks like "COMX" then //add it to the array which will be returned int nLen = _tcslen(pszCurrentDevice); if (nLen > 3 && _tcsnicmp(pszCurrentDevice, _T("COM"), 3) == 0) { //Work out the port number int nPort = _ttoi(&pszCurrentDevice[3]); ports.Add(nPort); } // Go to next NULL character while(szDevices[i] != _T('\0')) i ; // Bump pointer to the next string i ; // The list is double-NULL terminated, so if the character is // now NULL, we're at the end if (szDevices[i] == _T('\0')) break; } } else TRACE(_T("Failed in call to QueryDosDevice, GetLastError:%d\n"), GetLastError()); } else { //On 95/98 open up each port to determine their existence //Up to 255 COM ports are supported so we iterate through all of them seeing //if we can open them or if we fail to open them, get an access denied or general error error. //Both of these cases indicate that there is a COM port at that number. for (UINT i=1; i<256; i ) { //Form the Raw device name 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(); //Check to see if the error was because some other app had the port open or a general failure if (dwError == ERROR_ACCESS_DENIED || dwError == ERROR_GEN_FAILURE) bSuccess = TRUE; } else { //The port was opened successfully bSuccess = TRUE; //Don't forget to close the port, since we are going to do nothing with it anyway CloseHandle(hPort); } //Add the port number to the array which will be returned if (bSuccess) ports.Add(i); } } }