//串行设备句柄;
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会阻塞线程,窗口就卡死了。。。 单线程用异步串口可以,但并不好,异步方式,窗口界面一般你还需要用个定时器,定时来查询通讯是否完成,何必这么麻烦,实时性又差欢迎分享,转载请注明来源:内存溢出
评论列表(0条)