打印
[MM32硬件]

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

[复制链接]
76|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 穿西装的强子 于 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[2]<<8)|(usart->Buffer[3]);// 寄存器地址
        if( register_addr  >= 128)
        {
               
        } else {
                tx->Length = usart->Length;
                memcpy(&tx->Buffer[0],&usart->Buffer[0],usart->Length);
                modbus_data[register_addr] = (usart->Buffer[4]<<8)|(usart->Buffer[5]);
                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[2]<<8)|(usart->Buffer[3]);// 寄存器地址
        uint16_t register_len = (usart->Buffer[4]<<8)|(usart->Buffer[5]);// 寄存器数据长度
        if( usart->Length < (9+register_len*2)){
               
        } else {
                tx->Length = 0;
                tx->Buffer[tx->Length++] = DEVICES_ID;
                tx->Buffer[tx->Length++] = 16;
                tx->Buffer[tx->Length++] = usart->Buffer[2];
                tx->Buffer[tx->Length++] = usart->Buffer[3];
                tx->Buffer[tx->Length++] = usart->Buffer[4];
                tx->Buffer[tx->Length++] = usart->Buffer[5];
                uint16_t crc = calculate_crc_direct(tx->Buffer,tx->Length);
                tx->Buffer[tx->Length++] = crc;
                tx->Buffer[tx->Length++] = crc>>8;
               
                for( uint16_t i = 0; i < register_len;i++)
                {
                        modbus_data[register_addr+i] = (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录进去



使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

54

主题

243

帖子

3

粉丝