win32 api 串口编程.doc

上传人:asd****56 文档编号:70333796 上传时间:2023-01-19 格式:DOC 页数:6 大小:85KB
返回 下载 相关 举报
win32 api 串口编程.doc_第1页
第1页 / 共6页
win32 api 串口编程.doc_第2页
第2页 / 共6页
点击查看更多>>
资源描述

《win32 api 串口编程.doc》由会员分享,可在线阅读,更多相关《win32 api 串口编程.doc(6页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、win32 api 串口编程分类:C/C+2007-11-22 14:191158人阅读评论(0)收藏举报一、基本知识 Win32下串口通信与16位串口通信有很大的区别。在Win32下,可以使用两种编程方式实现串口通信,其一是调用的Windows的API函数,其二 是使用ActiveX控件。使用API 调用,可以清楚地掌握串口通信的机制,熟悉各种配置和自由灵活采用不同的流控进行串口通信。下面介绍串口操作的基本知识。打开串口:使用CreateFile()函数,可以打开串口。有两种方法可以打开串口,一种是同步方式(NonOverlapped),另外一种异步方式(Overlapped)。使用Over

2、lapped打开时,适当的方法是:HANDLEhComm;hComm=CreateFile(gszPort,GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0);if(hComm=INVALID_HANDLE_VALUE)/erroropeningport;abort配置串口:1.DCB配置 DCB(Device Control Block)结构定义了串口通信设备的控制设置。许多重要设置都是在DCB结构中设置的,有三种方式可以初始化DCB。(1)通过GetCommState()函数得DCB的初始值,其使用方式为

3、:DCBdcb=0;if(!GetCommState(hComm,dcb)/ErrorgettingcurrentDCBsettingselse/DCBisreadyforuse.(2)用BuildCommDCB()函数初始化DCB结构,该函数填充 DCB的波特率、奇偶校验类型、数据位、停止位。对于流控成员函数设置了缺省值。其用法是:DCBdcb;FillMemory(dcb,sizeof(dcb),0);dcb.DCBlength=sizeof(dcb);if(!BuildCommDCB(“9600,n,8,1,dcb)/CouldntbuildtheDCB.Usuallyaproblem/

4、withthecommunicationsspecificationstring.returnFALSE;else/DCBisreadyforuse.(3)用SetCommState()函数手动设置DCB初值。用法如下:DCBdcb;FillMemory(dcb,sizeof(dcb),0);if(!GetCommState(hComm,dcb)/getcurrentDCB/ErrorinGetCommStatereturnFALSE;/UpdateDCBrate.dcb.BaudRate=CBR_9600;/Setnewstate.if(!SetCommState(hComm,dcb)/Er

5、rorinSetCommState.Possiblyaproblemwiththecommunications/porthandleoraproblemwiththeDCBstructureitself.手动设置DCB值时,DCB的结构的各成员的含义,可以参看MSDN帮助。 2.流控设置 硬件流控:串口通信中的硬件流控有两种,DTE/DSR方式和RTS/CTS方式,这与DCB结构的初始化有关系,DCB结构中的 OutxCtsFlow、 fOutxDsrFlow、fDsrSensitivity、fRtsControl、fDtrControl几个成员的初始值很关键,不同的值代表不同 流控,也可以自

6、己设置流控,但建议采用标准流行的流控方式。采用硬件流控时,DTE、DSR、RTS、CTS的逻辑位直接影响到数据的读写及收发数据的缓 冲区控制。 软件流控:串口通信中采用特殊字符XON和XOFF作为控制串口数据的收发。与此相关的DCB成员是:fOut、fInX、XoffChar、 XonChar、 XoffLim和XonLim。具体含义参见MSDN帮助。 串口读写操作:串口读写有两种方式:同步方式(NonOverlapped)和异步方式(Overlapped)。同步方式是指必须完成了读写操作,函数 才返回,这可能造成程序死掉,因为如果在读写时发生了错误,永远不返回就会出错,可能线程将永远等待在那

7、儿。而异步方式则灵活得多,一旦读写不成功,就将 读写挂起,函数直接返回,可以通过GetLastError函数得知读写未成功的原因,所以常常采用异步方式操作。 读操作:ReadFile()函数用于完成读操作。异步方式的读操作为:DWORDdwRead;BOOLfWaitingOnRead=FALSE;OVERLAPPEDosReader=0;/Createtheoverlappedevent.Mustbeclosedbeforeexiting/toavoidahandleleak.osReader.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);if(osRea

8、der.hEvent=NULL)/Errorcreatingoverlappedevent;abort.if(!fWaitingOnRead)/Issuereadoperation.if(!ReadFile(hComm,lpBuf,READ_BUF_SIZE,dwRead,osReader)if(GetLastError()!=ERROR_IO_PENDING)/readnotdelayed?/Errorincommunications;reportit.elsefWaitingOnRead=TRUE;else/readcompletedimmediatelyHandleASuccessful

9、Read(lpBuf,dwRead); 如果读操作被挂起,可以调用WaitForSingleObject()函数或WaitForMuntilpleObjects()函数等待读操作完成或 者超时发生,再调用 GetOverlappedResult()得到想要的信息。 写操作:与读操作相似,故不详述,调用的API函数是: WriteFile函数。 串口状态: (1)通信事件:用SetCommMask()函数设置想要得到的通信事件的掩码,再调用WaitCommEvent()函数检测通信事件的发生。可设 置的通信事件标志(即SetCommMask()函数所设置的掩码)可以有EV_BREAK、EV_CT

10、S、EV_DSR、 EV_ERR、EV_RING、EV_RLSD、EV_RXCHAR、EV_RXFLAG、EV_TXEMPTY。 注意:1对于EV_RING标志的设置,WIN95是不会返回EV_RING事件的,因为WIN95不检测该事件。2设置EV_RXCHAR,可以检测到 字符到达,但是在绑定此事件和ReadFile()函数一起读取串口接收数据时,可能会出现错误,造成少读字节数,具体原因查看MSDN帮助。可以采用循 环读的办法,另外一个比较好的解决办法是调用ClearCommError()函数,确定在一次读操作中在缓冲区中等待被读的字节数。(2)错误处理和通信状态:在串口通信中,可能会产生很

11、多的错误,使用ClearCommError()函数可以检测错误并且清除错误条件。 (3)Modem状态:用SetcommMask()可以包含很多事件标志,但是这些事件标志只指示在串口线路上的电压变化情况。而调用 GetCommModemStatus()函数可以获得线路上真正的电压状态。 扩展函数:如果应用程序想用自己的流控,可以使用 EscapeCommFunction()函数设置DTR和RTS线路的电平。 通信超时:在通信中,超时是个很重要的考虑因素,因为如果在数据接收过程中由于某种原因突然中断或停止,如果不采取超时控制机制,将会使得I/O线程被挂 起或无限阻塞。串口通信中的超时设置分为两步

12、,首先设置 COMMTIMEOUTS结构的五个变量,然后调用SetcommTimeouts()设置超时值。对于使用异步方式读写的操作,如果操作挂起后,异步成 功完成了读写,WaitForSingleObject()或 WaitForMultipleObjects()函数将返回WAIT_OBJECT_0,GetOverlappedResult()返回TRUE。其 实还可以用GetCommTimeouts()得到系统初始值。 关闭串口:程序结束或需要释放串口资源时,应该正确关闭串口,关闭串口比较简单,使用API调用CloseHandle()关闭串口的句柄就可以了。调用方法为:CloseHandle

13、(hComm); 但是值得注意的是在关闭串口之前必须保证读写串口线程已经退出,否则会引起误操作,一般采用的办法是使用事件驱动机制,启动一事件,通知串口读写线程强制退出,在线程退出之前,通知主线程可以关闭串口。二、实现1.程序设计思路 对于不同的应用程序,虽然界面不同,但是如果采用串口与主机之间的通信,对串口的处理方式大致相似,无非就是通过串口收发数据,对于通过串口接收到的数 据,交给上层软件处理显示,对于上层要发给串口的数据,进行转发。但在实际编程中,由于采用的通信方式和流控不同,串口设置也不同,这就涉及到 DCB的初始化问题和读写串口等细节问题。串口通信应用程序设计的总体思路(即操作过程)是

14、:首先,确定要打开的串口名、波特率、奇偶校验方式、数据位、 停止位,传递给CreateFile()函数打开特定串口;其次,为了保护系统对串口的初始设置,调用 GetCommTimeouts()得到串口的原始超时设置;然后,初始化DCB对象,调用SetCommState() 设置DCB,调用SetCommTimeouts()设置串口超时控制;再次,调用SetupComm()设置串口接收发送数据的缓冲区大小,串口的设置 就基本完成,之后就可以启动读写线程了。一般来说,串口的读写由串口读写线程完成,这样可以避免读写阻塞时主程序死锁。对于全双工的串口读写,应该分别开启读线程和写线程;对于半双工和单工的

15、,建议只需开启一个线程即可。在线程中,按照预定好的通信握手方式,正确检测串口状态,读取发送串口数据。2.实现细节 在半双工的情况下,首先完成必要的串口配置,成功打开串口、DCB设置、超时设置;然后开启线程,如: CwinThread hSerialThread = (CWinThread) AfxBeginThread(SerialOperation,hWnd,THREAD_PRIORITY_NORMAL); 其中开启之线程为SerialOperation,优先级为普通。 全双工情况下的串口编程,与单工差不多,区别仅仅在于启动双线程,分别为读线程和写线程,读线程根据不同的事件或消息,通过不断查询串口所收到的有效数 据,完成读操作;写线程通过接收主线程的发送数据事件和要发送的数据,向串口发送。

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 技术资料 > 其他杂项

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁