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)

}

您好,基本的通信方式偶并行通信和串行掘宴通信两种。一条信息的各位数据被同拦棚时传送的通信方式称为并行通信。一条信息的各位数据被逐位按顺序传送的通讯方式称为串行通信。而串行通信又分为异步通信和同步通信两种方式。在单片机中,主要使用异步通信方式。异步通信方式的特点是:按字符传输的,每传输一个字符就用起始位来进来收、发双方的同步,简散则不会因收发双方的始终频率的小的偏差导致错误,这种传输方式利用每一帧的起、止信号来建立发送与接收之间的同步。谢谢。

个人研究认为串口类的读 *** 作都是同步方法,为了防止同步接受数据时由于超时等问题使主线程死锁,建议使用线程仔余异步接受念冲滚数据,如:

//异步读取

private void AsyReceiveData(object serialPortobj)

{

SerialPort sp = (SerialPort)serialPortobj

System.Threading.Thread.Sleep(1000)

MessageBox.Show(sp.ReadExisting())

sp.Close()

}

//开启接判销收数据线程

private void ReceiveData(SerialPort sp)

{

//异步接收数据线程

Thread threadReceiveSub = new Thread(new Parameterized

ThreadStart(AsyReceiveData))

threadReceiveSub.start}


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

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

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

发表评论

登录后才能评论

评论列表(0条)

保存