COMMTIMEOUTS

在用ReadFile和WriteFile读写 串行口时,需要考虑超时问题。如果在指定的时间内没有读出或写入指定数量的字符,那么ReadFile或WriteFile的操作就会结束。要查询当前的超时设置应调用 GetCommTimeouts函数,该函数会填充一个COMMTIMEOUTS结构。调用 SetCommTimeouts可以用某一个COMMTIMEOUTS结构的内容来设置超时。 有两种超时:间隔超时和总超时。间隔超时是指在接收时两个字符之间的最大时延,总超时是指读写操作总共花费的最大时间。写操作只支持总超时,而读操作两种超时均支持。
用COMMTIMEOUTS结构可以规定读/写操作的超时,该结构的定义为:
typedef struct _COMMTIMEOUTS {
DWORD ReadIntervalTimeout; // 读间隔超时
DWORD ReadTotalTimeoutMultiplier; // 读时间系数
DWORD ReadTotalTimeoutConstant; // 读时间 常量
DWORD WriteTotalTimeoutMultiplier; // 写时间系数
DWORD WriteTotalTimeoutConstant; // 写时间常量
} COMMTIMEOUTS,*LPCOMMTIMEOUTS;
COMMTIMEOUTS结构的成员都以毫秒为单位。
ReadIntervalTimeout:两字符之间最大的延时,当读取串口数据时,一旦两个字符传输的时间差超过该时间,读取函数将返回现有的数据。设置为0表示该参数不起作用。指定时间最大值(毫秒),充许接收的2个字节间有时间差。也就 是说,刚接收了一个字节后,等了ReadIntervalTimeout时间后还没有新的字节到达,就 认为本次读串口操作结束(后面的字节等下一次读取操作来处理)。即使你想读8个字节,但读第2个字节后,过了ReadIntervalTimeout时间后,第3个字节还没到。实际上就只读了2个字节。
ReadTotalTimeoutMultiplier:指定比例因子(毫秒),实际上是设置读取一个字节和等待下一个字节所需的时间,这样总的超时时间为读取的字节数乘以该值,同样一次读取操作到达这个时间后,也认为本次读操作己经结束。
ReadTotalTimeoutConstant:一次读取串口数据的固定超时。所以在一次读取串口的操作中,其超时为ReadTotalTimeoutMultiplier乘以读取的字节数再加上 ReadTotalTimeoutConstant。将ReadIntervalTimeout设置为MAXDWORD,并将ReadTotalTimeoutMultiplier 和ReadTotalTimeoutConstant设置为0,表示读取操作将立即返回存放在输入缓冲区的字符。可以理解为一个修正时间,实际上就是按ReadTotalTimeoutMultiplier计算出的超时时间再加上该时间才作为整个超时时间。
WriteTotalTimeoutMultiplier:写入每字符间的超时。
WriteTotalTimeoutConstant:一次写入串口数据的固定超时。所以在一次写入串口的操作中,其超时为WriteTotalTimeoutMultiplier乘以写入的字节数再加上 WriteTotalTimeoutConstant。
一般都会做以下设置:
TimeOuts.ReadIntervalTimeout=MAXDWORD;
// 把间隔超时设为最大,把总超时设为0将导致ReadFile立即返回并完成操作
TimeOuts.ReadTotalTimeoutMultiplier=0;
//读时间系数
TimeOuts.ReadTotalTimeoutConstant=0;
//读时间常量
TimeOuts.WriteTotalTimeoutMultiplier=50;
//总超时=时间系数*要求读/写的字符数+时间常量
TimeOuts.WriteTotalTimeoutConstant=2000;
//设置写超时以指定WriteComm成员函数中的
总超时的计算公式是:
总超时=时间系数×要求读/写的字符数 + 时间 常量
例如,如果要读入10个字符,那么读操作的总超时的计算公式为:
读总超时=ReadTotalTimeoutMultiplier×10 + ReadTotalTimeoutConstant
可以看出,间隔超时和总超时的设置是不相关的,这可以方便通信程序灵活地设置各种超时。如果所有写超时参数均为0,那么就不使用写超时。如果ReadIntervalTimeout为0,那么就不使用读间隔超时,如果
ReadTotalTimeoutMultiplier和ReadTotalTimeoutConstant都为0,则不使用读总超时。如果读间隔超时被设置成MAXDWORD并且两个读总超时为0,那么在读一次输入缓冲区中的内容后读操作就立即完成,而不管是否读入了要求的字符。 在用重叠方式读写 串行口时,虽然ReadFile和WriteFile在完成操作以前就可能返回,但超时仍然是起作用的。在这种情况下,超时规定的是操作的完成时间,而不是ReadFile和WriteFile的返回时间。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RS485是一种串行通信协议,常用于长距离通信和抗干扰能力要求较高的系统中。Delphi是一种高级编程语言,可用于开发Windows应用程序。在Delphi中,可以通过串口组件来实现RS485通信。 以下是基本的Delphi代码示例,用于初始化串口和发送/接收数据: ```delphi uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; Memo1: TMemo; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private { Private declarations } hCom: THandle; dcb: TDCB; commTimeouts: TCommTimeouts; public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.Button1Click(Sender: TObject); var port: string; begin port := 'COM1'; // 串口号 hCom := CreateFile(PChar(port), GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if hCom = INVALID_HANDLE_VALUE then begin ShowMessage('Failed to open ' + port); Exit; end; FillChar(dcb, SizeOf(dcb), 0); GetCommState(hCom, dcb); dcb.BaudRate := 9600; // 波特率 dcb.ByteSize := 8; // 数据位 dcb.Parity := NOPARITY; // 校验位 dcb.StopBits := ONESTOPBIT; // 停止位 SetCommState(hCom, dcb); FillChar(commTimeouts, SizeOf(commTimeouts), 0); commTimeouts.ReadIntervalTimeout := MAXDWORD; commTimeouts.ReadTotalTimeoutMultiplier := MAXDWORD; commTimeouts.ReadTotalTimeoutConstant := 1000; SetCommTimeouts(hCom, commTimeouts); ShowMessage('COM1 is open'); end; procedure TForm1.Button2Click(Sender: TObject); var s: string; buf: array[0..255] of Char; len, n: Cardinal; begin s := 'Hello, world!'; len := Length(s); WriteFile(hCom, s[1], len, n, nil); ShowMessage('Sent ' + IntToStr(n) + ' bytes'); FillChar(buf, SizeOf(buf), 0); ReadFile(hCom, buf, 255, n, nil); SetString(s, buf, n); Memo1.Lines.Add(s); end; ``` 在上面的示例中,我们首先打开一个串口(COM1),然后配置其参数(波特率、数据位、校验位和停止位)。接下来,我们可以使用WriteFile函数向串口发送数据,使用ReadFile函数从串口接收数据。在这个例子中,我们发送了一个字符串“Hello, world!”,并在接收到数据后将其添加到Memo1中。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值