WinCE中串口驱动及接口函数介绍
Wince串口通信

串口通信函数介绍
设置接收和发送缓冲区的大小: 设置接收和发送缓冲区的大小: 利用函数SetupComm来设置接收和发送数据的缓 利用函数 来设置接收和发送数据的缓 冲区的大小.这个函数不推荐使用, 冲区的大小.这个函数不推荐使用,系统会推荐一个 合适的默认值. 合适的默认值. 清空串口缓冲区: 清空串口缓冲区: 利用函数PurgeComm来清空串口的发送缓冲区和 利用函数 来清空串口的发送缓冲区和 接收缓冲区. 接收缓冲区. 清除错误并查询状态: 清除错误并查询状态: 中利用ClearCommError函数清除驱动 在WINCE中利用 中利用 函数清除驱动 程序产生的任何错误状态并返回当前窗口状态. 程序产生的任何错误状态并返回当前窗口状态.
Softeem Consultancy Service
串口通信函数介绍
打开关闭串口: 打开关闭串口: 函数中可以通过CreateFile函数打开串口,利用这个 函数打开串口, 在WINCE函数中可以通过 函数中可以通过 函数打开串口 函数打开窗口需要注意的是在串口名之后必须加一个冒号(:), 函数打开窗口需要注意的是在串口名之后必须加一个冒号 ,在 参数中要注意设置共享参数为独占方式( ), ),安全参数和模板 参数中要注意设置共享参数为独占方式(0),安全参数和模板 文件参数也必须被设置成NULL. 文件参数也必须被设置成 当使用完串口后要注意使用CloseHandle函数来关闭串口. 函数来关闭串口. 当使用完串口后要注意使用 函数来关闭串口 配置串口: 配置串口: 在使用串口时,还必须配置好串口的波特率, 在使用串口时,还必须配置好串口的波特率,奇偶检验和数据 位等, 提供了 提供了GetCommState和SetCommState函数分别获 位等,CE提供了 和 函数分别获 取串口的当前参数和设置串口的参数. 取串口的当前参数和设置串口的参数. 读写串口: 读写串口: 程序中使用ReadFile和WriteFile函数读取串口数据和向串口 程序中使用 和 函数读取串口数据和向串口 中写入数据.由于串口读写数据的速度比较慢, 中写入数据.由于串口读写数据的速度比较慢,所以不要在主线 程中读写大量数据, 程中读写大量数据,所以最好的方法是用单独的线程来读写数据
WinCE中串口驱动及接口函数介绍

WinCE中串口驱动及接口函数介绍串口驱动本身分为MDD层和PDD层。
MDD层对上层的Device Manager提供了标准的流设备驱动接口(COM_***),PDD层实现了HWOBJ结构及结构中若干针对于串口硬件操作的函数指针,这些函数指针将指向PDD层中的串口操作函数。
DDSI是指MDD层与PDD层的接口,在串口驱动中实际上就是指HWOBJ,PDD层会传给MDD层一个HWOBJ结构的指针,这样MDD层就可以调用PDD层的函数来操作串口。
微软针对于串口驱动提供了参考源代码,可以在下面的目录下找到:”\WINCE600\PUBLIC\COMMON\OAK\DRIVERS\SERIAL”。
串口驱动的结构也就是这样了,下面介绍相关的驱动中的接口。
1. HWOBJ结构在串口驱动中,HWOBJ结构中的函数实现了对串口硬件的操作,并在MDD层被调用。
可以说,该结构描述了串口设备的所有特性,先来介绍一下该结构,具体定义如下:typedef struct __HWOBJ{ULONG BindFlags;DWORD dwIntID;PHW_VTBL pFuncTbl;} HWOBJ, *PHWOBJ;BindFlags:用于控制MDD层如何来处理IST,具体值如下:THREAD_IN_PDD:MDD层不处理,中断在PDD层处理。
THREAD_AT_INIT:在驱动初始化的时候,MDD层启动IST。
THREAD_AT_OPEN:在驱动被Open的时候,MDD层启动IST。
dwInitID:系统的中断号 pFuncTbl:指向一个PHW_VTBL结构,该结构中包含一个函数指针列表,这些函数指针指向串口硬件操作函数,用于操作串口。
view plaincopy to clipboardprint?typedef struct __HW_VTBL{PVOID (*HWInit)(ULONG Identifier, PVOID pMDDContext);ULONG (*HWDeinit)(PVOID pHead);BOOL (*HWOpen)(PVOID pHead);ULONG (*HWClose)(PVOID pHead);ULONG (*HWGetBytes)(PVOID pHead, PUCHAR pTarget, PULONG pBytes);PVOID (*HWGetRxStart)(PVOID pHead);INTERRUPT_TYPE (*HWGetIntrType)(PVOID pHead);VOID (*HWOtherIntrHandler)(PVOID pHead);VOID (*HWLineIntrHandler)(PVOID pHead);ULONG (*HWGetRxBufferSize)(PVOID pHead);VOID (*HWTxIntrHandler)(PVOID pHead);ULONG (*HWPutBytes)(PVOID pHead, PUCHAR pSrc, ULONG NumBytes, PULONG pBytesSent);BOOL (*HWPowerOff)(PVOID pHead);BOOL (*HWPowerOn)(PVOID pHead);VOID (*HWClearDTR)(PVOID pHead);VOID (*HWSetDTR)(PVOID pHead);VOID (*HWClearRTS)(PVOID pHead);VOID (*HWSetRTS)(PVOID pHead);BOOL (*HWEnableIR)(PVOID pHead, ULONG BaudRate);BOOL (*HWDisableIR)(PVOID pHead);VOID (*HWClearBreak)(PVOID pHead);VOID (*HWSetBreak)(PVOID pHead);BOOL (*HWXmitComChar)(PVOID pHead, UCHAR ComChar);ULONG (*HWGetStatus)(PVOID pHead, LPCOMSTAT lpStat);VOID (*HWReset)(PVOID pHead);VOID (*HWGetModemStatus)(PVOID pHead, PULONG pModemStatus);VOID (*HWGetCommProperties)(PVOID pHead, LPCOMMPROP pCommProp);VOID (*HWPurgeComm)(PVOID pHead, DWORD fdwAction);BOOL (*HWSetDCB)(PVOID pHead, LPDCB pDCB);BOOL (*HWSetCommTimeouts)(PVOID pHead, LPCOMMTIMEOUTS lpCommTO);BOOL (*HWIoctl)(PVOID pHead, DWORD dwCode,PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut,DWORD dwLenOut,PDWORD pdwActualOut);} HW_VTBL, *PHW_VTBL;typedef struct __HW_VTBL{PVOID (*HWInit)(ULONG Identifier, PVOID pMDDContext);ULONG (*HWDeinit)(PVOID pHead);BOOL (*HWOpen)(PVOID pHead);ULONG (*HWClose)(PVOID pHead);ULONG (*HWGetBytes)(PVOID pHead, PUCHAR pTarget, PULONG pBytes);PVOID (*HWGetRxStart)(PVOID pHead);INTERRUPT_TYPE (*HWGetIntrType)(PVOID pHead);VOID (*HWOtherIntrHandler)(PVOID pHead);VOID (*HWLineIntrHandler)(PVOID pHead);ULONG (*HWGetRxBufferSize)(PVOID pHead);VOID (*HWTxIntrHandler)(PVOID pHead);ULONG (*HWPutBytes)(PVOID pHead, PUCHAR pSrc, ULONG NumBytes, PULONG pBytesSent);BOOL (*HWPowerOff)(PVOID pHead);BOOL (*HWPowerOn)(PVOID pHead);VOID (*HWClearDTR)(PVOID pHead);VOID (*HWSetDTR)(PVOID pHead);VOID (*HWClearRTS)(PVOID pHead);VOID (*HWSetRTS)(PVOID pHead);BOOL (*HWEnableIR)(PVOID pHead, ULONG BaudRate);BOOL (*HWDisableIR)(PVOID pHead);VOID (*HWClearBreak)(PVOID pHead);VOID (*HWSetBreak)(PVOID pHead);BOOL (*HWXmitComChar)(PVOID pHead, UCHAR ComChar);ULONG (*HWGetStatus)(PVOID pHead, LPCOMSTAT lpStat);VOID (*HWReset)(PVOID pHead);VOID (*HWGetModemStatus)(PVOID pHead, PULONG pModemStatus);VOID (*HWGetCommProperties)(PVOID pHead, LPCOMMPROP pCommProp);VOID (*HWPurgeComm)(PVOID pHead, DWORD fdwAction);BOOL (*HWSetDCB)(PVOID pHead, LPDCB pDCB);BOOL (*HWSetCommTimeouts)(PVOID pHead, LPCOMMTIMEOUTS lpCommTO);BOOL (*HWIoctl)(PVOID pHead, DWORD dwCode,PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut,DWORD dwLenOut,PDWORD pdwActualOut);} HW_VTBL, *PHW_VTBL; 这些函数将在PDD层实现,用于实际的串口硬件操作。
wince串口

WinCE中串口通讯的调试方法串口是嵌入式系统中应用很广的一种通讯接口。
在WinCE中,通常会有一个串口供调试使用,另外的串口可与外围设备连接,如GSM和GPS等模块,以获取相应的信息并进行处理。
在WinCE中,为了使用串口,必须有相应的串口驱动程序,一般在BSP 中都有实现。
串口驱动是典型的流驱动。
应用程序中可通过CreateFile()、ReadFile()和WriteFile()等文件系统的操作函数来访问串口,从而实现串口数据的收发。
虽然串口操作相对简单,但在实际调试时依然会碰到很多问题,譬如如何监视串口收发的数据。
在调试GSM模块时,如果WinCE不能正确控制模块,我们就需要确认是发送还是接收的问题,是模块还是开发板的问题。
在调试GPS模块时,经常需要监视GPS数据又不能影响固有GPS软件的运行。
这些都要求我们能内建虚拟串口,以将物理串口收到的数据分发到不同的虚拟串口上,相反,发送则是由不同的虚拟串口往物理串口转发的过程。
Serial Splitter Mobile就是这样一款专业软件,它能满足上述要求。
以前曾用它调试过一个串口设备。
当时用的是一个试用版,单次连接只能收发1M Bytes,超过1M就不工作了。
开始没在意,以为是串口驱动和自己软件的问题,后来发现是Serial Splitter试用版的限制。
调试手段引入的错误,是最让人郁闷的。
为了方便使用,今天到其官网下载了最新的版本,并破解之,去除了收发数据的限制和应用程序中的注册信息。
破解前的截图如下:破解后的截图如下:使用截图:该软件使用很方便,简单测试了一下,效果还是可以的,有需要的请到这里下载:/we-hjb/WINCE_SERIAL.rar,其中包括WinCE6.0下的Splitter Mobile破解版、WinCE串口调试助手和使用参考视频。
WINCE 驱动中断 相关函数详解

CreateEvent的用法HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, // SD BOOL bManualReset, // reset typeBOOL bInitialState, // initial state LPCTSTR lpName // object name);该函数创建一个Event同步对象,并返回该对象的HandlelpEventAttributes 一般为NULLbManualReset 创建的Event是自动复位还是人工复位,如果true,人工复位, 一旦该Event被设置为有信号,则它一直会等到ResetEvent()API被调用时才会恢复为无信号. 如果为false,Event被设置为有信号,则当有一个wait到它的Thread时,该Event就会自动复位,变成无信号.bInitialState 初始状态,true,有信号,false无信号lpName Event对象名一个Event被创建以后,可以用OpenEvent()API来获得它的Handle,用CloseHandle() 来关闭它,用SetEvent()或PulseEvent()来设置它使其有信号,用ResetEvent()来使其无信号,用WaitForSingleObject()或WaitForMultipleObjects()来等待其变为有信号.PulseEvent()是一个比较有意思的使用方法,正如这个API的名字,它使一个Event对象的状态发生一次脉冲变化,从无信号变成有信号再变成无信号,而整个操作是原子的.对自动复位的Event对象,它仅释放第一个等到该事件的thread(如果有),而对于人工复位的Event对象,它释放所有等待的thread.kerneliocontrol()函数This function provides the kernel with a generic I/O control for carrying out I/O operations.该函数为内核提供执行IO操作的通用IO控制SyntaxBOOL KernelIoControl(DWORD dwIoControlCode,LPVOID lpInBuf,DWORD nInBufSize,LPVOID lpOutBuf,DWORD nOutBufSize,LPDWORD lpBytesReturned);Parameters参数dwIoControlCode[in] I/O control code, which should support the OAL I/O controls【输入】IO控制代码,支持OAL级的IO控制IOCTL_HAL_RELEASE_SYSINTRIOCTL_HAL_REQUEST_SYSINTRIOCTL_HAL_TRANSLATE_IRQlpInBuf[in] Pointer to a buffer that contains the data required to perform the operation.Set to NULL if the dwIoControlCode parameter specifies an operation that does not require inputdata.【输入】指向一个缓冲区,其包含执行操作所必须的数据。
WINCE6.0+S3C6410串口驱动

WINCE6.0+S3C6410串口驱动WINCE串口驱动备注:本博文基于Real6410+WINCE6.0的系统来学习的1. 硬件设计图1 UART接口在此开发板中的应用如下:UART0作为调试口来使用图2 UART1用于和GPRS模块SIM900通信图3 UART2用于和GPS模块COMPASS_EB818通信图4UATR3用于和蓝牙模块通信图52. 软件设计2.1 WINCE串口驱动的架构在WINCE系统中,串口驱动是作为一个流驱动的形式存在,其驱动架构如下图所示:图6串口驱动分为MDD层和PDD层,DD层对上层的Device Manager(device.dll)提供了标准的流设备驱动接口(COM_xxx),PDD层实现了HWOBJ结构及结构中若干针对于串口硬件操作的函数指针,这些函数指针将指向PDD层中的串口操作函数。
DDSI是指MDD层与PDD层的接口,在串口驱动中实际上就是指HWOBJ,PDD层会传给MDD层一个HWOBJ结构的指针,这样MDD层就可以调用PDD层的函数来操作串口。
2.2 MDD层的导出接口函数MDD层为系统提供流设备接口,这些接口微软已经实现,但还是有必要学习一下2.2.1 COM_Init此函数始化串口设备,该函数通过读取注册表获得串口设备号,并获得相应的HWOBJ的结构指针,通过该指针调用PDD层的硬件初始化函数初始化串口。
Identifier:如果驱动被设备管理器加载,那么这个参数将包含一个注册表键值在”HKEY_LOCAL_MACHINE\Drivers\Active”路径下。
如果驱动是通过调用RegisterDevice函数来加载的,那么这个值等于dwInfo的值。
在COM_Init中,会先打开该键值,用返回的句柄来查询DeviceArrayIndex值,并根据该值获得PDD层的HWOBJ结构指针,下图是COM_Init函数的一部分图72.2.2 COM_Deinit卸载串口设备,该函数中主要做了一些释放资源的操作。
WinCE6.0下双模终端的USB转串口驱动开发

0 引 言
我国 3 G牌 照 的 发放 , 宣告 了 3 时代 的到 来 , G
基于 T —C MA和 C MA WC MA 的双 模 终 端 将 DS D D / D 取代 2 时代 的单 模 终 端 。诺 基亚 、 星 、 为 、 G 三 华 中 兴等 国 内外 通 信 厂 商 都 积 极 投 入 到 双 模 手 机 终 端 的开发 中来 , 目前 双模 手 机终 端 的研发 已经 成 为热 点 。当前市场 中主要 的智 能手 机操 作 系统 有 : o i N ka 主推 的 Sm in 开 放 内核 的嵌 入 式 Ln x 微 软 的 y ba , iu , WiC n E等 。由于 WiC 6 0嵌人 式 系统具 有实 时性 n E.
Wi E. U B设备驱动开发只提供了一些底层支持 n 60对 S C
的原因, 以通 信 模 块 厂 商 未 提 供 WiC 6 0下 的 所 nE .
U B驱 动 , 要 实 现 通 信 模 块 的基 本 功 能 , 开 发 S 而 除
纯 U B驱 动 外 , WiC 6 0下 , 需 要 修 改 Mo S 在 nE. 还 . d m源码 , e 存在 着开 发 周 期 长 、 作量 大 、 容 性 差 工 兼 等 问题 , 给开发 人 员带 来 了极 大 的不 便 。而通 过 串 口直接对 Mo e dm进 行操作 , 不仅 避 免 了上述 在开 发 中存 在 的问 题 , 时 由于操 作 Mo e 的 是 虚 拟 串 同 dm 口, 由它来 适 配 Moe 不 会 出 现 由物 理 串 口操 作 d m, Mo e 时制 约 M d m处理速 率 的问题 , 然保持 了 dm oe 仍 U B高 速的特 点 , 开 发人 员 只 需 开发 出对应 模 块 S 故 的 U B转 串 口驱 动 亦 可实 现 上 网 、 电话 等 功 能 ; S 打
WINCE下如何使用串口

WINCE下如何使用串口1.创建线程/////////////////////////////////////////////////////////////////// /////////DWORD CApplicationDlg::CommRecvTread(LPVOID lparam) {DWORD dwLength;char *recvBuf = new char[1024];CBuletoothApplicationDlg *pDlg = (CBuletoothApplicationDlg*)lparam;while(TRUE){if (WaitForSingleObject(pDlg->m_ExitThreadEvent, 0) == WAIT_OBJECT_0)break;if (pDlg->m_hComm != INVALID_HANDLE_VALUE){BOOL fReadState = ReadFile(pDlg->m_hComm, recvBuf, 1024, &dwLength, NULL);if(!fReadState){//MessageBox(_T("无法从串口读取数据!"));}else{if(dwLength != 0)OnCommRecv(pDlg, recvBuf, dwLength);}}}delete[] recvBuf;return 0;}/////////////////////////////////////////////////////////////////// ////////////2.打开串口,创建串口接收线程/////////////////////////////////////////////////////////////////// ///////////void CApplicationDlg::OnButtonPair(){// TODO: Add your control notification handler code here////////////////////////////////////////////////////////Sleep(100);////////////////////////////////////////////////////////DWORD IDThread;HANDLE hRecvThread;UpdateData(TRUE);CString strPort = PorTbl[m_ComboPort.GetCurSel()];DWORD baud = BaudTbl[m_ComboBaud.GetCurSel()];DWORD databit = DataBitTbl[1];BYTE stopbit = StopBitTbl[0];BYTE parity = ParityTbl[0];BOOL ret = OpenPort(strPort, baud, databit, stopbit, parity);if (ret == FALSE)return;m_ExitThreadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);// 创建串口接收线程hRecvThread = CreateThread(0, 0, CommRecvTread, this, 0, &IDThread);if (hRecvThread == NULL){MessageBox(_T("创建接收线程失败!"));return;}CloseHandle(hRecvThread);m_ButOpen.EnableWindow(FALSE);m_ButClose.EnableWindow(TRUE);MessageBox(_T("打开") + strPort + _T("成功!"));}/////////////////////////////////////////////////////////////////// //////////////3.串口接收线程/////////////////////////////////////////////////////////////////// /////////////DWORD CApplicationDlg::CommRecvTread(LPVOID lparam) {DWORD dwLength;char *recvBuf = new char[1024];CApplicationDlg *pDlg = (CApplicationDlg*)lparam;while(TRUE){if (WaitForSingleObject(pDlg->m_ExitThreadEvent, 0) == WAIT_OBJECT_0)break;if (pDlg->m_hComm != INVALID_HANDLE_VALUE){BOOL fReadState = ReadFile(pDlg->m_hComm, recvBuf, 1024, &dwLength, NULL);if(!fReadState)//MessageBox(_T("无法从串口读取数据!"));}else{if(dwLength != 0)OnCommRecv(pDlg, recvBuf, dwLength);}}}delete[] recvBuf;return 0;}/////////////////////////////////////////////////////////////////// //////////////4.串口接收信息处理/////////////////////////////////////////////////////////////////// /////////////void CALLBACK CApplicationDlg::OnCommRecv(CWnd* pWnd, char *buf, int buflen){//此处代码可以自己写了//接收到的串口信息处理部分}/////////////////////////////////////////////////////////////////// ///////////5.关闭串口/////////////////////////////////////////////////////////////////// //////////////BOOL CApplicationDlg::ClosePort(void)if(m_hComm != INVALID_HANDLE_VALUE){SetCommMask(m_hComm, 0);PurgeComm(m_hComm, PURGE_TXCLEAR | PURGE_RXCLEAR);CloseHandle(m_hComm);m_hComm = INVALID_HANDLE_VALUE;return TRUE;}return FALSE;}。
Windows CE下的串口驱动设计

ly rdd ie t te m rv ra dito u e h p cf e eo me rc s fsra rv ra dtepo e s fitru t rc sig a ee rv rwi sra d e, n r d c stes e i cd v lp nt o eso e l i e n rc s er p o e sn . h i n i p i d h o n p
及 Wi o s E的中断处理 过程 ,提出流接 口和分层相结合的驱动程序 设计方案 ,给出 Wi o s E 下串口驱动的具体开发过程及串 口 n w d C n w d C 驱
动 的 中断 处 理过 程 。
关健词 :嵌入式系统;中断处理 ;串 口驱动
De i n o e i l i e i d wsCE sg fS ra v ri W n o Dr n
中圈 分类号 E 下 的 串 口驱 动 设 计 no C
司浩乐 ,万 波 ,田玉敏 ‘
( 西安电子科技大学外部设备研究所 ,西安 7 0 7 ) 10 1
摘
要 :驱动程序 及串口驱动的开发和设计是构建嵌入式系统 的重要组成部分。该文介 绍了 Wi o s E下 的驱动程序 的结构、开发过程 n w d C
软为每种类型的本地驱动提供 了定制的接 I ,本地设备 驱动 S l 为所有特定类型的设备提供 了一组标准的功能 。常见的内建 驱动有键盘 、触摸屏 、音频设备等 。 可 安 装 的驱 动 程 序 又 称 作 流设 备 接 口程 序 (t a Sr ms e It fc r e) ne ae D i r,是 由设备 管理器 动态加载 的用 户模 式的 r v D L。这类驱动具有一组相 同的导出函数——流接 口函数, L
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
WinCE中串口驱动及接口函数介绍串口驱动本身分为MDD层和PDD层。
MDD层对上层的Device Manager提供了标准的流设备驱动接口(COM_***),PDD层实现了HWOBJ结构及结构中若干针对于串口硬件操作的函数指针,这些函数指针将指向PDD层中的串口操作函数。
DDSI是指MDD层与PDD层的接口,在串口驱动中实际上就是指HWOBJ,PDD层会传给MDD层一个HWOBJ结构的指针,这样MDD层就可以调用PDD层的函数来操作串口。
微软针对于串口驱动提供了参考源代码,可以在下面的目录下找到:”\WINCE600\PUBLIC\COMMON\OAK\DRIVERS\SERIAL”。
串口驱动的结构也就是这样了,下面介绍相关的驱动中的接口。
1. HWOBJ结构在串口驱动中,HWOBJ结构中的函数实现了对串口硬件的操作,并在MDD层被调用。
可以说,该结构描述了串口设备的所有特性,先来介绍一下该结构,具体定义如下:typedef struct __HWOBJ{ULONG BindFlags;DWORD dwIntID;PHW_VTBL pFuncTbl;} HWOBJ, *PHWOBJ;BindFlags:用于控制MDD层如何来处理IST,具体值如下:THREAD_IN_PDD:MDD层不处理,中断在PDD层处理。
THREAD_AT_INIT:在驱动初始化的时候,MDD层启动IST。
THREAD_AT_OPEN:在驱动被Open的时候,MDD层启动IST。
dwInitID:系统的中断号 pFuncTbl:指向一个PHW_VTBL结构,该结构中包含一个函数指针列表,这些函数指针指向串口硬件操作函数,用于操作串口。
view plaincopy to clipboardprint?typedef struct __HW_VTBL{PVOID (*HWInit)(ULONG Identifier, PVOID pMDDContext);ULONG (*HWDeinit)(PVOID pHead);BOOL (*HWOpen)(PVOID pHead);ULONG (*HWClose)(PVOID pHead);ULONG (*HWGetBytes)(PVOID pHead, PUCHAR pTarget, PULONG pBytes);PVOID (*HWGetRxStart)(PVOID pHead);INTERRUPT_TYPE (*HWGetIntrType)(PVOID pHead);VOID (*HWOtherIntrHandler)(PVOID pHead);VOID (*HWLineIntrHandler)(PVOID pHead);ULONG (*HWGetRxBufferSize)(PVOID pHead);VOID (*HWTxIntrHandler)(PVOID pHead);ULONG (*HWPutBytes)(PVOID pHead, PUCHAR pSrc, ULONG NumBytes, PULONG pBytesSent);BOOL (*HWPowerOff)(PVOID pHead);BOOL (*HWPowerOn)(PVOID pHead);VOID (*HWClearDTR)(PVOID pHead);VOID (*HWSetDTR)(PVOID pHead);VOID (*HWClearRTS)(PVOID pHead);VOID (*HWSetRTS)(PVOID pHead);BOOL (*HWEnableIR)(PVOID pHead, ULONG BaudRate);BOOL (*HWDisableIR)(PVOID pHead);VOID (*HWClearBreak)(PVOID pHead);VOID (*HWSetBreak)(PVOID pHead);BOOL (*HWXmitComChar)(PVOID pHead, UCHAR ComChar);ULONG (*HWGetStatus)(PVOID pHead, LPCOMSTAT lpStat);VOID (*HWReset)(PVOID pHead);VOID (*HWGetModemStatus)(PVOID pHead, PULONG pModemStatus);VOID (*HWGetCommProperties)(PVOID pHead, LPCOMMPROP pCommProp);VOID (*HWPurgeComm)(PVOID pHead, DWORD fdwAction);BOOL (*HWSetDCB)(PVOID pHead, LPDCB pDCB);BOOL (*HWSetCommTimeouts)(PVOID pHead, LPCOMMTIMEOUTS lpCommTO);BOOL (*HWIoctl)(PVOID pHead, DWORD dwCode,PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut,DWORD dwLenOut,PDWORD pdwActualOut);} HW_VTBL, *PHW_VTBL;typedef struct __HW_VTBL{PVOID (*HWInit)(ULONG Identifier, PVOID pMDDContext);ULONG (*HWDeinit)(PVOID pHead);BOOL (*HWOpen)(PVOID pHead);ULONG (*HWClose)(PVOID pHead);ULONG (*HWGetBytes)(PVOID pHead, PUCHAR pTarget, PULONG pBytes);PVOID (*HWGetRxStart)(PVOID pHead);INTERRUPT_TYPE (*HWGetIntrType)(PVOID pHead);VOID (*HWOtherIntrHandler)(PVOID pHead);VOID (*HWLineIntrHandler)(PVOID pHead);ULONG (*HWGetRxBufferSize)(PVOID pHead);VOID (*HWTxIntrHandler)(PVOID pHead);ULONG (*HWPutBytes)(PVOID pHead, PUCHAR pSrc, ULONG NumBytes, PULONG pBytesSent);BOOL (*HWPowerOff)(PVOID pHead);BOOL (*HWPowerOn)(PVOID pHead);VOID (*HWClearDTR)(PVOID pHead);VOID (*HWSetDTR)(PVOID pHead);VOID (*HWClearRTS)(PVOID pHead);VOID (*HWSetRTS)(PVOID pHead);BOOL (*HWEnableIR)(PVOID pHead, ULONG BaudRate);BOOL (*HWDisableIR)(PVOID pHead);VOID (*HWClearBreak)(PVOID pHead);VOID (*HWSetBreak)(PVOID pHead);BOOL (*HWXmitComChar)(PVOID pHead, UCHAR ComChar);ULONG (*HWGetStatus)(PVOID pHead, LPCOMSTAT lpStat);VOID (*HWReset)(PVOID pHead);VOID (*HWGetModemStatus)(PVOID pHead, PULONG pModemStatus);VOID (*HWGetCommProperties)(PVOID pHead, LPCOMMPROP pCommProp);VOID (*HWPurgeComm)(PVOID pHead, DWORD fdwAction);BOOL (*HWSetDCB)(PVOID pHead, LPDCB pDCB);BOOL (*HWSetCommTimeouts)(PVOID pHead, LPCOMMTIMEOUTS lpCommTO);BOOL (*HWIoctl)(PVOID pHead, DWORD dwCode,PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut,DWORD dwLenOut,PDWORD pdwActualOut);} HW_VTBL, *PHW_VTBL; 这些函数将在PDD层实现,用于实际的串口硬件操作。
2. MDD层APIMDD层向上提供了流设备接口,这部分代码微软已经实现,用于管理串口。
虽然我们不需要实现这部分,但是还是对相应的接口做个简单介绍。
2.1HANDLE COM_Init(ULONG Identifier):初始化串口设备,该函数通过读取注册表获得串口设备号,并获得相应的HWOBJ的结构指针,通过该指针调用PDD层的硬件初始化函数初始化串口。
Identifier:如果驱动被设备管理器加载,那么这个参数将包含一个注册表键值在” HKEY_LOCAL_MACHINE\Drivers\Active”路径下。
如果驱动是通过调用RegisterDevice函数来加载的,那么这个值等于dwInfo的值。
在COM_Init中,会先打开该键值,用返回的句柄来查询DeviceArrayIndex值,并根据该值获得PDD层的HWOBJ结构指针。
2.2 BOOL COM_Deinit(void):卸载串口设备,该函数中主要做了一些释放资源的操作。
也可以被DeregisterDevice函数调用。
2.3 HANDLE COM_Open(HANDLE pContext, DWORD AccessCode, DWORD ShareMode):打开串口设备。
应用程序调用CreateFile函数打开串口时,该函数会被调用。
pContext:COM_Init函数返回的Handle。
AccessCode:设置访问模式,比如共享读或者是读写模式。
ShareMode:在参数从应用程序中的CreateFile函数中传来,表示是否支持独自占有。
2.4 BOOL COM_Close(DWORD pContext):关闭串口设备。
应用程序调用CloseHandle函数关闭串口时,该函数会被调用。
pContext:该参数为COM_Open函数返回的Handle。