createevent(C++ 串口API 异步操作)
本文目录
C++ 串口API 异步操作
初始化://串行设备句柄; 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); }
请教高人,在C#中怎么写一个API的event,最好能给个实例,只写了一个createevent但不知道怎么弄了
private void ReceiveThread() { byte buf = new Byte; uint gotbytes; bool starting; starting = true; AutoResetEvent sg = new AutoResetEvent(false); Win32Com.OVERLAPPED ov = new Win32Com.OVERLAPPED(); IntPtr unmanagedOv; IntPtr uMask; uint eventMask = 0; unmanagedOv = Marshal.AllocHGlobal(Marshal.SizeOf(ov)); uMask = Marshal.AllocHGlobal(Marshal.SizeOf(eventMask)); ov.Offset = 0; ov.OffsetHigh = 0; ov.hEvent = sg.Handle; Marshal.StructureToPtr(ov, unmanagedOv, true); try { while(true) { if (!Win32Com.SetCommMask(hPort, Win32Com.EV_RXCHAR | Win32Com.EV_TXEMPTY | Win32Com.EV_CTS | Win32Com.EV_DSR | Win32Com.EV_BREAK | Win32Com.EV_RLSD | Win32Com.EV_RING | Win32Com.EV_ERR)) { throw new CommPortException(“IO Error “); } Marshal.WriteInt32(uMask, 0); //JH 1.2: Tells the main thread that this thread is ready for action. if (starting) {startEvent.Set(); starting = false;} if (!Win32Com.WaitCommEvent(hPort, uMask, unmanagedOv)) { if (Marshal.GetLastWin32Error() == Win32Com.ERROR_IO_PENDING) { sg.WaitOne(); } else { throw new CommPortException(“IO Error “); } } eventMask = (uint)Marshal.ReadInt32(uMask); if ((eventMask & Win32Com.EV_ERR) != 0) { UInt32 errs; if (Win32Com.ClearCommError(hPort, out errs, IntPtr.Zero)) { //JH 1.2: BREAK condition has an error flag and and an event flag. Not sure if both //are always raised, so if CE_BREAK is only error flag ignore it and set the EV_BREAK //flag for normal handling. Also made more robust by handling case were no recognised //error was present in the flags. (Thanks to Fred Pittroff for finding this problem!) int ec = 0; StringBuilder s = new StringBuilder(“UART Error: “, 40); if ((errs & Win32Com.CE_FRAME) != 0) {s = s.Append(“Framing,“); ec++;} if ((errs & Win32Com.CE_IOE) != 0) {s = s.Append(“IO,“); ec++;} if ((errs & Win32Com.CE_OVERRUN) != 0) {s = s.Append(“Overrun,“); ec++;} if ((errs & Win32Com.CE_RXOVER) != 0) {s = s.Append(“Receive Cverflow,“); ec++;} if ((errs & Win32Com.CE_RXPARITY) != 0) {s = s.Append(“Parity,“); ec++;} if ((errs & Win32Com.CE_TXFULL) != 0) {s = s.Append(“Transmit Overflow,“); ec++;} if (ec 》 0) { s.Length = s.Length - 1; throw new CommPortException(s.ToString()); } else { if (errs == Win32Com.CE_BREAK) { eventMask |= Win32Com.EV_BREAK; } else { throw new CommPortException(“IO Error “); } } } else { throw new CommPortException(“IO Error “); } } if ((eventMask & Win32Com.EV_RXCHAR) != 0) { do { gotbytes = 0; if (!Win32Com.ReadFile(hPort, buf, 1, out gotbytes, unmanagedOv)) { //JH 1.1: Removed ERROR_IO_PENDING handling as comm timeouts have now //been set so ReadFile returns immediately. This avoids use of CancelIo //which was causing loss of data. Thanks to Daniel Moth for suggesting this //might be a problem, and to many others for reporting that it was! int x = Marshal.GetLastWin32Error(); throw new CommPortException(“IO Error “); } if (gotbytes == 1) OnRxChar(buf); } while (gotbytes 》 0); } if ((eventMask & Win32Com.EV_TXEMPTY) != 0) { //JH1.3: lock(empty) empty = true; OnTxDone(); } if ((eventMask & Win32Com.EV_BREAK) != 0) OnBreak(); uint i = 0; if ((eventMask & Win32Com.EV_CTS) != 0) i |= Win32Com.MS_CTS_ON; if ((eventMask & Win32Com.EV_DSR) != 0) i |= Win32Com.MS_DSR_ON; if ((eventMask & Win32Com.EV_RLSD) != 0) i |= Win32Com.MS_RLSD_ON; if ((eventMask & Win32Com.EV_RING) != 0) i |= Win32Com.MS_RING_ON; if (i != 0) { uint f; if (!Win32Com.GetCommModemStatus(hPort, out f)) throw new CommPortException(“IO Error “); OnStatusChange(new ModemStatus(i), new ModemStatus(f)); } } } catch (Exception e) { //JH 1.3: Added for shutdown robustness (Thanks to Fred Pittroff, Mark Behner and Kevin Williamson!), . Win32Com.CancelIo(hPort); if (uMask != IntPtr.Zero) Marshal.FreeHGlobal(uMask); if (unmanagedOv != IntPtr.Zero) Marshal.FreeHGlobal(unmanagedOv); if (!(e is ThreadAbortException)) { rxException = e; OnRxException(e); } }仅供参考 }
更多文章:
except的用法总结(英语中关于expect besides expect for等表示除了的用法)
2024年7月2日 05:50
为什么编程语言不能是中文(计算机的汇编语言为什么没有中文的版本)
2024年8月11日 01:50
excel函数公式设置颜色(excel怎么用IF函数,改变字体的颜色)
2024年7月16日 17:25
spring festival初一作文(我的春节英语作文 初一水平的)
2024年6月6日 02:28
caution的形容词(caution 和 careful 和 attention的区别和用法是什么)
2024年7月1日 12:15
return to normal(英语Normal font怎么翻译)
2024年7月22日 20:28
c语言课程设计答辩问题(课程设计要答辩 C语言没怎么学 可以简单讲解一下这个程序么 帮忙加一下注释)
2024年8月22日 19:15
dos系统怎么进入(在windows中进入ms-dos有几种方法)
2024年7月14日 16:41
hamburger是什么意思中文(hamburger翻译中文是什么意思)
2024年6月30日 22:28
正则截取部分字符串(python 正则表达式如何截取字符串中间的内容)
2024年10月18日 03:50
大学生自学网app下载(大学生在使用电脑的同时,应该学会哪些对以后工作有用的软件或者技能呢)
2024年5月17日 18:19
matlab编程与工程应用第三版课后答案(MATLAB与系统仿真 试题)
2024年4月21日 13:05