🗣 Wd提问: 单片机modbus主机程序
🤖 Ai回答: Modbus 是一种常用的工业通信协议,常用于单片机(如 STM32、Arduino、51 单片机等)与外部设备(如传感器、PLC、变频器等)之间的数据交换。Modbus 有多种实现方式,包括 Modbus RTU 和 Modbus ASCII,其中 Modbus RTU 更为常见。
下面是一个基于 STM32 的 Modbus 主机程序示例(使用 HAL 库),并附上一个简单的 Modbus 主机轮询读取寄存器的代码框架。
✅ 一、Modbus 主机功能说明
Modbus 主机(Master)是发起请求的一方,通常通过串口(RS-485 或 RS-232)与从机(Slave)通信。常见的功能码包括:
`0x03`:读取输入寄存器(Read Input Registers)
`0x04`:读取保持寄存器(Read Holding Registers)
`0x06`:写单个寄存器(Write Single Register)
`0x10`:写多个寄存器(Write Multiple Registers)
✅ 二、硬件准备(以 STM32 为例)
STM32 开发板(如 STM32F103C8T6)
RS-485 收发模块(如 MAX232 或 MAX485)
串口连接到 Modbus 从机
波特率设置一致(如 9600, 8N1)
✅ 三、STM32 Modbus 主机程序结构
1、引入头文件和定义
c
include stm32f1xx_hal.h
include stdio.h
include string.h
// 定义 Modbus 帧结构体
typedef struct {
uint8_t address;
uint8_t function_code;
uint16_t start_address;
uint16_t quantity;
uint16_t data[32]; // 假设最多读取32个寄存器
} ModbusRequest;
// 接收缓冲区
define RX_BUFFER_SIZE 128
uint8_t rx_buffer[RX_BUFFER_SIZE];
uint16_t rx_length = 0;
// 发送缓冲区
uint8_t tx_buffer[128];
2、初始化串口(USART)
c
UART_HandleTypeDef huart1;
void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 9600;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
HAL_UART_Init(&huart1);
}
3、Modbus 请求帧构造函数(以读取保持寄存器为例)
c
void build_modbus_request(uint8_t slave_id, uint8_t function_code,
uint16_t start_addr, uint16_t num_regs, uint8_t *buffer)
{
buffer[0] = slave_id; // 从机地址
buffer[1] = function_code; // 功能码
buffer[2] = (start_addr 8); // 起始地址高位
buffer[3] = (start_addr & 0xFF); // 起始地址低位
buffer[4] = (num_regs 8); // 寄存器数量高位
buffer[5] = (num_regs & 0xFF); // 寄存器数量低位
// CRC 校验
uint16_t crc = modbus_crc(buffer, 6);
buffer[6] = (crc & 0xFF);
buffer[7] = (crc 8);
}
4、CRC 计算函数(Modbus RTU)
c
uint16_t modbus_crc(uint8_t *data, uint16_t length)
{
uint16_t crc = 0xFFFF;
for (uint16_t i = 0; i < length; i++) {
crc ^= (uint16_t)data[i];
for (uint8_t j = 0; j < 8; j++) {
if (crc & 0x0001) {
crc = (crc 1) ^ 0xA001;
} else {
crc = 1;
}
}
}
return crc;
}
5、发送 Modbus 请求
c
void send_modbus_request(uint8_t *request, uint16_t len)
{
HAL_UART_Transmit(&huart1, request, len, HAL_MAX_DELAY);
}
6、接收 Modbus 响应
c
void receive_modbus_response(uint8_t *response, uint16_t *len)
{
while (rx_length < 5) { // 至少接收5字节(地址+功能码+字节数+数据+CRC)
HAL_UART_Receive_IT(&huart1, rx_buffer + rx_length, 1);
rx_length++;
}
// 检查CRC
uint16_t expected_crc = (rx_buffer[rx_length 2] << 8) | rx_buffer[rx_length 1];
uint16_t actual_crc = modbus_crc(rx_buffer, rx_length 2);
if (expected_crc == actual_crc) {
memcpy(response, rx_buffer, rx_length);
*len = rx_length;
} else {
// CRC 错误处理
}
}
7、主循环(主程序)
c
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
uint8_t request[8];
uint8_t response[128];
uint16_t response_len;
while (1) {
// 构造请求
build_modbus_request(0x01, 0x03, 0x0000, 0x0002, request);
// 发送请求
send_modbus_request(request, 8);
// 接收响应
receive_modbus_response(response, &response_len);
// 处理响应数据
if (response_len 5) {
uint8_t byte_count = response[2];
for (uint8_t i = 0; i < byte_count; i += 2) {
uint16_t value = (response[3 + i] << 8) | response[4 + i];
printf(Register %d: 0x%04X\n, i / 2, value);
}
}
HAL_Delay(1000); // 每秒读一次
}
}
✅ 四、注意事项
确保波特率、数据位、停止位、校验位与从机一致。
使用 RS-485 时注意方向控制(DE/RE 引脚)。
可使用 `HAL_UART_Receive_IT()` 实现中断接收,提高效率。
如果使用其他单片机(如 Arduino、ESP32、51 单片机),逻辑类似,但需要调整串口库。
✅ 五、参考资源
[Modbus 协议规范](https://www.modbus.org/docs/Modbus_Application_Protocol_V1.1b3.pdf)
[STM32 HAL 库文档](https://www.st.com/en/embedded-software/stm32cube-embedded-software.html)
[Modbus RTU CRC 计算工具](https://www.circuitspecialists.com/blog/modbus-crc-calculator)
如果你有具体的单片机型号或开发环境(如 STM32、Arduino、ESP32、51 单片机等),我可以为你提供更详细的代码或优化建议。欢迎继续提问!
📣 商家广告:





0
IP地址: 72.218.114.170
搜索次数: 0
提问时间: 2025-11-08 23:13:30
🛒 域名购买:
app.jl.cn
67.gs
23.gold
touwang.com.cn
zr.gs
soukan.com.cn
op.gs
25.gs
cgbc.cn
zansou.com.cn
❓️ 热门提问:
什么挂机软件好用
ip global
小型机房设计
机房抗震等级
云计算龙头公司
mysql安装在云服务器上
wap网页制作
高带宽 vps
代理服务器设置
电脑cpu加速
豌豆Ai站群搜索引擎系统
🌐 域名评估:
ltkj.net
s.xj.cn
rr.tj.cn
hh.jx.cn
oo.zj.cn
su8.jx.cn
ypettoy.com
drones.cab
vivo.fj.cn
aa.ln.cn
⛏ 最新挖掘:
凯里酸汤鱼
贵阳烤脑花
都匀毛尖茶
花溪牛肉粉
贵阳烤生蚝
贵阳烤豆腐
贵阳纸包鱼
贵阳特色菜
🖌 热门作画:
🤝 关于我们:
豌豆Ai
域名
建站
站群
留痕
推广
评估
源码
开发Ai
工具
日记
价格
加盟
广告
流量
留言
联系
🗨 加入群聊:
🔗 友情链接:
谷歌搜索推广
検索エンジン 海外
ai提问
🧰 站长工具:
Ai工具 whois查询 搜索
📢 温馨提示:本站所有问答由Ai自动创作,内容仅供参考,若有误差请用“联系”里面信息通知我们人工修改或删除。
👉 技术支持:本站由豌豆Ai提供技术支持,使用的最新版:《豌豆Ai站群搜索引擎系统 V.25.10.25》搭建本站。