【STM32】Modbus配置的一些问题
很久没有使用Modbus了,记得上一次使用还是在STM32L4平台,现在需要再F103上再使用,遇到了一些问题,顺便记录一下。
一、移植Modbus的注意事项
在移植完Modbus的库文件之后,对于在项目中实际使用的芯片需要移植底层接口。这些底层接口分为两类
(1)定时器——用于帧间隔
(2)通信接口——数据传输使用,可以使串口,USB等。
如下图所示:在我的工程中主要有以下文件

其中portserial.c和porttimer.h是我放定时器和串口的底层接口的地方,一般情况下,无论你使用的是标准库,HAL或LL库,只需要将对应的接口函数放进去就没什么问题。
二、串口配置
在主函数main.c中,需要通过modbus提供的函数,对串口和定时器初始化,一般情况下,我习惯于将原本的初始化函数注释掉,防止一些奇怪的问题。

初始化函数的入口参数最后会涉及到portserial.c中的串口配置,需要在其中修改,我这里就只适配了波特率,有必要的话可以将其它参数也配置好。

串口中断内加入Modbus的状态机
void USART2_IRQHandler(void)
{
/* USER CODE BEGIN USART2_IRQn 0 */
if(LL_USART_IsActiveFlag_RXNE(USART2) == SET)
{
LL_USART_ClearFlag_RXNE(USART2);
prvvUARTRxISR();//接收状态机
}
//发生完成中断
if(LL_USART_IsActiveFlag_TC(USART2) == SET)
{
prvvUARTTxReadyISR();//发送状态机
//清除中断标志
LL_USART_ClearFlag_TC(USART2);
}
}
移植发送和接收函数到modbus内

如果你使用的485,并且需要使用单独IO来控制发送和接收的话,也需要将函数加到上图的函数内。
三、定时器配置及踩坑
在porttimer.c内,如下

尤其需要注意红色方框内的部分,ARR寄存器要同步到入口参数的变量。另外PSC寄存器配置情况决定了Modbus判断帧间隔的时基。
我使用的定时器时钟是72MHz,最开始我没在意,随便配置的719,即10us,但是后面无论如何也不能实现Modbus的通信。后来我翻看各个库文件,在mbrtu.c文件中,发现如下代码。
eMBErrorCode
eMBRTUInit( UCHAR ucSlaveAddress, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity )
{
eMBErrorCode eStatus = MB_ENOERR;
ULONG usTimerT35_50us;
( void )ucSlaveAddress;
ENTER_CRITICAL_SECTION( );
/* Modbus RTU uses 8 Databits. */
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; /* 1800us. */
}
else
{
/* The timer reload value for a character is given by:
*
* ChTimeValue = Ticks_per_1s / ( Baudrate / 11 )
* = 11 * 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 * 220000UL ) / ( 2UL * ulBaudRate );
}
if( xMBPortTimersInit( ( USHORT ) usTimerT35_50us ) != TRUE )
{
eStatus = MB_EPORTERR;
}
}
EXIT_CRITICAL_SECTION( );
return eStatus;
}
先不论他里面的算式有何意义,或者这些帧判别代码是怎么实现的,我发现他里面的变量usTimerT35_50us后缀是50us,对于Modbus来说3.5T是一个很关键的数字,如果不知道为什么,那需要去看一下Modbus基础的知识。
既然其后缀是50us,那么为了让我的定时器适配这些功能,我也需要将我的定时器配置成计数间隔为50us。所以我将PSC的数值719改为3599后就可以正常使用了。
6706

被折叠的 条评论
为什么被折叠?



