You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32 Modbus RTU USART发送场景下int变量转高低字节实现方法问询

问题原因

你用sprintf实现达不到预期是因为sprintf的%x是将数值转换为ASCII编码的十六进制字符串,例如455转义后得到的是字符数组{'1','c','7','\0'},对应ASCII值为0x31、0x63、0x37、0x00,和你需要的数值本身的高低字节完全是两个概念。

正确实现方式

方法1:位运算拆分(推荐,跨平台通用)

直接通过位运算提取16位数值的高低字节,该方法不受CPU大小端模式影响,完全符合Modbus RTU要求的大端序(高字节在前、低字节在后)规范:

#include <stdint.h>

int freq = 455;
// 先转换为Modbus要求的16位无符号类型,避免int溢出或符号位干扰
uint16_t modbus_val = (uint16_t)freq;
// 提取高低字节
uint8_t high_byte = (modbus_val >> 8) & 0xFF;
uint8_t low_byte = modbus_val & 0xFF;

你示例中的455对应十六进制为0x01C7,拆分后high_byte为0x01,low_byte为0xC7,完全符合你的需求。

报文填充示例

uint8_t pBuffer[8] = {0};
// 填充固定字段
pBuffer[0] = 0x02;    // 从站地址
pBuffer[1] = 0x06;    // 功能码:写单个保持寄存器
pBuffer[2] = 0x0C;    // 寄存器地址高字节
pBuffer[3] = 0x21;    // 寄存器地址低字节
// 填充数值字段
pBuffer[4] = high_byte;
pBuffer[5] = low_byte;
// 后续计算CRC16填充到pBuffer[6]、pBuffer[7]后即可发送
HAL_UART_Transmit(&huart2, pBuffer, 8, 0xFFFF);

可选方法:联合体拆分

如果你习惯用联合体也可以实现,原理是利用共用内存空间的特性直接读取高低字节:

union ModbusVal {
    uint16_t val;
    uint8_t byte[2];
};

union ModbusVal mval;
mval.val = (uint16_t)freq;
// 注意:STM32是小端模式,所以byte[0]是低字节,byte[1]是高字节
uint8_t high_byte = mval.byte[1];
uint8_t low_byte = mval.byte[0];

该方法仅适用于已知CPU大小端的场景,通用性不如位运算方法。

内容的提问来源于stack exchange,提问作者desarrollo1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 06:21:01