打印
[程序源码]

关于modbus的几点疑惑

[复制链接]
1267|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
huzhiyang|  楼主 | 2020-6-30 22:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 huzhiyang 于 2020-6-30 22:22 编辑

modbus最底层就是基于uart的,我们移植的时候主要的是两个文件,一个c文件提供板级uart的相关接口,用于收发数据;一个c文件提供板级定时器相关接口,用于判断接收发送超时。

我有两个疑问:
1.在串口接收中断里面调用了modbus提供的处理函数,但这个函数里面有很多判断,还有开定时器,我不明白,如果是115200这种频率比较高的波特率,在中断里面有过多的判断,不会引起数据丢失吗?
   我测器来好像会有这个问题,我记得几年前用freescale的M4的芯片时,当时用的是120M的主频,我在串口接收中断里面多加了几个判断,就导致接收数据会丢,后来改成9600才解决。
   现在用的单片机是EFM32的,使用的片内28M RC振荡器,测试下来问题很大:   我在串口中断里面用数组接收能完全收到:   
void LEUART0_IRQHandler(void)
{        
    rx_buff[rx_idx++] = LEUART_Rx(LEUART0);
    if(USART_IEN_TXC == (LEUART_IntGet(LEUART0) & USART_IEN_TXC))    /*当前是发送完成中断*/
    {
        prvvUARTTxReadyISR();
    }
        else if(USART_IEN_RXDATAV == (LEUART_IntGet(LEUART0) & USART_IEN_RXDATAV))
        {
            prvvUARTRxISR();
        }
}
但是如果放在prvvUARTRxISR里面就接收不完全了,我发送才5个字节,仿真的时候看那个全局数组,有的时候接收3个字节,有的时候接收2个字节。
static void prvvUARTRxISR( void )
{
    rx_buff[rx_idx++] = LEUART_Rx(LEUART0);
    pxMBFrameCBByteReceived(  );
}


void LEUART0_IRQHandler(void)
{        
    if(USART_IEN_TXC == (LEUART_IntGet(LEUART0) & USART_IEN_TXC))    /*当前是发送完成中断*/
    {
        prvvUARTTxReadyISR();
    }
        else if(USART_IEN_RXDATAV == (LEUART_IntGet(LEUART0) & USART_IEN_RXDATAV))
        {
            prvvUARTRxISR();
        }
}
2.我看modbus在初始化时钟的时候,大于19200的时候,超时时间设置的是1800us,也就是1.8ms,  这个可以理解,毕竟115200的波特率1ms能接收到11个字节,也就是说接收一个字节的时间0.1ms都不到。
   再来看看9600的波特率,设置的时间是4ms,9600的波特率接收一个字节的时间差不多是1ms,4ms的时间应该也没问题,但还是接上面的话题,如果主频慢的话,4ms超时不一定够吧?

3.难道主频低的单片机玩不了modbus吗?大家是怎么玩modbus的呢,期待大家的建议。   


使用特权

评论回复

相关帖子

沙发
叶春勇| | 2020-6-30 22:56 | 只看该作者
115200数据就丢失,有点夸张

使用特权

评论回复
评论
huzhiyang 2020-7-2 20:51 回复TA
就是因为波特率高了,如果在中断里面过多的代码和条件判断,就会来不及从uart的buff取数据而导致被后面来的数据覆盖了 
板凳
youhm| | 2020-7-1 11:10 | 只看该作者
modbus处理不要放在中断里,一帧数据接收完成后再处理。

使用特权

评论回复
评论
huzhiyang 2020-7-2 20:49 回复TA
modbus的架构就是放在中断里面处理的啊 
地板
oufuqiang| | 2020-7-2 15:24 | 只看该作者
不知道是什么结构的程序。51单片机主频11.0592MHz跑230400bps连续不断的数据都不丢。

使用特权

评论回复
5
huzhiyang|  楼主 | 2020-7-2 20:50 | 只看该作者
oufuqiang 发表于 2020-7-2 15:24
不知道是什么结构的程序。51单片机主频11.0592MHz跑230400bps连续不断的数据都不丢。 ...

是要看怎么处理数据吧,如果做个缓冲区,中断程序里面只是接收数据,然后把数据放到缓冲区里面,其它线程再来处理这些数据,那肯定是没问题的。

使用特权

评论回复
6
〽️〽️〽️| | 2020-7-3 21:09 | 只看该作者
DMA方式,不会丢

使用特权

评论回复
7
dalarang| | 2020-7-3 21:26 | 只看该作者
115200波特率,算下来86us左右收到一个字节。
即便是28M的时钟,86us也有2000多个时钟周期,若干个判断无论无何也无法占满这2000多个时钟周期的。
从别的地方找找原因吧,是不是定时器的T3.5时间算错了之类的。

使用特权

评论回复
8
huzhiyang|  楼主 | 2020-7-5 20:58 | 只看该作者
dalarang 发表于 2020-7-3 21:26
115200波特率,算下来86us左右收到一个字节。
即便是28M的时钟,86us也有2000多个时钟周期,若干个判断无论 ...

定时器看起来也没啥问题啊:
BOOL xMBPortTimersInit( USHORT usTim1Timerout50us )
{
    timer2_init(usTim1Timerout50us);
    return FALSE;
}


inline void vMBPortTimersEnable(  )
{        
        NVIC_EnableIRQ(TIMER2_IRQn);
        TIMER_Enable(TIMER2, TRUE);   
    /* Enable the timer with the timeout passed to xMBPortTimersInit( ) */
}

inline void vMBPortTimersDisable(  )
{   
        TIMER_Enable(TIMER2, false);   
        NVIC_DisableIRQ(TIMER2_IRQn);       
    TIMER_CounterSet(TIMER2,0);
    /* Disable any pending timers. */
}

手上没示波器,感觉定时器也不好仿真,我测试了下定时器,将modbus相关的处理函数全部屏蔽了,定时的是10ms一次中断,设置的计数上限制是35000,
然后进到中断后将寄存器的count存入数组,不过记下来的count不是35000,或许是定时器的值在进到中断后又从0开始计数了吧,然后到我写入数组的时候已经记了一些数吧。
个人分析下来,现在的问题就是,当串口收到数据后,定时器开始工作,但是似乎定时器很快就进入到中断,然后认为串口没有后续数据,修改了状态机,导致串口收到的数据不全。
现在不知道是定时器的问题,还是串口中断里面处理逻辑太多,导致串口无法及时取出uart数据寄存器的值,看来真的需要示波器看看了。

使用特权

评论回复
9
huzhiyang|  楼主 | 2020-7-12 16:23 | 只看该作者
利用闲暇时间断断续续的调了一周多,终于调通了,这里遇到几个问题:
1.定时器的问题,先是在串口中断的地方加了个GPIO,然后用示波器查看GPIO的脉宽,确定UART接收一个字节大约1ms,没问题,然后查看了定时器,发现之前测试的定时器定时也没问题,但是调用协议栈初始化的定时器定时就不对,后来发现协议栈里面定义的定时器中断里面没有清中断标志位,清掉之后就好了。
2.串口接收中断的问题,在跟踪协议栈的时候,数据接收没问题,但是数据发不出来,然后分析协议栈,发现使能串口发送中断的时候,进不到发送状态机里,然后看到这个状态机是在中断里面触发的,而我设置的串口中断是发送完成中断,使能当然进不去,改成串口发送buff空中断就可以进发送中断了。
3.改成串口发送中断后,仿真的时候发现接收到数据的时候也会进到发送为空的处理函数,看了下中断状态寄存器,串口中断接收到数据的时候,发送buff为空的标志位是1,这个也好理解,这个时候发送buff确实为空嘛,调换了中断里面接收和发送的判断条件,modbus就可以返回值了。

使用特权

评论回复
10
一路向北lm| | 2020-7-13 08:18 | 只看该作者
用RT-Thread 一键配置FreeModbus 主站从站

使用特权

评论回复
11
zeshoufx| | 2020-7-13 08:32 | 只看该作者
解决了吗

使用特权

评论回复
12
huzhiyang|  楼主 | 2020-7-25 15:34 | 只看该作者

解决了,上面有我调试的总结

使用特权

评论回复
13
huzhiyang|  楼主 | 2020-7-25 15:35 | 只看该作者
一路向北lm 发表于 2020-7-13 08:18
用RT-Thread 一键配置FreeModbus 主站从站

我是用的EFM32的芯片,裸机。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

32

主题

190

帖子

2

粉丝