穿西装的强子 发表于 2025-6-20 23:06

【灵动微电子MM32F0121测评】7、手搓modbus协议从机(二)

本帖最后由 穿西装的强子 于 2025-6-20 23:11 编辑

根据上一个帖子已经搭建好了modbus传输的协议,只需添加0x06和0x10寄存器功能即可
以下是0x06寄存器,根据协议,如果协议正常,则返回值与发送值一样,因此使用memcpy将接收的usart数据复制到tx数据内
再将接收数据的寄存器值存在Modbus_data这个变量里做存储使用

void ModBus_Register_SingleWrite(USART_RxTx_TypeDef *usart,USART_RxTx_TypeDef *tx)
{
      uint16_t register_addr = (usart->Buffer<<8)|(usart->Buffer);// 寄存器地址
      if( register_addr>= 128)
      {
               
      } else {
                tx->Length = usart->Length;
                memcpy(&tx->Buffer,&usart->Buffer,usart->Length);
                modbus_data = (usart->Buffer<<8)|(usart->Buffer);
                tx->CompleteFlag = 1;
                USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
      }
}根据0x10寄存器,是写多个数据,按照协议,是有数据长度和寄存器个数的参数,理论上是按着寄存器数据连续的写入,而不是跳着写入这些数据,因此这些数据可以根据地址内容进行填充,正常接收的话,返回寄存器地址和寄存器个数即可。



根据以上协议,数据总长度= 寄存器个数*2+固定字节9,因此小于该长度的数据都属于异常数据。
由于数据类型是16位的,因此将接收的8位数据转换成16位数据进行存储,存储的数据可以根据自己的使用方法进行调用即可。
void ModBus_Register_MultiWrite(USART_RxTx_TypeDef *usart,USART_RxTx_TypeDef *tx)
{
      uint16_t register_addr = (usart->Buffer<<8)|(usart->Buffer);// 寄存器地址
      uint16_t register_len = (usart->Buffer<<8)|(usart->Buffer);// 寄存器数据长度
      if( usart->Length < (9+register_len*2)){
               
      } else {
                tx->Length = 0;
                tx->Buffer = DEVICES_ID;
                tx->Buffer = 16;
                tx->Buffer = usart->Buffer;
                tx->Buffer = usart->Buffer;
                tx->Buffer = usart->Buffer;
                tx->Buffer = usart->Buffer;
                uint16_t crc = calculate_crc_direct(tx->Buffer,tx->Length);
                tx->Buffer = crc;
                tx->Buffer = crc>>8;
               
                for( uint16_t i = 0; i < register_len;i++)
                {
                        modbus_data = (usart->Buffer[(i)*2+7]<<8)|(usart->Buffer[(i)*2+1+7]);
                }
                tx->CompleteFlag = 1;
                USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
               
      }
      
}最后,视频演示,该视频是在使用KEIL5进行debug阶段验证,可以看到左侧工程文件是MM32F0120的芯片

右侧是modbus寄存器数据,可以看到视频在使用modbus poll软件进行通信时,选择了16(0x10)寄存器,进行多数据写入功能,每次修改寄存器值时,keil的右侧debug界面modbus数据都会变化。
录屏没录好,只录了modbuspoll的,没把keil录进去

https://www.bilibili.com/video/BV1gPKPzZE4U/

AdaMaYun 发表于 2025-7-31 17:53

modbus协议从机值得推荐
页: [1]
查看完整版本: 【灵动微电子MM32F0121测评】7、手搓modbus协议从机(二)