搜索
bottom↓
回复: 22

FreeModbus移植用于485的错误

[复制链接]

出0入0汤圆

发表于 2016-9-27 21:18:58 | 显示全部楼层 |阅读模式
感谢xukai871105的帖子“FreeModbus移植 经验分享”,使我们在编写STM32片子的MODBUS时有很好的参考。

特别申明,欢迎进行技术讨论,请喜欢讨论非技术问题的不要回复,尤其是那位n先生不要回复。谢谢!

在使用485通信时,在发送回复前应该首先把驱动芯片的控制端转换到发送状态,然后再发送数据。例如使用MAX485,高电平为发送模式。

在mbrtu.c文件里的eMBRTUSend函数有这么一段:

启动第一次发送,这样才可以进入发送完成中断,
   xMBPortSerialPutByte( ( char )*pucSndBufferCur );
   pucSndBufferCur++;
   usSndBufferCount--;
   vMBPortSerialEnable( FALSE, TRUE ); //使能发送中断,禁止接收中断
请问,在发送之前把驱动芯片的控制端转换到发送状态在哪里呢?
没有!
实际上驱动芯片的控制端转换是在vMBPortSerialEnable( FALSE, TRUE ); 函数里面。原程序是把顺序搞反了,结果就是发送的第一个字节经常会错误。这个问题在232通信时发现不了,在485通信时也不是每次都错。因此对于不认真测试的人会忽略这个错误,但如果在相关通信程序里不做通信异常检测和重发的话,将对产品造成重大隐患。

结论:上述程序应该修改为:
   vMBPortSerialEnable( FALSE, TRUE ); //使能发送中断,禁止接收中断 -- 实际上里面还包含驱动芯片的控制端转换。
   xMBPortSerialPutByte( ( char )*pucSndBufferCur );
   pucSndBufferCur++;
   usSndBufferCount--;

出0入0汤圆

 楼主| 发表于 2016-10-22 14:58:16 | 显示全部楼层
增加一个发现:
在函数eMBException  eMBFuncReadHoldingRegister( unsigned char * pucFrame, unsigned short * usLen ) 里面,

获取读取的寄存器个数的代码有误,源代码如下:
usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF] << 8 );
usRegCount = (USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] );
应该是:
usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF] << 8 );
usRegCount |= (USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] );
或者:
usRegCount = ( USHORT )( ( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF] << 8 ) | (  pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] ) );

出0入0汤圆

发表于 2016-10-22 19:08:05 | 显示全部楼层
楼主对技术的态度太让你佩服了,正好在移植freemodbus,感谢楼主

出0入198汤圆

发表于 2016-10-22 22:33:29 | 显示全部楼层
wangzugong 发表于 2016-10-22 14:58
增加一个发现:
在函数eMBException  eMBFuncReadHoldingRegister( unsigned char * pucFrame, unsigned sh ...


2 楼确实是个官方的 Bug,我去年也发现了,并在自己重构的的 FreeModbus 主+从机 项目( https://github.com/armink/FreeModbus_Slave-Master-RTT-STM32 )中修复过了。

出0入0汤圆

发表于 2016-10-23 09:22:00 | 显示全部楼层
楼主发现了FreeModbus 485 的BUG,大家可以少走弯路了。

出0入0汤圆

 楼主| 发表于 2016-11-28 21:08:56 | 显示全部楼层
sunnydragon 发表于 2016-10-22 22:33
2 楼确实是个官方的 Bug,我去年也发现了,并在自己重构的的 FreeModbus 主+从机 项目( https://github. ...

好东西,但你那个网站很难打开呀。

出0入198汤圆

发表于 2016-11-29 07:45:58 | 显示全部楼层
wangzugong 发表于 2016-11-28 21:08
好东西,但你那个网站很难打开呀。

我在国内的开源中国也有同步,你可以试试:https://git.oschina.net/Armink/FreeModbus_Slave-Master-RTT-STM32

出0入0汤圆

发表于 2016-11-29 07:56:50 | 显示全部楼层
确实是BUG,但是因为MODBUS读字的最大长度其实是小于一个字节的,所以没有影响
没影响的BUG,最难发现

出0入0汤圆

发表于 2016-11-29 10:07:42 | 显示全部楼层
厉害呀! 这么小的问题 都能发现

出0入0汤圆

发表于 2016-11-29 10:08:06 | 显示全部楼层
sunnydragon 发表于 2016-10-22 22:33
2 楼确实是个官方的 Bug,我去年也发现了,并在自己重构的的 FreeModbus 主+从机 项目( https://github. ...

你才是真正的大神!
非常感谢你的代码!

出0入8汤圆

发表于 2016-11-29 11:35:13 | 显示全部楼层
厉害啊,留着学习下啊~~

出0入0汤圆

发表于 2016-11-29 19:58:08 | 显示全部楼层
都是大神啊,mark!

出0入0汤圆

发表于 2016-11-30 07:54:29 | 显示全部楼层
freeModbus只能用于一个串口,要二个以上,就要重新架构了。

出0入0汤圆

 楼主| 发表于 2016-12-2 11:10:17 | 显示全部楼层
sdsdc 发表于 2016-11-30 07:54
freeModbus只能用于一个串口,要二个以上,就要重新架构了。

就用目前这个从站软件,稍微改动一下,我用3个串口通信,没问题。只是最好是控制这3个口的主站不要同时发请求。

出0入0汤圆

发表于 2016-12-13 13:37:24 | 显示全部楼层
MARK FreeModbus 485方向控制。

原来使用485的时候发现了问题。也搞不明白如何修改。

后来加了一个三极管改成了RXD自动控制收发的。

不过看了你的帖子以后,豁然开朗!

谢谢!

感觉还是使用自动收发比较好!

出0入0汤圆

发表于 2018-2-5 21:42:48 | 显示全部楼层
阿豪博士 发表于 2016-12-13 13:37
MARK FreeModbus 485方向控制。

原来使用485的时候发现了问题。也搞不明白如何修改。

自动收发控制硬件如何实现?

出0入0汤圆

发表于 2018-5-22 22:19:34 | 显示全部楼层
这个细节需要mark一下,等到正式开始移植的时候再来仔细看看

出0入0汤圆

发表于 2018-7-10 08:00:25 | 显示全部楼层
打开程序没有楼主所说的情况,怎么回事呢?
eMBErrorCode
eMBRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength )
{
    eMBErrorCode    eStatus = MB_ENOERR;
    USHORT          usCRC16;

    ENTER_CRITICAL_SECTION(  );

    /* Check if the receiver is still in idle state. If not we where to
     * slow with processing the received frame and the master sent another
     * frame on the network. We have to abort sending the frame.
     */
    if( eRcvState == STATE_RX_IDLE )
    {
        /* First byte before the Modbus-PDU is the slave address. */
        pucSndBufferCur = ( UCHAR * ) pucFrame - 1;
        usSndBufferCount = 1;

        /* Now copy the Modbus-PDU into the Modbus-Serial-Line-PDU. */
        pucSndBufferCur[MB_SER_PDU_ADDR_OFF] = ucSlaveAddress;
        usSndBufferCount += usLength;

        /* Calculate CRC16 checksum for Modbus-Serial-Line-PDU. */
        usCRC16 = usMBCRC16( ( UCHAR * ) pucSndBufferCur, usSndBufferCount );
        ucRTUBuf[usSndBufferCount++] = ( UCHAR )( usCRC16 & 0xFF );
        ucRTUBuf[usSndBufferCount++] = ( UCHAR )( usCRC16 >> 8 );

        /* Activate the transmitter. */
        eSndState = STATE_TX_XMIT;
        vMBPortSerialEnable( FALSE, TRUE );
    }
    else
    {
        eStatus = MB_EIO;
    }
    EXIT_CRITICAL_SECTION(  );
    return eStatus;
}

出0入0汤圆

发表于 2018-7-10 16:26:01 | 显示全部楼层
hzy789 发表于 2018-7-10 08:00
打开程序没有楼主所说的情况,怎么回事呢?
eMBErrorCode
eMBRTUSend( UCHAR ucSlaveAddress, const UCHAR  ...

不再这里   在其他地方

出0入0汤圆

发表于 2018-7-17 12:58:19 | 显示全部楼层
vjcmain 发表于 2018-2-5 21:42
自动收发控制硬件如何实现?

不只是一个三极管这么简单,应该是组成了一个可重触发的单稳态电路,我猜测的

出0入0汤圆

发表于 2018-7-20 09:29:45 | 显示全部楼层
freemodbus,很多临界区代码,中断里处理业务逻辑,我个人认为不太好

出0入0汤圆

发表于 2018-7-20 10:34:22 | 显示全部楼层
本帖最后由 myxiaonia 于 2018-7-20 13:29 编辑

我最近也在看freemodbus,有什么bug我也在这里报告了

freemodbus-v1.5.0\modbus\functions\mbfuncdisc.c  此文件中46行 #if MB_FUNC_READ_COILS_ENABLED > 0 应该改为 #if MB_FUNC_READ_DISCRETE_INPUTS_ENABLED > 0
freemodbus-v1.5.0\modbus\rtu\mbrtu.c  此文件中134行后应该增加 eSndState = STATE_TX_IDLE; 这样结构更严谨。

出0入0汤圆

发表于 2019-6-19 12:46:44 | 显示全部楼层
这个问题理论上是这样,但是实际测试的时候——
如果将vMBPortSerialEnable() 放到 xMBPortSerialPutByte() 前面,会导致从机重新上电后发送的第一个数据包的第一个字节丢失,从第二个数据包后就正常了。如下数据, Modbus Poll 的第一轮接收的第一个字节“0x01”丢失。
如果将vMBPortSerialEnable() 放到 xMBPortSerialPutByte() 后面,测试过程中不会出现上述问题。当然长时间工作丢包问题不在讨论范围。
贴上Modbus Poll 数据:
000001-Tx:01 03 00 46 00 02 25 DE
000002-Rx:03 04 00 00 00 00 FA 33
000003-Tx:01 03 00 46 00 02 25 DE
000004-Rx:01 03 04 00 00 00 00 FA 33
000005-Tx:01 03 00 46 00 02 25 DE
000006-Rx:01 03 04 00 00 00 00 FA 33
ps:必须是从机重新上电后重现该问题。

问题摸索中……
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-20 06:31

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表