串口编程 —— 实现 GPS 过程中自己用到的函数 COMMTIMEOUTS,SetCommMask,SetCommTimeouts...

一、COMMTIMEOUTS

COMMTIMEOUTS:COMMTIMEOUTS主要用于串口超时参数设置。COMMTIMEOUTS结构如下:

typedef struct _COMMTIMEOUTS {
DWORD ReadIntervalTimeout;
DWORD ReadTotalTimeoutMultiplier;
DWORD ReadTotalTimeoutConstant;
DWORD WriteTotalTimeoutMultiplier;
DWORD WriteTotalTimeoutConstant;
} COMMTIMEOUTS,*LPCOMMTIMEOUTS;


  ReadIntervalTimeout:两字符之间最大的延时,当读取串口数据时,一旦两个字符传输的时间差超过该时间,读取函数将返回现有的数据。设置为0表示该参数不起作用。

  ReadTotalTimeoutMultiplier:读取每字符间的超时。

  ReadTotalTimeoutConstant:一次读取串口数据的固定超时。所以在一次读取串口的操作中,其超时为ReadTotalTimeoutMultiplier乘以读取的字节数再加上 ReadTotalTimeoutConstant。将ReadIntervalTimeout设置为MAXDWORD,并将ReadTotalTimeoutMultiplier 和ReadTotalTimeoutConstant设置为0,表示读取操作将立即返回存放在输入缓冲区的字符。

  WriteTotalTimeoutMultiplier:写入每字符间的超时。

  WriteTotalTimeoutConstant:一次写入串口数据的固定超时。所以在一次写入串口的操作中,其超时为WriteTotalTimeoutMultiplier乘以写入的字节数再加上 WriteTotalTimeoutConstant。

一般都会做以下设置:
TimeOuts.ReadIntervalTimeout=MAXDWORD;
// 把间隔超时设为最大,把总超时设为0将导致ReadFile立即返回并完成操作

TimeOuts.ReadTotalTimeoutMultiplier=0;
//读时间系数

TimeOuts.ReadTotalTimeoutConstant=0;
//读时间常量

TimeOuts.WriteTotalTimeoutMultiplier=50;
//总超时=时间系数*要求读/写的字符数+时间常量

TimeOuts.WriteTotalTimeoutConstant=2000;
//设置写超时以指定WriteComm成员函数中的

二、SetCommTimeouts

要查询当前的超时设置应调用GetCommTimeouts函数,该函数会填充一个COMMTIMEOUTS结构。调用SetCommTimeouts可以用某一个COMMTIMEOUTS结构的内容来设置超时。

  有两种超时:间隔超时和总超时。间隔超时是指在接收时两个字符之间的最大时延,总超时是指读写操作总共花费的最大时间。写操作只支持总超时,而读操作两种超时均支持。用COMMTIMEOUTS结构可以规定读/写操作的超时,该结构的定义为:

typedef struct _COMMTIMEOUTS {

DWORD ReadIntervalTimeout; // 读间隔超时

DWORD ReadTotalTimeoutMultiplier; // 读时间系数

DWORD ReadTotalTimeoutConstant; // 读时间常量

DWORD WriteTotalTimeoutMultiplier; // 写时间系数

DWORD WriteTotalTimeoutConstant; // 写时间常量

} COMMTIMEOUTS,*LPCOMMTIMEOUTS;

  COMMTIMEOUTS结构的成员都以毫秒为单位。总超时的计算公式是:

总超时=时间系数×要求读/写的字符数 + 时间常量

  例如,如果要读入10个字符,那么读操作的总超时的计算公式为:

读总超时=ReadTotalTimeoutMultiplier×10 + ReadTotalTimeoutConstant

  可以看出,间隔超时和总超时的设置是不相关的,这可以方便通信程序灵活地设置各种超时。

  如果所有写超时参数均为0,那么就不使用写超时。如果ReadIntervalTimeout为0,那么就不使用读间隔超时,如果ReadTotalTimeoutMultiplier和ReadTotalTimeoutConstant都为0,则不使用读总超时。如果读间隔超时被设置成MAXDWORD并且两个读总超时为0,那么在读一次输入缓冲区中的内容后读操作就立即完成,而不管是否读入了要求的字符。

三、SetCommMask

SetCommMask ()函数设置事件掩模来监视指定通信端口上的事件,其原型为:


BOOL SetCommMask(
 HANDLE hFile, //标识通信端口的句柄
 DWORD dwEvtMask //能够使能的通信事件
);

  串口上可能发生的事件如下表所示:

事件描述
EV_BREAKA break was detected on input.
EV_CTSThe CTS (clear-to-send) signal changed state.
EV_DSRThe DSR(data-set-ready) signal changed state.
EV_ERRA line-status error occurred. Line-status errors are CE_FRAME, CE_OVERRUN, and CE_RXPARITY.
EV_RINGA ring indicator was detected.
EV_RLSDThe RLSD (receive-line-signal-detect) signal changed state.
EV_RXCHARA character was received and placed in the input buffer.
EV_RXFLAGThe event character was received and placed in the input buffer. The event character is specified in the device's DCB structure, which is applied to a serial port by using the SetCommState function.
EV_TXEMPTYThe last character in the output buffer was sent.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是在 Visual Studio 使用读取串口数据的函数来读取 GPS 字符串的代码: ```c++ #include <Windows.h> #include <string> #include <iostream> using namespace std; int main() { HANDLE hComm; DWORD dwBytesRead; // Open the serial port hComm = CreateFile("COM1", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); if (hComm == INVALID_HANDLE_VALUE) { cout << "Error in opening serial port" << endl; return 0; } // Initialize the DCB structure DCB dcb; SecureZeroMemory(&dcb, sizeof(DCB)); dcb.DCBlength = sizeof(DCB); // Get the serial port's configuration if (!GetCommState(hComm, &dcb)) { cout << "Error in getting the serial port's configuration" << endl; return 0; } // Set the serial port's configuration dcb.BaudRate = CBR_9600; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; if (!SetCommState(hComm, &dcb)) { cout << "Error in setting the serial port's configuration" << endl; return 0; } // Initialize the timeouts structure COMMTIMEOUTS timeouts; SecureZeroMemory(&timeouts, sizeof(COMMTIMEOUTS)); timeouts.ReadIntervalTimeout = 50; timeouts.ReadTotalTimeoutConstant = 50; timeouts.ReadTotalTimeoutMultiplier = 10; if (!SetCommTimeouts(hComm, &timeouts)) { cout << "Error in setting the serial port's timeouts" << endl; return 0; } // Read the GPS data from the serial port char data[100]; string gpsData; while (true) { if (!ReadFile(hComm, data, sizeof(data), &dwBytesRead, NULL)) { cout << "Error in reading from the serial port" << endl; return 0; } if (dwBytesRead > 0) { gpsData.append(data, dwBytesRead); if (gpsData.find("\n") != string::npos) { cout << gpsData; gpsData.clear(); } } } // Close the serial port CloseHandle(hComm); return 0; } ``` 请注意,上面的代码仅仅是演示如何使用串口读取函数读取 GPS 字符串,如果您要使用这个代码,需要根据实际情况进行修改和完善。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值