1.开启一个 Serial Port
  利用一般开启档案的 CreatFile() 即可开启 serial port device

[cpp] view plaincopy print?
  1. HANDLE CreateFile(
  2. LPCTSTR lpFileName, // pointer to name of the file
  3. DWORD dwDesiredAccess, // access (read-write) mode
  4. DWORD dwShareMode, // share mode
  5. LPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security attributes
  6. DWORD dwCreationDistribution, // how to create
  7. DWORD dwFlagsAndAttributes, // file attributes
  8. HANDLE hTemplateFile // handle to file with attributes to copy
  9. );
HANDLE CreateFile(
LPCTSTR lpFileName, // pointer to name of the file
DWORD dwDesiredAccess, // access (read-write) mode
DWORD dwShareMode, // share mode
LPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security attributes
DWORD dwCreationDistribution, // how to create
DWORD dwFlagsAndAttributes, // file attributes
HANDLE hTemplateFile // handle to file with attributes to copy
);

  用 CreateFile() API.
  lpFileName 为 "COM1" 或是 "COM2"
  dwDersiredAccess 一般为 GENERIC_READ|GENERIC_WRITE
  dwShareMode "必须"为 0, 即不能共享, 但同一个 process 中的不同 thread 在一开启之后就可以共享.
  lpSecurityAttributes 一般为 NULL
  dwCreateionDistributon 在这里"必须"为 OPEN_EXISTING
  dwFlagsAndAttributes 定义了开启的属性, 若是设成 FILE_FLAG_OVERLAPPED 则可使用异步的 I/O.
  hTemplateFile "必须"为 NULL
  传回档案 handle
  设定 Serial Port 传送及接收缓冲区的大小

  在开启完 serial port 之后, 可以藉由呼叫 SetupComm() 来进行配置传送时的缓冲区及接收时的缓冲区. 如果没有呼叫 SetupComm() 的话, Win95 会配置内定的缓冲区.

[cpp] view plaincopy print?
  1. BOOL SetupComm(
  2. HANDLE hFile, // handle of communications device
  3. DWORD dwInQueue, // size of input buffer
  4. DWORD dwOutQueue // size of output buffer
  5. );
BOOL SetupComm(
HANDLE hFile, // handle of communications device
DWORD dwInQueue, // size of input buffer
DWORD dwOutQueue // size of output buffer
);

  2.关闭 Serial Port file

  利用一般的 CloseHandle() 即可.

[cpp] view plaincopy print?
  1. BOOL CloseHandle(
  2. HANDLE hObject // handle to object to close
  3. );
BOOL CloseHandle(
HANDLE hObject // handle to object to close
);

  3.取得 Seial Port 的信息

  在 Win32 里头, 将一些通讯时会用到的信息用 COMMPROP 这个结构来表示. (当然不仅仅是 Serial Port) 可以用 GetCommProperties() 来取得:

[cpp] view plaincopy print?
  1. BOOL GetCommProperties(
  2. HANDLE hFile, // handle of communications device
  3. LPCOMMPROP lpCommProp // address of communications properties structure
  4. );
BOOL GetCommProperties(
HANDLE hFile, // handle of communications device
LPCOMMPROP lpCommProp // address of communications properties structure
);

  COMMPROP 长的像这个样子:

[cpp] view plaincopy print?
  1. typedef struct _COMMPROP { // cmmp
  2. WORD wPacketLength; // packet size, in bytes
  3. WORD wPacketVersion; // packet version
  4. DWORD dwServiceMask; // services implemented
  5. DWORD dwReserved1; // reserved
  6. DWORD dwMaxTxQueue; // max Tx bufsize, in bytes
  7. DWORD dwMaxRxQueue; // max Rx bufsize, in bytes
  8. DWORD dwMaxBaud; // max baud rate, in bps
  9. DWORD dwProvSubType; // specific provider type
  10. DWORD dwProvCapabilities; // capabilities supported
  11. DWORD dwSettableParams; // changable parameters
  12. DWORD dwSettableBaud; // allowable baud rates
  13. WORD wSettableData; // allowable byte sizes
  14. WORD wSettableStopParity; // stop bits/parity allowed
  15. DWORD dwCurrentTxQueue; // Tx buffer size, in bytes
  16. DWORD dwCurrentRxQueue; // Rx buffer size, in bytes
  17. DWORD dwProvSpec1; // provider-specific data
  18. DWORD dwProvSpec2; // provider-specific data
  19. WCHAR wcProvChar[1]; // provider-specific data
  20. } COMMPROP;
typedef struct _COMMPROP { // cmmp
WORD wPacketLength; // packet size, in bytes
WORD wPacketVersion; // packet version
DWORD dwServiceMask; // services implemented
DWORD dwReserved1; // reserved
DWORD dwMaxTxQueue; // max Tx bufsize, in bytes
DWORD dwMaxRxQueue; // max Rx bufsize, in bytes
DWORD dwMaxBaud; // max baud rate, in bps
DWORD dwProvSubType; // specific provider type
DWORD dwProvCapabilities; // capabilities supported
DWORD dwSettableParams; // changable parameters
DWORD dwSettableBaud; // allowable baud rates
WORD wSettableData; // allowable byte sizes
WORD wSettableStopParity; // stop bits/parity allowed
DWORD dwCurrentTxQueue; // Tx buffer size, in bytes
DWORD dwCurrentRxQueue; // Rx buffer size, in bytes
DWORD dwProvSpec1; // provider-specific data
DWORD dwProvSpec2; // provider-specific data
WCHAR wcProvChar[1]; // provider-specific data
} COMMPROP;

  在这里, lpCommProp 需要 programmer 自行配置空间. 有趣的问题是, 系统在这个结构之后会需要额外的空间. 但是配置者也就是 programmer 却不知道系统会需要多少. 很简单的做法是配置一大块绝对会够的空间. 另一个聪明的做法是执行两次 GetCommProperties() , 第一次只配置 sizeof(COMMPROP) 这么大的空间, 因为还没有开始执行一些动作, 所以系统并不会尝试着在后面填东西, 所以不会出问题. 接着执行第一次的 GetCommProperties(), 得到结果, 取出结构中的 wPacketLength, 这个 member 代表实际上需要的大小, 然后依据这个大小重新配置一个新的. 这样的话 , 就不会有浪费任何空间的问题了.

  至于上述 COMMPROP 结构的成员所代表的意思, on-line help 中应该写的都满清楚的 .

4.设定及取得通讯状态

  你可以利用 COMMPROP 来取得一些状态, 但是当你想改变目前的设定时你需要两个 API 来完成:

[cpp] view plaincopy print?
  1. BOOL GetCommState(
  2. HANDLE hFile, // handle of communications device
  3. LPDCB lpDCB // address of device-control block structure
  4. );
BOOL GetCommState(
HANDLE hFile, // handle of communications device
LPDCB lpDCB // address of device-control block structure
);
[cpp] view plaincopy print?
  1. BOOL SetCommState(
  2. HANDLE hFile, // handle of communications device
  3. LPDCB lpDCB // address of device-control block structure
  4. );
BOOL SetCommState(
HANDLE hFile, // handle of communications device
LPDCB lpDCB // address of device-control block structure
);

  你可以用 GetCommState() 来取得目前 Serial Port 的状态, 也可以用 SetCommState() 来设定 Serial Port 的状态.

  DCB 的结构就请自行翻阅 help 啰.

  另外, programmer 最常控制的几个设定就是 baud rate, parity method, data bits, 还有 stop bit. BuildCommDCB() 提供了对于这几个常见设定的控制.

[cpp] view plaincopy print?
  1. BOOL BuildCommDCB(
  2. LPCTSTR lpDef, // pointer to device-control string
  3. LPDCB lpDCB // pointer to device-control block
  4. );
BOOL BuildCommDCB(
LPCTSTR lpDef, // pointer to device-control string
LPDCB lpDCB // pointer to device-control block
);

  lpDef 长的像这样: "baud=2400 parity=N data=8 stop=1"

5.通讯设定对话盒

  Win32 API 中提供了一个开启通讯设定对话盒的 API: CommConfigDialog(), 当呼叫这个 API 时, 会蹦现一个可供设定 Baud Rate, Data Bits, Parity .. 等信息的对话盒, programmer 可以利用它来让使用者设定一些信息, 并且取得结果.

[cpp] view plaincopy print?
  1. BOOL CommConfigDialog(
  2. LPTSTR lpszName, // pointer to device name string
  3. HWND hWnd, // handle to window
  4. LPCOMMCONFIG lpCC // pointer to comm. configuration structure
  5. );
BOOL CommConfigDialog(
LPTSTR lpszName, // pointer to device name string
HWND hWnd, // handle to window
LPCOMMCONFIG lpCC // pointer to comm. configuration structure
);

  其中 lpCC 被用来存放设定值的结果.

[cpp] view plaincopy print?
  1. typedef struct _COMM_CONFIG {
  2. DWORD dwSize;
  3. WORD wVersion;
  4. WORD wReserved;
  5. DCB dcb;
  6. DWORD dwProviderSubType;
  7. DWORD dwProviderOffset;
  8. DWORD dwProviderSize;
  9. WCHAR wcProviderData[1];
  10. } COMMCONFIG, *LPCOMMCONFIG;
typedef struct _COMM_CONFIG {
DWORD dwSize;
WORD wVersion;
WORD wReserved;
DCB dcb;
DWORD dwProviderSubType;
DWORD dwProviderOffset;
DWORD dwProviderSize;
WCHAR wcProviderData[1];
} COMMCONFIG, *LPCOMMCONFIG;

  在我们呼叫 CommConfigDialog() 之前, dwSize 要设为 sizeof(COMMCONFIG), wVersion 的值在这边似乎不重要(我不清楚, VC5 的 on-line help 说可以设为 1, 我手中的 book 的范例是设为 0x100), 呼叫完 CommConfigDialog() 之后, 成员 dcb 中的 BaudRate, ByteSize, StopBits, Parity 就是使用者的设定.

6.Timeout 的机制

  因为传输时并不会维持一个绝对稳定的速率. 因为传输品质的关系, programer 会需要 timeout 的机制来协助他们做一些控制. 在 Win32 通讯 Timeout 的机制中, timeout 的性质共分为两类, 先来看看 COMMTIMEOUTS 这个结构:

[cpp] view plaincopy print?
  1. typedef struct _COMMTIMEOUTS { // ctmo
  2. DWORD ReadIntervalTimeout;
  3. DWORD ReadTotalTimeoutMultiplier;
  4. DWORD ReadTotalTimeoutConstant;
  5. DWORD WriteTotalTimeoutMultiplier;
  6. DWORD WriteTotalTimeoutConstant;
  7. } COMMTIMEOUTS,*LPCOMMTIMEOUTS;
typedef struct _COMMTIMEOUTS { // ctmo
DWORD ReadIntervalTimeout;DWORD ReadTotalTimeoutMultiplier;
DWORD ReadTotalTimeoutConstant;
DWORD WriteTotalTimeoutMultiplier;
DWORD WriteTotalTimeoutConstant;
} COMMTIMEOUTS,*LPCOMMTIMEOUTS;

  programmer 可以利用 GetCommTimeouts() 和 SetCommTimeouts() 来读取或是设定目前的 timeout 值.

[cpp] view plaincopy print?
  1. BOOL GetCommTimeouts(
  2. HANDLE hFile, // handle of communications device
  3. LPCOMMTIMEOUTS lpCommTimeouts // address of comm. time-outs structure
  4. );
BOOL GetCommTimeouts(
HANDLE hFile, // handle of communications device
LPCOMMTIMEOUTS lpCommTimeouts // address of comm. time-outs structure
);
[cpp] view plaincopy print?
  1. BOOL SetCommTimeouts(
  2. HANDLE hFile, // handle of communications device
  3. LPCOMMTIMEOUTS lpCommTimeouts // address of communications time-out structure
  4. );
BOOL SetCommTimeouts(
HANDLE hFile, // handle of communications device
LPCOMMTIMEOUTS lpCommTimeouts // address of communications time-out structure
);

  第一种 timeout 的机制称为 interval timeout, 从字面上的意义很容易可以理解这种 timeout 的机制是读取字符之间的间隔时间的 timeout, 只有读取字符时才能够使用interval timeout. 也就是在这个结构中的 ReadIntervalTimeout, 单位为 ms, 当读取完一个字符后, 超过了 ReadIntervalTimeout 的值, 却还没有读到下一个字符时, timeout 就发生了.

  第二种 timeout 的机制称为 total timeout, 顾名思义即是传输的总时间的 timeout . 在这种 timeout 的机制下, Win32 提供了一个具有弹性的方式来设定 total timeout. 以读取的 total timeout 为例, 利用 ReadTotalTimeoutMultiplier 和 ReadTotalTimeoutConstant 构成了一个线性的上限值. 什么意思呢? 实际上的 total timeout 应该是这样的一个式子:

  ReadTotalTimeout = ReadTotalTimeOutMultiplier * BytesToRead + ReadTotalTimeoutConstant

  WriteTotalTimeout 用同样的公式来计算. 这样的话, 不仅可以用一个固定的值来做为 timeout 值, 也可以用条线来做为 timeout 的值, 而随着要读取或是要写的 bytes 数而变动.

  如果不想使用 timeout, 就把 COMMTIMEOUTS 里头的资料成员都填为 0.

  如果你将 ReadIntervalTimeout 设为 MAXDWORD, 且将 ReadTotalTimeOutMultiplier 和 ReadTotalTimeoutConstant 都设为 0 的话, 那么读取时, 如果 receive queue 里头并没有资料, 读取的动作将会马上返回, 而不会停滞在读取的动作.

  这里有一个和 BuildCommDCB() 很像的 API 叫 BuildCommDCBAndTimeouts():

[cpp] view plaincopy print?
  1. BOOL BuildCommDCBAndTimeouts(
  2. LPCTSTR lpDef, // pointer to the device-control string
  3. LPDCB lpDCB, // pointer to the device-control block
  4. LPCOMMTIMEOUTS lpCommTimeouts // pointer to comm. time-out structure
  5. );
BOOL BuildCommDCBAndTimeouts(
LPCTSTR lpDef, // pointer to the device-control string
LPDCB lpDCB, // pointer to the device-control block
LPCOMMTIMEOUTS lpCommTimeouts // pointer to comm. time-out structure
);

  lpDef 一样是控制字符串, 可以给像 BuildCommDCB() 中的 lpDef 那样格式的字符串, 但是多了 "TO=XXX" 这个设定. 如果 "TO=ON", 这个 API 会依据 lpCommTimeouts 里头的值来设定读和写的 timeout 值. 如果 "TO=OFF", 则会设定这个 device 没有 timeout. 如果是 "ON" 和 "OFF" 之外的其它值, 则 lpCommTimeouts 的设定将会被忽略.

  对了, 在设定完 timeout 值之后, 记得要检查 COMMPROP 里的 dwProvCapabilities 中的 PCF_INTTIMEOUTS 和 PCF_TOTALTIMEOUTS 两个 flags 是否有被 set, 以确认 interval timeout 和 total timeout 是否有支持.

7.读取资料

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

[cpp] view plaincopy print?
  1. BOOL ReadFile(
  2. HANDLE hFile, // handle of file to read
  3. LPVOID lpBuffer, // address of buffer that receives data
  4. DWORD nNumberOfBytesToRead, // number of bytes to read
  5. LPDWORD lpNumberOfBytesRead, // address of number of bytes read
  6. LPOVERLAPPED lpOverlapped // address of structure for data
  7. );
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 内等待读或写的资料.

[cpp] view plaincopy print?
  1. BOOL PurgeComm(
  2. HANDLE hFile, // handle of communications resource
  3. DWORD dwFlags // action to perform
  4. );
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(), 从字面上的意思看来, 它是用来清除错误情况用的, 但是实际上它还可以拿来取得目前通讯设备的一些信息.

[cpp] view plaincopy print?
  1. BOOL ClearCommError(
  2. HANDLE hFile, // handle to communications device
  3. LPDWORD lpErrors, // pointer to variable to receive error codes
  4. LPCOMSTAT lpStat // pointer to buffer for communications status
  5. );
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 的结构如下:

[cpp] view plaincopy print?
  1. typedef struct _COMSTAT { // cst
  2. DWORD fCtsHold : 1; // Tx waiting for CTS signal
  3. DWORD fDsrHold : 1; // Tx waiting for DSR signal
  4. DWORD fRlsdHold : 1; // Tx waiting for RLSD signal
  5. DWORD fXoffHold : 1; // Tx waiting, XOFF char rec'd
  6. DWORD fXoffSent : 1; // Tx waiting, XOFF char sent
  7. DWORD fEof : 1; // EOF character sent
  8. DWORD fTxim : 1; // character waiting for Tx
  9. DWORD fReserved : 25; // reserved
  10. DWORD cbInQue; // bytes in input buffer
  11. DWORD cbOutQue; // bytes in output buffer
  12. } COMSTAT, *LPCOMSTAT
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.

[cpp] view plaincopy print?
  1. BOOL WriteFile(
  2. HANDLE hFile, // handle to file to write to
  3. LPCVOID lpBuffer, // pointer to data to write to file
  4. DWORD nNumberOfBytesToWrite, // number of bytes to write
  5. LPDWORD lpNumberOfBytesWritten, // pointer to number of bytes written
  6. LPOVERLAPPED lpOverlapped // pointer to structure needed for overlapped I/O
  7. );
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().

[cpp] view plaincopy print?
  1. BOOL SetCommBreak(
  2. HANDLE hFile // handle of communications device
  3. );
BOOL SetCommBreak(
HANDLE hFile // handle of communications device
);
[cpp] view plaincopy print?
  1. BOOL ClearCommBreak(
  2. HANDLE hFile // handle to communications device
  3. );
BOOL ClearCommBreak(
HANDLE hFile // handle to communications device
);
[cpp] view plaincopy print?
  1. BOOL TransmitCommChar(
  2. HANDLE hFile, // handle of communications device
  3. char cChar // character to transmit
  4. );
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() 来取得或是设定目前设定的通讯事件.

[cpp] view plaincopy print?
  1. BOOL GetCommMask(
  2. HANDLE hFile, // handle of communications device
  3. LPDWORD lpEvtMask // address of variable to get event mask
  4. );
BOOL GetCommMask(
HANDLE hFile, // handle of communications device
LPDWORD lpEvtMask // address of variable to get event mask
);
[cpp] view plaincopy print?
  1. BOOL SetCommMask(
  2. HANDLE hFile, // handle of communications device
  3. DWORD dwEvtMask // mask that identifies enabled events
  4. );
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()

[cpp] view plaincopy print?
  1. BOOL WaitCommEvent(
  2. HANDLE hFile, // handle of communications device
  3. LPDWORD lpEvtMask, // address of variable for event that occurred
  4. LPOVERLAPPED lpOverlapped, // address of overlapped structure
  5. );
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 对几个硬件讯号做控制.

[cpp] view plaincopy print?
  1. BOOL EscapeCommFunction(
  2. HANDLE hFile, // handle to communications device
  3. DWORD dwFunc // extended function to perform
  4. );
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() 的意思相同

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zeroless/archive/2006/01/10/575581.aspx

Win32串口操作的技巧相关推荐

  1. 串口操作之API篇 CreateFile

    CreateFile http://bbs.fishc.com/thread-72944-1-1.html (出处: 鱼C论坛) ----------------------------------- ...

  2. Win32串口API

    Win32串口API 在工业控制中,工控机(一般都基于Windows平台)经常需要与智能仪表通过串口进行通信.串口通信方便易行,应用广泛.  一般情况下,工控机和各智能仪表通过RS485总线进行通信. ...

  3. linux串口拼接,Linux下串口操作之數據拼接

    串口操作中,特別以非阻塞的方式讀取和發送數據,做好進程之間的同步很重要.有時我們會發現這樣一個問題,在進行read操作時,一次read不能獲得一個完整的數據幀,這就好比你買了一個電腦,送貨的先把顯示器 ...

  4. 安徽信息技术初中会考上机考试模拟_中学信息技术上机操作考试技巧

    中学信息技术上机操作考试技巧 中学信息技术上机操作考试技巧 惠安三中 曾惠忠 [内容摘要] 本文是作者结合两年来福建省中学信息技术上机操作考试情况,对考生容易出现的一些问题加以分析.总结.希望本文的介 ...

  5. 串口通信模块4:串口操作自定义类(1)

    为了以后使用方便,将串口的属性及操作封装成一个类.对串口的操作可以直接通过调用这个串口类提供的几个函数接口即可. 1.CMySerial类的定义:MySerial.h #pragma once #in ...

  6. 未来教育计算机二级Excel解析,Excel操作小技巧,助你学好计算机二级office!

    原标题:Excel操作小技巧,助你学好计算机二级office! Office考试中最难的是什么?当然是Excel函数啊! 小编辛苦整理了excel10大懒人技巧,让你考试速提分!还不赶紧收藏起来 一. ...

  7. recovery模式下支持ADB连接和串口操作

    前言 Android平台下我们有时候会进入recovery下做一些操作,不管是通过ADB连接还是通过串口操作,都需要你的平台支持,不支持的话可以按照我们这篇文章进行修改. 正文 ADB连接 进入rec ...

  8. 神奇的python(六)之python的串口操作(pyserial)

    简介:最近项目突然要使用python串口操作,这不,查资料,翻文档,是时候写一份串口操作的简要用法,以后有时间可以使用pyqt再写个界面,弄个串口调试终端. (1) 安装pyserial库 pip i ...

  9. 31.QT中串口操作

    记录一下QT下的串口操作 #include <QSerialPort>QSerialPort * serialPort;serialPort = new QSerialPort;seria ...

最新文章

  1. 【机器学习】扎实入门机器学习的路子
  2. 信息抽取新SOTA!首个结构化生成式信息抽取预训练模型,一统信息抽取四大任务...
  3. 有意思,USB资料分享
  4. eeglab基础学习
  5. 自己动手开发多线程异步 MQL5 WEBREQUEST
  6. 双三次插值(BiCubic插值)
  7. 关于JavaScript继承与原型链的一些理解
  8. 教程篇(7.0) 09. FortiGate安全 应用控制 ❀ Fortinet 网络安全专家 NSE 4
  9. 转专业计算机类面试自我介绍,转专业面试自我介绍
  10. Java字节流读取shp_shp系列(四)——利用C++进行Shx文件的读(打开)
  11. perl中正则匹配中文字符
  12. (心态篇)空杯心态,一个程序员的自我修炼
  13. DeepMind再爆性骚扰丑闻!内部邮件泄露,色狼自夸猛男
  14. 利用jQuery UI为CMS网站实现拖拽布局效果,秒杀table布局
  15. ShopXO开源电商系统源码支持PC+H5支付宝小程序微信小程序百度小程序头条抖音小程序QQ小程序APP等
  16. git 如何提交丰富的emoji表情
  17. 20175312 2018-2019-2 实验三 敏捷开发与XP实践 实验报告
  18. html绝对定位自适应不同分辨率,如何利用“自适应网页设计”实现不同的设备上呈现同样的网页...
  19. canvas在线画图
  20. 2022年NOC软件创意编程(学而思)决赛小学高年级组scratch

热门文章

  1. 2020-12-03 The Geometry of Rotations and Rigid-Body Motions (刚体运动和旋转的几何表示,罗德里格参数)
  2. ThreadLocalT
  3. Exynos4412裸机开发 —— 看门狗定时器
  4. UVa 10082 - WERTYU 解题报告 - C语言
  5. StringWriter/PrintWriter在Java输出异常信息中的作用
  6. css 实现页面加载中等待效果
  7. (转)NAT与NAT穿透 原理
  8. GridView绑定数据源 绑定DataReader /DataSet /DataTable
  9. 2019牛客多校一 D. Parity of Tuples
  10. Hadoop平台K-Means聚类算法分布式实现+MapReduce通俗讲解