·天新网首页·加入收藏·设为首页
首页|笔记本|手机|数码相机|摄像机|MP3/MP4|主板|内存|显示器|办公|打印机|下载|开发|汽车|学院|业界
硬件|台式机|数码|数字家庭|投影仪|GPS/CPU|显卡|硬盘|服务器|网络|一体机|驱动|源码|游戏|考试|报价
Win32串口操作的技巧
http://dev.21tx.com 2003年04月17日

上一页 1 2 3

  7.读取资料

  从 serial port 里头读取资料就跟读取一般的档案一样, 使用 ReadFile() 来达成.

BOOL ReadFile(
HANDLE hFile, // handle of file to read
LPVOID lPBuffer, // address of buffer that receives data
DWORD nNumberOfBytesToRead, // number of bytes to read
LPDWORD lpNumberOfBytesRead, // address of number of bytes read
LPOVERLAPPED lpOverlapped // address of structure for data
);

  要注意的是, nNumberOfBytesToRead 设定的是一次最多的读取量, 很有可能所读取的值(检查 lpNumberOfBytesRead)小于这个值. 通常在错误发生或是 timeout 发生时这个 API 就会返回.

  PurgeComm() 这个 API 可以用来终止目前正在进行的读或写的动作, 也可以 flush 掉 I/O buffer 内等待读或写的资料.

BOOL PurgeComm(
HANDLE hFile, // handle of communications resource
DWORD dwFlags // action to perform
);

  其中 dwFlags 共有四种 flags:

  PURGE_TXABORT: 终止目前正在进行的(背景)写入动作
  PURGE_RXABORT: 终正目前正在进行的(背景)读取动作
  PURGE_TXCLEAR: flush 写入的 buffer
  PURGE_TXCLEAR: flush 读取的 buffer

  而使用 FlushFileBuffers() 可以确保所有的资料都被送出, 这个 API 才会返回.

  另外一个有趣的 API 是 ClearCommError(), 从字面上的意思看来, 它是用来清除错误情况用的, 但是实际上它还可以拿来取得目前通讯设备的一些信息.

BOOL ClearCommError(
HANDLE hFile, // handle to communications device
LPDWORD lpErrors, // pointer to variable to receive error codes
LPCOMSTAT lpStat // pointer to buffer for communications status
);

  呼叫这个 API 之后, 关于通讯设备的一些信息会被储存在 lpStat 中, COMSTAT 的结构如下:

typedef struct _COMSTAT { // cst
DWORD fCtsHold : 1; // Tx waiting for CTS signal
DWORD fDsrHold : 1; // Tx waiting for DSR signal
DWORD fRlsdHold : 1; // Tx waiting for RLSD signal
DWORD fXoffHold : 1; // Tx waiting, XOFF char rec'd
DWORD fXoffSent : 1; // Tx waiting, XOFF char sent
DWORD fEof : 1; // EOF character sent
DWORD fTxim : 1; // character waiting for Tx
DWORD fReserved : 25; // reserved
DWORD cbInQue; // bytes in input buffer
DWORD cbOutQue; // bytes in output buffer
} COMSTAT, *LPCOMSTAT

  藉由 fCtsHold, fDsrHold, fRlsdHold, fXoffHold, fXoffSent 可以知道目前因为什么因素而使通讯阻碍住了.( 跟 handshaking 和 flow control 有关) cbInque 和 cbOutQue 则可以显示出还有多少 bytes 在读取或是写入 queue 中.

  8.写入资料

  和读取资料一样, programmer 可以使用 WriteFile() 来将资料写入 serial port.

BOOL WriteFile(
HANDLE hFile, // handle to file to write to
LPCVOID lpBuffer, // pointer to data to write to file
DWORD nNumberOfBytesToWrite, // number of bytes to write
LPDWORD lpNumberOfBytesWritten, // pointer to number of bytes written
LPOVERLAPPED lpOverlapped // pointer to structure needed for overlapped I/O
);

  关于通讯设备的写入有三个很有趣的 API, 它们分别是 SetCommBreak(), ClearCommBreak, 和 TransmitCommChar().

BOOL SetCommBreak(
HANDLE hFile // handle of communications device
);

BOOL ClearCommBreak(
HANDLE hFile // handle to communications device
);

BOOL TransmitCommChar(
HANDLE hFile, // handle of communications device
char cChar // character to transmit
);

  SetCommBreak() 是用来暂停目前的传输作业, 它会使 buffer 中的资料都不再被送出, 这个时候, program 可以去做些杂七杂八的事, 之后, 再利用 ClearCommBreak() 回复传输作业.

  TransmitCommChar() 是用来立即性的赶在所有 buffer 数据被送出去之前, 传输一个字符的数据出去, 即使 buffer 中还有资料. 换句话说, 这个字符有最高的优先权被送出去.

  9.事件驱动式的 I/O

  在 Win32 里头, 对于通讯设备的 I/O 可以用像是事件驱动式的方法来达成. 主要是利用一个叫 WaitCommEvent() 的 API. 呼叫这个 API 之后, 会一直 block 到设定的事件发生之后才会返回. 我们先来看看如何设定事件, 再回过头来看 WaitCommEvent() .

  programer 可以用 GetCommMask() 和 SetCommMask() 来取得或是设定目前设定的通讯事件.

BOOL GetCommMask(
HANDLE hFile, // handle of communications device
LPDWORD lpEvtMask // address of variable to get event mask
);

BOOL SetCommMask(
HANDLE hFile, // handle of communications device
DWORD dwEvtMask // mask that identifies enabled events
);

  可以设定的事件有 EV_BREAK, EV_CTS, EV_DSR, EV_ERR, EV_RING, EV_RLSD, EV_RXCHAR, EV_RXFLAG, EV_TXEMPTY.(其意义请自行参考 help), 当然, 你可以把它们 or 起来成为组合的事件.

  在设定完想要处理的事件之后, 可以使用 WaitCommEvent()

BOOL WaitCommEvent(
HANDLE hFile, // handle of communications device
LPDWORD lpEvtMask, // address of variable for event that occurred
LPOVERLAPPED lpOverlapped, // address of overlapped structure
);

  WaitCommEvent() 会一直 block 到你所设定的通讯事件发生为止. 所以当 WaitCommEvent() 返回时, 你可以由 lpEvtMask 取得究竟是那一事件发生, 再来决定要如何处理.

  举例来说, 可以用 SetCommMask() 设定事件为 EV_RXCHAR, 那么在呼叫 WaitCommEvent() 时, 它会等到有字符可供读取时才会返回, 那么在它返回之后, 可以检查一下 lpEvtMask 中是否 set 了 EV_RXCHAR, 如果是的话就可以用 ReadFile() 去读取. 这样的话, 可以避免掉某些情形之下, 需要做 polling 所引起效率不彰的问题.

  10.错误的处理

  前面提过的 ClearnCommError() 可以用来取得目前发生错误的原因.(请参见 help)

  11.硬件的控制命令

  Win32 中提供了 EscapeCommFunction() 允许 programer 对几个硬件讯号做控制.

BOOL EscapeCommFunction(
HANDLE hFile, // handle to communications device
DWORD dwFunc // extended function to perform
);

  其中 dwFunc 可以是:

CLRDTR : 让 DTR OFF
CLRRTS : 让 RTS OFF
SETDTR : 让 DTR ON
SETRTS : 让 RTS ON
SETXOFF : "仿真" 接收到 XOFF 字符
SETXON : "仿真" 接收到 XON 字符
SETBREAK : 和 SetCommBreak() 的意思相同
CLRBREAK : 和 ClearCommBreak() 的意思相同

上一篇: UML辅助网站规划和设计指南
下一篇: NetBIOS特性与编程基础

上一页 1 2 3

Google
 
热点文章
关于我们 | 联系我们 | 广告服务 | 工作机会 | 版权声明 | 欢迎投稿 | 网站地图
Copyright © 2000-2008 , www.21tx.com , All Rights Reserved .
晨新科技 版权所有 Created by TXSite.net