【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后就可以正常使用了。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值