Modbus协议 报文间隔3.5个字符计算&设置



Modbus 协议报文间隔需要大于3.5个字符。

Freemodbus需要配合一个定时器使用,这是因为它是通过定时器超时来判断Modbus传输过程结束的,在Modbus协议中,以RTU模式为例,报文帧由时长至少为3.5个字符的空闲间隔区分,这个区间被称为t3.5,注意,这里是“至少”不是至多,也就是通信之间也不希望对方发的过快,所以在Freemodbus中对定时器就采用了类似于四舍五入的办法,比3.5个字符略微多一点的溢出时间。

Modbus 协议报文间隔需要大于3.5个字符计算:

1.1、有检验位

1个字符=1(起始位)+8(数据位)+1(奇偶校验位)+1(停止位)=11位

3.5个字符=3.5*11=38.5位

如果波特率=9600bps,则3.5个字符间隔时间为38.5/9.6=4.0104167毫秒

1.2、无校验位

1个字符=1(起始位)+8(数据位)+0(无校验位)+1(停止位)=10位

3.5个字符=3.5*10=35位

如果波特率=9600bps,则3.5个字符间隔时间为35/9.6=3.6458毫秒

2、通常可以将传输45位的时间四舍五入后做为报文时间间隔。

如果波特率=9600bps,则45位传输时间为45/9.6=4.6875≈5毫秒

所以Freemodus的作者做了一个 特别巧妙的公式变量:

usTimerT35_50us = ( 7UL * 220000UL ) / ( 2UL * ulBaudRate )

这里,usTimerT35_50us表示 3.5个字符,对应 50us的倍数,以波特率9600计算,刚刚理论计算为4ms左右,4000us/50us = 80

那么这个公式的计算结果是:usTimerT35_50us = ( 7UL * 220000UL ) / ( 2UL * ulBaudRate ) = 7*220000/(2*9600) = 80.2,这个值是无符号整型,所以就是80。

那么算出 80 以后怎么用呢,80代表的是80个 50us,这是作者为了移植方便,所以都用 50us作为基准,在具体使用的时候,刚说到要比t3.5稍微大点,大太多,反应慢,容易出错,作者给了一种方法:

usTimeoutMS = ( usTim1Timerout50us + 10 ) / 20;

其中 usTimeoutMS 就是要延时的ms数,还是以9600为例,那么定时器溢出时间为  (80+10)/20 = 4ms,然后移植者再根据自己的处理器,设置4ms的定时器溢出即可。

针对F460的设置:

		stcTimerCfg.Tim0_CounterMode = Tim0_Sync;//同步计数模式
		stcTimerCfg.Tim0_SyncClockSource = Tim0_Pclk1;//选择时钟(时钟配置的是100M)
		stcTimerCfg.Tim0_ClockDivision = Tim0_ClkDiv1024;//分频 (97656.25Hz)

//波特率大于19200,统一设置1750us

//波特率大于19200,统一设置1750us
stcTimerCfg.Tim0_CmpValue = (uint16_t) 171;//19200以上,统一配置1750us:171=97656.25/1000000*1750        

//波特率小于19200, 设置t35

stcTimerCfg.Tim0_CmpValue = (uint16_t) 5 * (usTimerT35_50us+10);//19200以下, 97656.25/1000000 * (usTimerT35_50us+10) * 50 = 97656.25/20000 * (usTimerT35_50us+10) = 5 * (usTimerT35_50us+10)


版权声明:本文为childbor原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。