实例介绍
【实例简介】
【实例截图】
【实例截图】
【核心代码】
#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);
}
}
}
好例子网口号:伸出你的我的手 — 分享!
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明


网友评论
我要评论