串口编程:超时COMMTIMEOUTS结构

原文:http://forum.eet-cn.com/BLOG_ARTICLE_3446.HTM

串口编程之二:超时COMMTIMEOUTS结构

 

在WIN32  API编程中,除了DCB结构之外,还需要了解COMMTIMEOUTS结构.这个结构是为了读写串口的超时而设置的.

COMMTIMEOUTS结构如下:  
   
  typedef   struct   _COMMTIMEOUTS   {    
  DWORD   ReadIntervalTimeout;                 //任意相邻连个字符之间的超时设置
  DWORD   ReadTotalTimeoutMultiplier;        //读操作总的超时时间的系数
  DWORD   ReadTotalTimeoutConstant;       //读操作总的超时时间的修正常量
  DWORD   WriteTotalTimeoutMultiplier;       //写操作总的超时时间的系数
  DWORD   WriteTotalTimeoutConstant;       //写操作总的超时时间的修正常量
  }   COMMTIMEOUTS,*LPCOMMTIMEOUTS;     
      
    
    ReadIntervalTimeout:两相邻字符之间最大的延时。当读串口数据时,一旦两个字符传输的时间间隔超过该时间,读函数将返回现有的数据。设置为0表示该参数不起作用。    
   
    ReadTotalTimeoutMultiplier:读操作总的超时事件的系数。 这个变量是不能单独使用的。 必须和ReadTotalTimeoutConstant 一起使用才有效果。    
    
    ReadTotalTimeoutConstant:读操作总的超时时间的修正常量。 这个变量也是不能单独使用的。必须和ReadTotalTimeoutMultiplier一起使用才有效果。 
    
    WriteTotalTimeoutMultiplier:写操作总的超时事件的系数。 这个变量是不能单独使用的。 必须和WriteTotalTimeoutConstant 一起使用才有效果。   
    
    WriteTotalTimeoutConstant:写操作总的超时时间的修正常量。 这个变量也是不能单独使用的。必须和WriteTotalTimeoutMultiplier一起使用才有效果。

       在整个串口的读写操作中, 存在着两种超时设置。一种是间隔超时, 一种是总超时。 这两种超时是独立存在,互不影响的。 

      间隔超时, 只在读操作中存在。就是ReadIntervalTimeout。 当读操作中,前后两个字符之间的时间间隔超过时,读操作就结束了。举例来说,你一次读取8个字符,但是在你读取了第一个字符之后,在读取第二个字符时,间隔超时了,那么读操作就结束了, 这样整个操作就只读取了1个字节。 即使, 你的总时间没有超时。 

       另一种超时,就是总超时。 这里有一个公式。
       总的读/写超时时间 = Read(Write)TotalTimeoutMultiplier x 要读/写的字节数 + Read(Write)TotalTimeoutConstant. 
       这里要说明的一点,要读/写的字节数是从哪里来的。 这个是从ReadFile 或者WriteFile 函数中定义的。
       在读操作时, 若当前所花读取时间已经超过了总的超时设置, 则读操作就结束了。即使, 每两个字符之间的间隔没有超时。 举例来说, 若总共读取8个字节。 间隔设置为8ms, 总超时系数为3ms,总超时常数为3ms。 则总的超时时间为3*8+3=27ms。若每个字符读取的间隔为7ms, 则这次操作总共能读取4个字符。 就结束了。因为读取第5个字符时, 已经需要35ms, 超过总超时时间了。

下面来讨论一下这几个参数的设定:
将ReadIntervalTimeout设置为MAXDWORD,将ReadTotalTimeoutMultiplier   和ReadTotalTimeoutConstant设置为0,表示读操作将立即返回存放在输入缓冲区的字符。  

将ReadIntervalTimeout设置为MAXDWORD,将ReadTotalTimeoutMultiplier   和ReadTotalTimeoutConstant设置为MAXDWORD, 表示读操作会一直等待直到所需要读取的字节数全部接收到为止。 (大家可以把MAXDWORD 认为是永远)

将ReadIntervalTimeout设置为0, 则不使用间隔超时, 只考虑总超时设置。

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Visual Studio 2019是微软开发的一款强大的集成开发环境,它支持多种编程语言和多种平台的开发。在Visual Studio 2019中进行串口编程可以使用C++或C#等语言进行开发。串口编程需要借助Windows API来实现,具体步骤如下: 1. 打开Visual Studio 2019,创建一个新的控制台应用程序项目。 2. 在项目中添加一个头文件“Windows.h”。 3. 声明并初始化一个DCB结构体变量,设置串口的波特率、数据位、停止位和校验位等参数。 4. 调用CreateFile函数打开串口并获取串口句柄。 5. 使用WriteFile函数向串口发送数据,使用ReadFile函数从串口读取数据。 6. 关闭串口,释放句柄。 下面是一段C++代码示例: ``` #include <Windows.h> #include <iostream> int main() { HANDLE hSerial; DCB dcbSerialParams = { 0 }; COMMTIMEOUTS timeouts = { 0 }; DWORD dwBytesWritten = 0; DWORD dwBytesRead = 0; hSerial = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hSerial == INVALID_HANDLE_VALUE) { std::cout << "Failed to open serial port!" << std::endl; return 1; } dcbSerialParams.DCBlength = sizeof(dcbSerialParams); if (!GetCommState(hSerial, &dcbSerialParams)) { std::cout << "Failed to get serial parameters!" << std::endl; CloseHandle(hSerial); return 1; } dcbSerialParams.BaudRate = CBR_9600; dcbSerialParams.ByteSize = 8; dcbSerialParams.StopBits = ONESTOPBIT; dcbSerialParams.Parity = NOPARITY; if (!SetCommState(hSerial, &dcbSerialParams)) { std::cout << "Failed to set serial parameters!" << std::endl; CloseHandle(hSerial); return 1; } timeouts.ReadIntervalTimeout = 50; timeouts.ReadTotalTimeoutConstant = 50; timeouts.ReadTotalTimeoutMultiplier = 10; timeouts.WriteTotalTimeoutConstant = 50; timeouts.WriteTotalTimeoutMultiplier = 10; if (!SetCommTimeouts(hSerial, &timeouts)) { std::cout << "Failed to set timeouts!" << std::endl; CloseHandle(hSerial); return 1; } char buffer[] = "Hello, world!"; if (!WriteFile(hSerial, buffer, sizeof(buffer), &dwBytesWritten, NULL)) { std::cout << "Failed to write to serial port!" << std::endl; CloseHandle(hSerial); return 1; } char readBuffer[1024]; if (!ReadFile(hSerial, readBuffer, sizeof(readBuffer), &dwBytesRead, NULL)) { std::cout << "Failed to read from serial port!" << std::endl; CloseHandle(hSerial); return 1; } std::cout << "Received data: " << readBuffer << std::endl; CloseHandle(hSerial); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值