MODBUS RTU协议的稳定性 点击:2256 | 回复:3



我爱猪头

    
  • 精华:0帖
  • 求助:0帖
  • 帖子:3帖 | 15回
  • 年度积分:0
  • 历史总积分:30
  • 注册:2004年4月06日
发表于:2004-05-09 15:02:00
楼主
最近用c编写可一套控制程序,用MODBUS RTU协议进行通讯,上位机通过pc机的串口(linux下)用485-232转换芯片连接到WAGO750-315模块的从站。程序用c编写,主要方式如下 rtu_set_coil (1,wr_buf,0,2,1); write ( fd,wr_buf,10 ); read (fd, rd_buf,7); 在连续不停地读写模块一段时间后会出现死机,程序不读写了。关掉shell,重新打开一个shell,再用gcc编译和运行程序,又能继续读写。 这是硬件问题还是程序问题呢? 请指教,谢谢!



如火

  • 精华:172帖
  • 求助:0帖
  • 帖子:803帖 | 5249回
  • 年度积分:0
  • 历史总积分:0
  • 注册:1900年1月01日
发表于:2005-12-09 13:47:00
1楼
您可以编写一个超时判断,一旦发现超时,就断开,重新连接开始访问,当然这只是您的软件编写没有问题的情况下防止设备有问题采取的方法。

叶帆

  • 精华:1帖
  • 求助:0帖
  • 帖子:18帖 | 88回
  • 年度积分:0
  • 历史总积分:239
  • 注册:2003年9月03日
发表于:2005-12-12 23:48:00
2楼
设置好读写的频率,我想是不是读写太快,读写缓冲区溢出了
这是我写的嵌入式系统的一段 Modbus Rtu读写程序,你可以参考一下

//*************************************************************************
//**函 数 名:RtuData
//**输    入:Addr                 - 设备地址(1~247)
//**        :Mode                 - 功能模式
//**        :DataStart            - 数据区起始地址
//**        :DataArray()          - 读写数据缓存区
//**        :DataNum              - 数据个数
//**输    出:操作的信息: 0 - 正确 1-接收的数据长度不对  2 - 接收的数据错误  3- 数据长度错
//**功能描述:以RTU模式读写数据
//**全局变量:
//**调用模块:
//**作    者:叶帆
//**日    期:2005-2-2
//**修 改 人:
//**日    期:
//**版    本:V1.0
//*************************************************************************
WORD RtuData(BYTE Addr, BYTE Mode, WORD DataStart, BYTE *DataArray, WORD DataNum)
{
    BYTE bytSendArray[255];              //发送数据缓冲区
    BYTE bytReceiveArray[255];           //接收数据缓冲区
    UINT intCRC16;
    int i;
    int intOffSet;
    int intSendNum;
    int intGetDataLen;                  //实际接收数据的帧长度

    if (DataNum>64 || DataNum<1) return 3;
  
    bytSendArray[0] = Addr;                       //设备地址
    bytSendArray[1] = Mode;                       //功能模式
    bytSendArray[2] = DataStart / 256;            //机车地址高位
    bytSendArray[3] = DataStart & 0xFF;           //机车地址低位

    bytSendArray[4] = DataNum / 256;              //数据个数高位
    bytSendArray[5] = DataNum & 0xFF;             //数据个数低位

    if (Mode==WriteData)
    {
    bytSendArray[6] = DataNum * 2;            //数据的字节个数
    for(i = 1;i<DataNum * 2+1;i++)
        bytSendArray[6+i] = DataArray[i-1];

    intOffSet = 7 + DataNum * 2;
    }
    else
    {
    intOffSet = 6;
    }

    intCRC16=GetCheckCode(bytSendArray,intOffSet);
    bytSendArray[intOffSet] = intCRC16 & 0xFF;                    //CRC校验低位
    bytSendArray[intOffSet + 1] = (intCRC16>>8) &0xff;            //CRC校验高位
    
    intSendNum=intOffSet+2;
    
    NB_Delay(3);
    
    if (Mode==WriteData)  intGetDataLen = 8;
    else                  intGetDataLen = 5 + DataNum * 2;
    
    //发送和接收数据
    if (GZ_Command(intSendNum,bytSendArray,intGetDataLen,bytReceiveArray)!=0)
    {
    return 1;             //数据接收错误
    }

    //信息处理
    intCRC16=GetCheckCode(bytReceiveArray,intGetDataLen-2);

    //CRC16校验检验
    if (bytReceiveArray[intGetDataLen - 2]==(intCRC16 & 0xFF) && bytReceiveArray[intGetDataLen - 1]==((intCRC16>>8) &0xff))
    {
    //帧数据是否正确
    if (bytReceiveArray[0] == bytSendArray[0] && bytReceiveArray[1] == bytSendArray[1])
    {
       if( Mode==WriteData)
       {
          //
       }
       else
       {
          for(i=0;i<bytReceiveArray[2];i++)
          DataArray[i] = bytReceiveArray[3 + i];
       }
       return 0;
    }
    }
   return 2;
}


王晟磊

  • 精华:12帖
  • 求助:0帖
  • 帖子:70帖 | 687回
  • 年度积分:0
  • 历史总积分:1173
  • 注册:2004年2月11日
发表于:2006-02-07 18:09:00
3楼
晕倒,不死才怪,一没帧超时处理,二没出错处理.
接收开始后起动一个计时器,超时退出延时清空接收缓存并重发请求.

热门招聘
相关主题

官方公众号

智造工程师