基本信息
源码名称: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);
}
}
}