关于论坛中Freemodbus定时器配置的一个问题说明,研究modbus的都可以看看

QQ群有人问,那个移植的modbus的定时器配置如下:


void MX_TIM4_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;

htim4.Instance = TIM4;
htim4.Init.Prescaler = 4199;
htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
htim4.Init.Period = 35;
htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(&htim4);

sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig);

sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig);

}

系统时钟168M,用定时器4,它的时钟为84Mhz
那么分频后时钟频率为84M/4200=20000hz
即时间应该是1/20000s=50us
下面的计时周期是35,那么定时时间就是50*35us=1750us

然而我们用的波特率是115200,
按照modbus协议,超时时间为3.5个字符时间
那么单个个时间究竟是多少呢?
问题是:

如果波特率是115200,3.5个字符不也应该是245微秒吗?
20KHZ 35个脉冲,是不是有些太多了?

///////////////////////////////////////////////////////////////////////////////////

针对这个问题, 要去仔细看看freemodbus的程序了.
找到文件mbrtu.c
打开,看到里面有这个代码:


eMBRTUInit( UCHAR ucSlaveAddress, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity )
{
eMBErrorCode eStatus = MB_ENOERR;
ULONG usTimerT35_50us;

( void )ucSlaveAddress;
ENTER_CRITICAL_SECTION( );

/[i] Modbus RTU uses 8 Databits. [/i]/
if( xMBPortSerialInit( ucPort, ulBaudRate, 8, eParity ) != TRUE )
{
eStatus = MB_EPORTERR;
}
else
{
/* If baudrate > 19200 then we should use the fixed timer values
* t35 = 1750us. Otherwise t35 must be 3.5 times the character time.
*/
if( ulBaudRate > 19200 )
{
usTimerT35_50us = 35; /[i] 1800us. [/i]/
}
else
{
/* The timer reload value for a character is given by:
*
* ChTimeValue = Ticks_per_1s / ( Baudrate / 11 )
[i] = 11 [/i] Ticks_per_1s / Baudrate
* = 220000 / Baudrate
* The reload for t3.5 is 1.5 times this value and similary
* for t3.5.
*/
usTimerT35_50us = ( 7UL [i] 220000UL ) / ( 2UL [/i] ulBaudRate );
}
if( xMBPortTimersInit( ( USHORT ) usTimerT35_50us ) != TRUE )
{
eStatus = MB_EPORTERR;
}
}
EXIT_CRITICAL_SECTION( );

return eStatus;
}

上面的代码是初始化modbus,根据波特率自动调整定时时间,
主要看这句


/* If baudrate > 19200 then we should use the fixed timer values
* t35 = 1750us. Otherwise t35 must be 3.5 times the character time.
*/
if( ulBaudRate > 19200 )
{
usTimerT35_50us = 35; /[i] 1800us. [/i]/
}
else
{
/* The timer reload value for a character is given by:
*
* ChTimeValue = Ticks_per_1s / ( Baudrate / 11 )
[i] = 11 [/i] Ticks_per_1s / Baudrate
* = 220000 / Baudrate
* The reload for t3.5 is 1.5 times this value and similary
* for t3.5.
*/
usTimerT35_50us = ( 7UL [i] 220000UL ) / ( 2UL [/i] ulBaudRate );

如果波特率大于19200那么超时时间应该是固定为1750us
如果小于那么要根据3.5个字符时间定时了...
具体的定时时间计算里面也详细的给出了一个公式..不再解释了...

由上面可以得出,我们115200波特率的定时时间应该是1750us,那么
我们就可以确定,我们配置定时器的时候应该配置多少了.
正如刚开始写的,分频4200,需35个计时周期.
所以我们用stm32cubemx配置的时候直接就这样配置了.

这样做的好处,正如我移植的modbus里面的代码一样
文件porttimer.c中的函数


BOOL
xMBPortTimersInit( USHORT usTim1Timerout50us )
{
return TRUE;;
}

里面就可以不用去配置了,因为我们用stm32cubemx配置的时候已经定义好了超时时间,这里就不用写任何代码了.....

好了,如果大家对论坛中的那个移植的modbus有任何其他问题也可以在下面回复,我尽力回答
已邀请:

chney

赞同来自:

正在学习modbus 感谢分享。

要回复问题请先登录注册