小坤 发表于 2024-4-15 09:16:36

Modbus RTU 从机处理机制 跟风 赚点积分

本帖最后由 小坤 于 2024-4-15 09:28 编辑

1. 首先就是基础的串口配置就不说 。
2. 接收超时机制根据实际的波特兰进行配置,3.5个字节~4个字节都是可以的。串口波特率可以修改的话,接收超时时间可以做成自动计算或者查表类。
3.接收解析:
void Modebus_PC_task(void)
{
    if(UART3.Rx_OK)               //接收完成
    {
                  //关闭接收
      Modbus.CRC_data = crc16( UART3.Rx_buff, (UART3.Rx_counter - 2));            //计算CRC校验值
      Modbus.CRC_H = Modbus.CRC_data >> 8;
      Modbus.CRC_L = Modbus.CRC_data & 0xFF;                                    //拆分高低位
      if((UART3.Rx_buff == Modbus.CRC_H) && (UART3.Rx_buff == Modbus.CRC_L))//判断CRC校验是否正确
      {
            Modbus.address = UART3.Rx_buff;                                    //地址
            if((Modbus.address == Sys_addr)||(Modbus.address == Broad_addr))      //判断地址
            {
                Modbus.CMD = UART3.Rx_buff;                                    //功能码
                Modbus.Reg_addr =UART3.Rx_buff*256+UART3.Rx_buff;         //寄存器地址
                switch(Modbus.CMD )
                {
                     case 0x03 : PC_ReadReg();            break;                   //读寄存器
                     case 0x06:
                     case 0x10:PC_WriteReg();             break;                   //写寄存器
                  //default:Send_Err(Err_CMD);      break;                         //异常功能码
                }
            }
      }
       // Delay_Ms(1);
      memset(&UART3.Rx_buff, 0, sizeof(UART3.Rx_buff));                           //内存清零
      UART3.Rx_OK = 0;                                                            //状态赋值
      UART3.Rx_counter = 0;                                                         //清零
            // 打开接收
    }
}

4. 读寄存器
voidPC_ReadReg(void)
{
    Buff_u16_u8 Buff;
    uint8_t buff_n;
    uint16_t i=0;
    uint8_t n=0;

    Modbus.Reg_Len = UART3.Rx_buff*256+UART3.Rx_buff;             //寄存器长度
    if((Modbus.Reg_Len<1)||(Modbus.Reg_Len>125))    return;             //寄存器个数范围   1<=寄存器数量<=125
    if(Modbus.Reg_addr+Modbus.Reg_Len >Reg_len)   return;             //起始地址+寄存器长度<=总寄存器数量

    buff_n = Sys_addr ;                            //地址
    buff_n = Modbus.CMD;                           //功能码
    buff_n = Modbus.Reg_Len*2;                     //数据长度
    for(i=Modbus.Reg_addr; i<(Modbus.Reg_addr+Modbus.Reg_Len); i++ )
    {
      Buff.Dat = Modbus.Reg;
      buff_n = Buff.Byte;
      buff_n = Buff.Byte;                  //数据
    }
    Modbus.CRC_data = crc16( buff_n, n);
    buff_n = Modbus.CRC_data>>8;
    buff_n = Modbus.CRC_data&0xFF;               //校验
    UART3_Send_n(buff_n, n);                            //中断发送
}


5.写寄存器
void PC_WriteReg()
{
    Buff_u16_u8 Buff;
    uint8_t buff_n;
    uint16_t i=0;
    uint8_t n=0;

    if( Modbus.CMD == 0X06 )                         //写单个寄存器
    {
      if( Modbus.Reg_addr <=Reg_len)            //判断地址是否合规
      {
            Buff.Byte = UART3.Rx_buff;
            Buff.Byte = UART3.Rx_buff;         //获取数据
            Modbus.Reg = Buff.Dat;          //寄存器赋值
      }
    }

    if( Modbus.CMD == 0X10 )      //写多个寄存器
    {
      Modbus.Reg_Len = UART3.Rx_buff*256+UART3.Rx_buff;
      if((Modbus.Reg_Len<1)||(Modbus.Reg_Len>123))    return;         //寄存器个数范围   1<=寄存器数量<=123
      if(Modbus.Reg_Len*2!=UART3.Rx_buff)   return;                //数据字节数据范围Modbus.Reg_Len*2
      if(Modbus.Reg_addr+Modbus.Reg_Len >Reg_len)   return;      //起始地址+寄存器长度<=总寄存器数量

      for(i=Modbus.Reg_addr; i<(Modbus.Reg_addr+Modbus.Reg_Len); i++ )
      {
                Buff.Byte = UART3.Rx_buff;
                n++;
                Buff.Byte = UART3.Rx_buff;;
                n++;
                Modbus.Reg = Buff.Dat;            //寄存器赋值
      }
    }

    for(n=0; n<6; n++)
    {
      buff_n = UART3.Rx_buff;       //返回值
    }
    Modbus.CRC_data = crc16(buff_n, n);
    buff_n = Modbus.CRC_data>>8;
    buff_n = Modbus.CRC_data&0xFF;   //校验
    UART3_Send_n(buff_n, n);                //发送
}

以上就是从机的读写机制;



结构体声明
/****************   Modbus定义 **************************************/
typedef struct
{
    volatileuint8_t   address;                //地址
    volatileuint8_t    CMD;                  //功能码
    volatileuint16_t   Reg_addr;               //寄存器地址
    volatileuint16_t   Reg_Len;                //寄存器长度
//   volatileuint16_t   Read_Reg;      //读寄存器数组
//   volatileuint16_t   Write_Reg;   //写寄存器数组
    volatileuint16_t   Reg;   //写寄存器数组

    volatileuint16_t   CRC_data;               //CRC校验
    volatileuint8_t    CRC_H;                  //CRC H
    volatileuint8_t    CRC_L;                  //CRC L
    volatileuint16_t   Err_code;               //异常码
}Modbus_conf;

数据 共用体
/****************   共用体 *****************************/
typedef union
{
      unsigned int   Dat;
      unsigned charByte;
}Buff_u16_u8;

寄存器枚举
enum MODBUS_REG
{
    Start_Reg = 0,
    Sys_addr_Reg,   //设备地址
/**************** 1号***************************/
    Status_1_Reg,   //状态
    Power_1_Reg,      //功率大小
    Mode_1_Reg,       //模式
    Time_1_Reg,       //时间
    Temp_1_Reg,       //温度
/**************** 2号***************************/
    Status_2_Reg,   //状态
    Power_2_Reg,      //功率大小
    Mode_2_Reg,       //模式
    Time_2_Reg,       //时间
    Temp_2_Reg,       //温度
    Reg_len         //寄存器长度
};

可以参考的串口配置
typedef struct
{
    uint8_t state;               //状态
    uint8_t RXDEnable;            //接收使能
    uint8_t TXDEnable;            //接收使能
    uint8_t TX_over_flag;         //发送完成标识
    uint8_t rx_buffer_overflow;   //接收溢出:
    char rx_over_time;            //接收溢出时间
    uint8_t rx_err;               //校收出错
    uint8_t Rx_OK;                  //校收完成
    //接收
    uint8_t Rx_buff;//接收缓冲区
    uint8_t Rx_wr_index;                      //接收写指针
    uint8_t Rx_rd_index;                      //接收读指针
    uint8_t Rx_counter;                     //接收计数
    //发送
    uint8_t Tx_buff; //发送缓冲区
    uint8_t Tx_Length;                        //需发送的数据长度
    uint8_t Tx_counter;                     //发送计数
}Typedef_COMx;

谢谢,勿喷,挣积分{:smile:}


_奶咖君_ 发表于 2024-4-15 09:21:16

RTU?

小坤 发表于 2024-4-15 09:28:48

_奶咖君_ 发表于 2024-4-15 09:21
RTU?

是的,写错了,修正

小坤 发表于 2024-4-21 13:05:13

୧(๑•̀◡•́๑)૭

jwd 发表于 2024-4-21 14:34:10

{:4_250:}

110 发表于 2024-5-15 17:10:20

支持楼主,学习了!谢谢1

HJJDSTC 发表于 2024-6-11 11:18:47

感谢分享
页: [1]
查看完整版本: Modbus RTU 从机处理机制 跟风 赚点积分