C++ 串口API 异步 *** 作

C++ 串口API 异步 *** 作,第1张

初始化:

//串行设备句柄;

HANDLE hComDev=0

//串口打开标志;

BOOL bOpen=FALSE

//线程同步事件句柄;

HANDLE hEvent=0

DCB dcb

COMMTIMEOUTS timeouts

//设备已打开

if(bOpen) return FALSE

//打开COM1

if((hComDev=CreateFile(“COM1”,GENERIC�READ|GENERIC�WRITE,0,NULL,OPEN�EXISTING,FILE�ATTRIBUTE�NORMAL,NULL))==INVALID�HANDLE�VALUE)

return FALSE

//设置超时控制

SetCommTimeouts(hComDev,&timeouts)

//设置接收缓冲区和输出缓冲区的大小

SetupComm(hComDev,1024,512)

//获取缺省的DCB结构的值

GetCommState(hComDev,&dcb)

//设定波特率为9600 bps

dcb.BaudRate=CBR�9600

//设定无奇偶校验

dcb.fParity=NOPARITY

//设定数据位为8

dcb.ByteSize=8

//设定一个停止位

dcb.StopBits=ONESTOPBIT

//监视串口的错误和接收到字符两种事件

SetCommMask(hComDev,EV�ERR|EV�RXCHAR)

//设置串行设备控制参数

SetCommState(hComDev,&dcb)

//设备已打开

bOpen=TRUE

//创建人工重设、未发信号的事件

hEvent=CreateEvent(NULL,FALSE,FALSE,

“WatchEvent”)

//创建一个事件监视线程来监视串口事件

AfxBeginThread(CommWatchProc,pParam)

}

数据发送

数据发送利用WriteFile()函数实现。对于同步I/O *** 作,它的最后一个参数可为NULL;而对异步I/O *** 作,它的最后一个参数必需是一个指向OVERLAPPED结构的指针,通过OVERLAPPED结构来获得当前的 *** 作状态。

BOOL WriteComm(LPCVOID lpSndBuffer,DWORD dwBytesToWrite)

{

//lpSndBuffer为发送数据缓冲区指针,

dwBytesToWrite为将要发送的字节长度

//设备已打开

BOOL bWriteState

//实际发送的字节数

DWORD dwBytesWritten

//设备未打开

if(!bOpen) return FALSE

bWriteState=WriteFile(hComDev,lpSndBuffer,dwBytesToWrite,&dwBytesWritten,NULL)

if(!bWriteState || dwBytesToWrite!=dwBytesWritten)

//发送失败

return FALSE

else

//发送成功

return TRUE

}

数据接收

接收数据的任务由ReadFile函数完成。该函数从串口接收缓冲区中读取数据,读取数据前,先用ClearCommError函数获得接收缓冲区中的字节数。接收数据时,同步和异步读取的差别同发送数据是一样的。

DWORD ReadComm(LPVOID lpInBuffer,DWORD dwBytesToRead)

{

//lpInBuffer为接收数据的缓冲区指针, dwBytesToRead为准备读取的数据长度(字节数)

//串行设备状态结构

COMSTAT ComStat

DWORD dwBytesRead,dwErrorFlags

//设备未打开

if(!bOpen) return 0

//读取串行设备的当前状态

ClearCommError(hComDev,&dwErrorFlags,&ComStat)

//应该读取的数据长度

dwBytesRead=min(dwBytesToRead,ComStat.cbInQue)

if(dwBytesRead>0)

//读取数据

if(!ReadFile(hComDev,lpInBuffer,dwBytesRead,&dwBytesRead,NULL))

dwBytesRead=0

return dwBytesRead

}

事件监视线程

事件监视线程对串口事件进行监视,当监视的事件发生时,监视线程可将这个事件发送(SendMessage)或登记(PostMessage)到对事件进行处理的窗口类(由pParam指定)中。

UINT CommWatchProc(LPVOID pParam)

{

DWORD dwEventMask=0//发生的事件;

while(bOpen)

{

//等待监视的事件发生

WaitCommEvent(hComDev, &dwEventMask,NULL)

if ((dwEventMask & EV�RXCHAR)==EV�RXCHAR)

……//接收到字符事件后,可以将此消息登记到由pParam有指定的窗口类中进行处理

if(dwEventMask & EV�ERR)==EV�ERROR)

……//发生错误时的处理

}

SetEvent(hEvent)

//发信号,指示监视线程结束

return 0

}

关闭串行设备

在整个应用程序结束或不再使用串行设备时,应将串行设备关闭,包括取消事件监视,将设备打开标志bOpen置为FALSE以使事件监视线程结束,清除发送/接收缓冲区和关闭设备句柄。

void CloseSynComm()

{

if(!bOpen) return

//结束事件监视线程

bOpen=FALSE

SetCommMask(hComDev,0)

//取消事件监视,此时监视线程中的WaitCommEvent将返回

WaitForSingleObject(hEvent,INFINITE)

//等待监视线程结束

CloseHandle(hEvent)//关闭事件句柄

//停止发送和接收数据,并清除发送和接收缓冲区

PurgeComm(hComDev,PURGE�TXABORT| PURGE�RXABORT|PURGE�TXCLEAR|PURGE�RXCLEAR)

//关闭设备句柄

CloseHandle(hComDev)

}

:异步串口可以不用,同步阻塞方式必须用,否则调用readfile writefile会阻塞线程,窗口就卡死了。。。 单线程用异步串口可以,但并不好,异步方式,窗口界面一般你还需要用个定时器,定时来查询通讯是否完成,何必这么麻烦,实时性又差


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/11740341.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-18
下一篇 2023-05-18

发表评论

登录后才能评论

评论列表(0条)

保存