您现在的位置是:首页 >技术交流 >MODBUS通讯程序设计流程图网站首页技术交流

MODBUS通讯程序设计流程图

LaoZhangGong123 2024-06-17 10:13:52
简介MODBUS通讯程序设计流程图

MODBUS通讯一般来说是基于RS485电平的通讯,RS485是半双工,很多单片机工程师做的通讯不是稳定,主要原因是流程没有掌控好。

我以前也犯过和他们一样错误,觉得很容易。在QQ群里,有位老工程师和大家一样犯了同样的毛病。曾经去一家公司面试,他们也遇到过类似的问题。他们咨询我用是什么485芯片,想知道一些信息。他们以为是自己的芯片问题,其实就是程序流程不正确。当然,这次面试肯定是泡汤,他们的动机不是招聘,而是想找答案。我告诉了芯片的型号,但具体流程设计,是口述的。面试时,当有人问解决方案时,就要注意留个心眼。

看似简单,那是因为你没有用到项目上去,只有做过的人才知道其中的奥妙。一次通讯正确,那不叫稳定,要能工作一年不出问题,才能说自己做好了。

1、变量定义如下:

#define RS485_TX_Overtime_RefValue    40   //发送完成最大等待时间为80ms,流程图直接用40
#define RS485_TX_Buffer_Size               17
u8 TX[RS485_TX_Buffer_Size];
u8 TXindex;//TX[]的发送下标值;
u8 Tmax;//TX[]的装载数据完成后的最大下标值
u8 TXstep;
u8 TXcnt;//RS485发送无从机超时计数器

#define Rmax               125
u8 RX[Rmax]; //RS485接收缓冲区数组
u8 RXindex;          //RX[]的装载索引值
u8 RXcnt;              //RS485接收时间计数器
u8 RXstep;

union RS485_CRC16_DATA_TYPE
{ uint8_t  b[2];
  uint16_t  d; //b[1]和d的高8位值相等;b[0]和d的低8位值相等;
};
union RS485_CRC16_DATA_TYPE  RS485_serial_crc;

uint8_t  High8Bit,Low8Bit;//用来保存计算到的CRC

2、流程图如下:

 

 照着上面的流程图设计,应该问题不大。

3、CRC循环冗长检测

//函数功能:CRC循环冗长检测
u16 FrequencyConverter_Crc16(u8 *data,u8 len)
{
    u16 ccitt16 = 0xA001;      //多项式0xA001
    u16 crc = 0xFFFF;
    int i;

    for(;len>0;len--)
  {
        crc^=*data;                  //异或
        for(i=0;i<8;i++)
        {
            if(crc & 0x0001)    //最低位为1,减去除数
            {
                crc>>=1;            //将最低位的1移出,剩下的数与0xA001异或
                crc^=ccitt16;
            }
            else                          //最高位为0,不需要减去除数
            {
                crc>>=1;                 //直接移位
            }
        }
        data++;
    }
    return crc;
}

4、装载举例

          TX[0] = 0x01;               //装载变频器设备地址
          TX[1] = 0x03;               //装载MODBUS读命令
          TX[2] = RegAdress>>8;       //装载寄存器地址的高8位值
          TX[3] = RegAdress&0xFF;     //装载寄存器地址的低8位值
          TX[4] = DataOrNumber1>>8;   //装载读取数据长度的高8位值
          TX[5] = DataOrNumber1&0xFF; //装载读取数据长度的低8位值
          crc16 = FrequencyConverter_Crc16(&TX[0],6);    //计算CRC16的值
          TX[6] = (u8)(crc16&0x00FF); //装载CRC16的低8位值
          TX[7] = (u8)(crc16>>8);     //装载CRC16的高8位值
          Tmax = 7;//设置TX[]中的最大装载索引值

5、结论

本流程图,在实际案例中使用过,很不错。

欢迎交流,互相进步。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。