电脑串口接收数据程序.docx
《电脑串口接收数据程序.docx》由会员分享,可在线阅读,更多相关《电脑串口接收数据程序.docx(14页珍藏版)》请在冰豆网上搜索。
电脑串口接收数据程序
本程序用于电脑串口接收数据
SerialPort.h
#ifndefSERIALPORT_H_
#defineSERIALPORT_H_
#include
#include"TChar.h"
#include
#include
#include
#include
#include
#include
#include
#include
usingnamespacestd;
/**串口通信类
*
*本类实现了监听发到指定串口的数据
*/
classCSerialPort
{
public:
CSerialPort(void);
~CSerialPort(void);
public:
/**初始化串口函数
*
*@param:
UINTportNo串口编号,默认值为1,即COM1,注意,尽量不要大于9
*@param:
UINTbaud波特率,默认为9600
*@param:
charparity是否进行奇偶校验,'Y'表示需要奇偶校验,'N'表示不需要奇偶校验
*@param:
UINTdatabits数据位的个数,默认值为8个数据位
*@param:
UINTstopsbits停止位使用格式,默认值为1
*@param:
DWORDdwCommEvents默认为EV_RXCHAR,即只要收发任意一个字符,则产生一个事件
*@return:
bool初始化是否成功
*@note:
在使用其他本类提供的函数前,请先调用本函数进行串口的初始化
* /n本函数提供了一些常用的串口参数设置,若需要自行设置详细的DCB参数,可使用重载函数
*/n本串口类析构时会自动关闭串口,无需额外执行关闭串口
*@see:
*/
//boolInitPort(UINTportNo=3,UINTbaud=CBR_19200,charparity='N',UINTdatabits=8,UINTstopsbits=1,DWORDdwCommEvents=EV_RXCHAR);
boolInitPort(UINTportNo,UINTbaud,charparity,UINTdatabits,UINTstopsbits,DWORDdwCommEvents);
/**串口初始化函数
*
*本函数提供直接根据DCB参数设置串口参数
*@param:
UINTportNo
*@param:
constLPDCB&plDCB
*@return:
bool初始化是否成功
*@note:
本函数提供用户自定义地串口初始化参数
*@see:
*/
boolInitPort(UINTportNo,constLPDCB&plDCB);
/**开启监听线程
*
*本监听线程完成对串口数据的监听,并将接收到的数据打印到屏幕输出
*@return:
bool操作是否成功
*@note:
当线程已经处于开启状态时,返回flase
*@see:
*/
boolOpenListenThread();
/**关闭监听线程
*
*
*@return:
bool操作是否成功
*@note:
调用本函数后,监听串口的线程将会被关闭
*@see:
*/
boolCloseListenTread();
/**获取串口缓冲区中的字节数
*
*
*@return:
UINT操作是否成功
*@note:
当串口缓冲区中无数据时,返回0
*@see:
*/
UINTGetBytesInCOM();
/**读取串口接收缓冲区中的数据
*
*
*@param:
unsignedchar*lpInBuffer存放读取数据的字符变量
*@return:
bool读取是否成功
*@note:
*@see:
*/
boolMyReadFile(unsignedchar*lpInBuffer);
private:
/**打开串口
*
*
*@param:
UINTportNo串口设备号
*@return:
bool打开是否成功
*@note:
*@see:
*/
boolopenPort(UINTportNo);
/**关闭串口
*
*
*@return:
void操作是否成功
*@note:
*@see:
*/
voidClosePort();
/**串口监听线程
*
*监听来自串口的数据和信息
*@param:
void*pParam线程参数
*@return:
UINTWINAPI线程返回值
*@note:
*@see:
*/
staticUINTWINAPIListenThread(void*pParam);
private:
/**串口句柄*/
HANDLEm_hComm;
/**线程退出标志变量*/
staticbools_bExit;
/**线程句柄*/
volatileHANDLEm_hListenThread;
/**同步互斥,临界区保护*/
CRITICAL_SECTIONm_csCommunicationSync;//!
<互斥操作串口
};
#endif//SERIALPORT_H_
/**线程退出标志*/
boolCSerialPort:
:
s_bExit=false;//CSerialPort:
:
为自定义的前缀。
/**当串口无数据时,sleep至下次查询间隔的时间,单位:
秒*/
constUINTSLEEP_TIME_INTERVAL=5;//定义UINTSLEEP_TIME_INTERVAL为一个常量。
UINT:
指无符号整数。
CSerialPort:
:
CSerialPort(void)
:
m_hListenThread(INVALID_HANDLE_VALUE)//INVALID_HANDLE_VALUE实际值等于-1
{
m_hComm=INVALID_HANDLE_VALUE;
m_hListenThread=INVALID_HANDLE_VALUE;
InitializeCriticalSection(&m_csCommunicationSync);
}
CSerialPort:
:
~CSerialPort(void)
{
CloseListenTread();
ClosePort();
DeleteCriticalSection(&m_csCommunicationSync);
}
//初始化串口函数
boolCSerialPort:
:
InitPort(UINTportNo/*=1*/,UINTbaud/*=CBR_9600*/,charparity/*='N'*/,
UINTdatabits/*=8*/,UINTstopsbits/*=1*/,DWORDdwCommEvents/*=EV_RXCHAR*/)
{
/**临时变量,将制定参数转化为字符串形式,以构造DCB结构:
串口通讯中的设置信息,如波特率,奇偶校验位等....*/
charszDCBparam[50];
sprintf_s(szDCBparam,"baud=%dparity=%cdata=%dstop=%d",baud,parity,databits,stopsbits);
/**打开指定串口,该函数内部已经有临界区保护,上面请不要加保护*/
if(!
openPort(portNo))
{
returnfalse;
}
/**进入临界段*/
EnterCriticalSection(&m_csCommunicationSync);
/**是否有错误发生*/
BOOLbIsSuccess=TRUE;
/**
设置输入缓冲区和输出缓冲区的大小都是1024.
*/
if(bIsSuccess)
{
bIsSuccess=SetupComm(m_hComm,1024,1024);
}
/**设置串口的超时时间,均设为0,不使用超时限制*/
COMMTIMEOUTSCommTimeouts;
CommTimeouts.ReadIntervalTimeout=0;
CommTimeouts.ReadTotalTimeoutMultiplier=0;
CommTimeouts.ReadTotalTimeoutConstant=0;
if(bIsSuccess)
{
bIsSuccess=SetCommTimeouts(m_hComm,&CommTimeouts);
}
DCBdcb;
if(bIsSuccess)
{
/**获取当前串口配置参数,并且构造串口DCB参数*/
bIsSuccess=GetCommState(m_hComm,&dcb)&&BuildCommDCB(szDCBparam,&dcb);
/**开启RTSflow控制*/
dcb.fRtsControl=RTS_CONTROL_ENABLE;
}
if(bIsSuccess)
{
/**使用DCB参数配置串口状态*/
bIsSuccess=SetCommState(m_hComm,&dcb);
}
/**清空串口缓冲区*/
PurgeComm(m_hComm,PURGE_RXCLEAR|PURGE_TXCLEAR|PURGE_RXABORT|PURGE_TXABORT);
/**离开临界段*/
LeaveCriticalSection(&m_csCommunicationSync);
returnbIsSuccess==TRUE;
}
//关闭串口
voidCSerialPort:
:
ClosePort()
{
if(m_hComm!
=INVALID_HANDLE_VALUE)
{
CloseHandle(m_hComm);
m_hComm=INVALID_HANDLE_VALUE;
}
}
//打开串口
boolCSerialPort:
:
openPort(UINTportNo)
{
/**进入临界段*/
EnterCriticalSection(&m_csCommunicationSync);
/**把串口的编号转换为设备名*/
charszPort[50];
sprintf_s(szPort,"COM%d",portNo);
/**打开指定的串口*/
m_hComm=CreateFileA(szPort,/**设备名,COM1,COM2等*/
GENERIC_READ,/**只读模式*/
0,/**共享模式,0表示不共享*/
NULL,/**安全性设置,一般使用NULL*/
OPEN_EXISTING,/**该参数表示设备必须存在,否则创建失败*/
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,/**重叠方式*/
0);
/**如果打开失败,释放资源并返回*/
if(m_hComm==INVALID_HANDLE_VALUE)
{
LeaveCriticalSection(&m_csCommunicationSync);
returnfalse;
}
/**退出临界区*/
LeaveCriticalSection(&m_csCommunicationSync);
returntrue;
}
//打开监听线程
boolCSerialPort:
:
OpenListenThread()
{
/**检测线程是否已经开启了*/
if(m_hListenThread!
=INVALID_HANDLE_VALUE)
{
/**线程已经开启*/
returnfalse;
}
s_bExit=false;
/**线程ID*/
UINTthreadId;
/**开启串口数据监听线程*/
m_hListenThread=(HANDLE)_beginthreadex(NULL,0,ListenThread,this,0,&threadId);
/**检测线程是否开启或发生错误了*/
if(!
m_hListenThread)
{
returnfalse;
}
/**设置线程的优先级,高于普通线程*/
if(!
SetThreadPriority(m_hListenThread,THREAD_PRIORITY_ABOVE_NORMAL))
{
returnfalse;
}
returntrue;
}
//关闭监听线程
boolCSerialPort:
:
CloseListenTread()
{
if(m_hListenThread!
=INVALID_HANDLE_VALUE)
{
/**通知线程退出*/
s_bExit=true;
/**等待线程退出*/
Sleep(10);
/**置线程句柄无效*/
CloseHandle(m_hListenThread);
m_hListenThread=INVALID_HANDLE_VALUE;
}
returntrue;
}
//获取串口缓冲区的字节数
UINTCSerialPort:
:
GetBytesInCOM()
{
DWORDdwError=0;/**错误码*/
COMSTATcomstat;/**COMSTAT结构体,记录通信设备的状态信息*/
memset(&comstat,0,sizeof(COMSTAT));
UINTBytesInQue=0;
/**在调用ReadFile和WriteFile之前,通过本函数清除以前遗留的错误标志*/
if(ClearCommError(m_hComm,&dwError,&comstat))
{
BytesInQue=comstat.cbInQue;/**获取在输入缓冲区中的字节数*/
}
returnBytesInQue;
}
//串口监听线程
UINTWINAPICSerialPort:
:
ListenThread(void*pParam)
{
/**得到本类的指针*/
CSerialPort*pSerialPort=reinterpret_cast(pParam);
//线程循环,轮询方式读取串口数据
while(!
pSerialPort->s_bExit)
{
/**获取串口输入缓冲区的字节数据*/
UINTBytesInQue=pSerialPort->GetBytesInCOM();
/**如果串口输入缓冲区中无数据,则休息一会再查询*/
if(BytesInQue==0)
{
Sleep(SLEEP_TIME_INTERVAL);
continue;
}
/**读取输入缓冲区中的数据并输出显示*/
do
{
unsignedcharlpInBuffer[1024];
if(pSerialPort->MyReadFile(lpInBuffer)==true)
{
/**将读取的数据显示到命令行窗口*/
cout<continue;
}
}while(--BytesInQue);
}
return0;
}
boolCSerialPort:
:
MyReadFile(unsignedchar*lpInBuffer)
{
DWORDdwBytesRead=1024;
COMSTATComStat;
DWORDdwErrorFlags;
OVERLAPPEDm_osRead;//创建OVERLAPPED结构。
memset(&m_osRead,0,sizeof(OVERLAPPED));
m_osRead.hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
ClearCommError(m_hComm,&dwErrorFlags,&ComStat);//清除错误
dwBytesRead=min(dwBytesRead,(DWORD)ComStat.cbInQue);
if(m_hComm==INVALID_HANDLE_VALUE)
{
returnfalse;
}
/**临界区保护*/
EnterCriticalSection(&m_csCommunicationSync);
/*等待串口输入缓冲区的输入*/
if(!
dwBytesRead)
returnFALSE;
BOOLbReadStatus;
//从缓冲区读取数据。
bReadStatus=ReadFile(m_hComm,lpInBuffer,dwBytesRead,&dwBytesRead,&m_osRead);//异步读取数据。
if((!
bReadStatus))
{
/*GetLastError()返回ERROR_IO_PENDING,表示串口正在进行读操作*/
if(GetLastError()==ERROR_IO_PENDING)
{
/*表示知道对象被触发信号才返回。
*/
WaitForSingleObject(m_osRead.hEvent,INFINITE);
/*当串口读操作进行完毕后,m_osRead的hEvent时间会变为有信号,清空缓冲区*/
PurgeComm(m_hComm,PURGE_TXABORT|PURGE_RXABORT|PURGE_RXCLEAR|PURGE_RXABORT);
}
/**离开临界区*/
LeaveCriticalSection(&m_csCommunicationSync);
returntrue;
}
returntrue;
}
Main.c
#include"SerialPort.h"
usingnamespacestd;
int_tmain(intargc,_TCHAR*argv[])
{
CSerialPortmySerialPort;//首先将之前定义的类实例化
intlength=8;//定义传输的长度
if(!
mySerialPort.InitPort(2,CBR_9600,'N',8,1,EV_RXCHAR))//串口、波特率、奇偶校验、数据位个数、停止位……
{
std:
:
cout<<"initPortfail!
"<:
endl;
}
else
{
std:
:
cout<<"initPortsuccess!
"<:
endl;
}
if(!
mySerialPort.OpenListenThread())//是否打开监听线程,开启线程用来传输返回值
{
std:
:
cout<<"OpenListenThreadfail!
"<:
endl;
}
else
{
std:
:
cout<<"OpenListenThreadsuccess!
"<:
endl;
}
system("pause");
return0;
}