STM32F103开发板上移植Agile Modbus库的详细指南
- [一、Agile Modbus简介](#一、Agile Modbus简介)
- 二、准备工作
- 三、移植步骤
-
- [(一)添加Agile Modbus源码到项目中](#(一)添加Agile Modbus源码到项目中)
- [(二)初始化Modbus RTU句柄](#(二)初始化Modbus RTU句柄)
- (三)配置UART接口
- (四)实现发送和接收函数
- (五)实现Modbus主站功能
- (六)实现Modbus从机功能
- 四、测试与验证
- 五、总结
在嵌入式开发中,Modbus协议是工业自动化和物联网应用中常用的通信协议之一。Agile Modbus是一个轻量级、纯C语言编写的Modbus库,支持Modbus RTU和Modbus TCP协议,且完全脱离硬件,非常适合在各种平台上移植。本文将详细介绍如何在STM32F103开发板上移植Agile Modbus库,实现Modbus RTU通信。
一、Agile Modbus简介
Agile Modbus是一个开源的Modbus库,其核心代码完全用C语言编写,不依赖于任何特定硬件平台,因此可以轻松移植到任何支持C语言的微控制器上。它支持Modbus RTU和Modbus TCP两种通信模式,本文主要介绍Modbus RTU的移植。
GitHub源码地址:[Agile Modbus GitHub]
二、准备工作
(一)硬件准备
• STM32F103开发板:确保开发板正常工作,所有引脚连接良好。
• RS485模块:用于实现Modbus RTU通信,连接到STM32F103的UART接口。
• ModbusPoll和ModbusSlaver:分别用于调试和测试Modbus从机和主机通信。
(二)软件准备
• STM32CubeMX:用于生成初始化代码。
• STM32CubeIDE:用于编写和编译代码。
• Agile Modbus源码:从GitHub下载Agile Modbus库的源码。
三、移植步骤
(一)添加Agile Modbus源码到项目中
• 下载Agile Modbus源码:从GitHub下载Agile Modbus库的源码,解压后找到agile_modbus/inc、agile_modbus/src和agile_modbus/util三个文件夹。

• 导入源码到项目:在STM32CubeIDE中创建一个新的STM32项目,将上述三个文件夹中的所有文件添加到项目中。

(二)初始化Modbus RTU句柄
在STM32F103开发板上,我们需要初始化Modbus RTU句柄,配置发送和接收缓冲区,并设置从机地址。
c
#include "agile_modbus.h"
static uint8_t mb_send_buf[256]; // 发送缓冲区
static uint8_t mb_recv_buf[256]; // 接收缓冲区
agile_modbus_rtu_t mb_rtu = {0}; // Modbus RTU句柄
void Modbus_Init(void)
{
// 初始化Modbus RTU句柄
agile_modbus_rtu_init(&mb_rtu, mb_send_buf, sizeof(mb_send_buf), mb_recv_buf, sizeof(mb_recv_buf));
// 设置从机地址(根据实际情况修改)
agile_modbus_set_slave(&mb_rtu._ctx, 0x01);
}
(三)配置UART接口
在STM32CubeMX中配置UART接口,用于与RS485模块通信。以下是关键配置步骤:
• 选择UART接口:例如选择USART1。
• 配置波特率:根据Modbus协议的要求,通常设置为9600。
• 配置数据位、停止位和校验位:设置为8位数据位、1位停止位、无校验位。
• 启用DMA接收:为了提高通信效率,建议启用DMA接收功能。
生成代码后,确保在MX_USART1_UART_Init()函数中正确配置了UART参数。
(四)实现发送和接收函数
Agile Modbus库需要用户提供发送和接收函数。以下是基于STM32 HAL库的实现:
c
#include "usart.h"
// 发送函数
int MB_Transmit(uint8_t *buf, int len)
{
HAL_UART_Transmit(&huart1, buf, len, HAL_MAX_DELAY);
return len;
}
// 接收函数
int MB_Receive(uint8_t *buf, int len)
{
int recv_len = HAL_UART_Receive(&huart1, buf, len, HAL_MAX_DELAY);
return recv_len;
}
(五)实现Modbus主站功能
以下是一个简单的Modbus主站任务,用于读取从机的输入寄存器。
c
#include "agile_modbus.h"
#include "usart.h"
void Modbus_Master_Task(void)
{
int send_len = 0, recv_len = 0;
uint16_t reg_data[10] = {0}; // 存储读取的寄存器数据
while (1)
{
// 清空接收缓冲区
memset(mb_recv_buf, 0, sizeof(mb_recv_buf));
// 组包并发送读取输入寄存器请求
send_len = agile_modbus_serialize_read_input_registers(&mb_rtu._ctx, 0x00, 5);
if (send_len > 0)
{
MB_Transmit(mb_send_buf, send_len); // 发送请求
}
// 接收从机响应
recv_len = MB_Receive(mb_recv_buf, sizeof(mb_recv_buf));
if (recv_len > 0)
{
// 解包响应数据
int data_count = agile_modbus_deserialize_read_input_registers(&mb_rtu._ctx, recv_len, reg_data);
if (data_count > 0)
{
// 打印读取的寄存器数据
for (int i = 0; i < data_count; i++)
{
printf("Reg[%d] = %d\r\n", i, reg_data[i]);
}
}
}
HAL_Delay(1000); // 延时1秒
}
}
(六)实现Modbus从机功能
以下是一个简单的Modbus从机任务,用于响应主站的读取请求。
c
#include "agile_modbus.h"
#include "usart.h"
// 输入寄存器映射
typedef struct
{
uint16_t reg0;
uint16_t reg1;
uint16_t reg2;
uint16_t reg3;
uint16_t reg4;
} InputRegs;
static InputRegs input_regs = {1, 2, 3, 4, 5};
// 获取输入寄存器数据
static int Get_Input_Regs(void *buf, int bufsz)
{
memcpy(buf, &input_regs, sizeof(input_regs));
return 0;
}
// 输入寄存器映射表
agile_modbus_slave_util_map_t input_map =
{
0x00,
sizeof(input_regs),
Get_Input_Regs,
NULL
};
// 从机工具结构体
const agile_modbus_slave_util_t slave_util =
{
NULL,
0x00,
NULL,
0x00,
NULL,
0x00,
&input_map,
sizeof(input_regs)
};
void Modbus_Slave_Task(void)
{
int recv_len = 0, send_len = 0;
while (1)
{
// 接收主站请求
recv_len = MB_Receive(mb_recv_buf, sizeof(mb_recv_buf));
if (recv_len > 0)
{
// 处理请求并生成响应
send_len = agile_modbus_slave_handle(&mb_rtu._ctx, recv_len, 1, agile_modbus_slave_util_callback, &slave_util, NULL);
if (send_len > 0)
{
// 发送响应
MB_Transmit(mb_send_buf, send_len);
}
}
}
}
四、测试与验证
• 硬件连接:将RS485模块连接到STM32F103的USART1接口,并确保RS485模块的DE(数据使能)引脚正确控制发送/接收模式。
• 编译与烧录:将上述代码编译并烧录到STM32F103开发板上。
• 启动ModbusSlaver:设置波特率为9600,观察Modbus主机通信的发送和接收数据。
• 测试主站功能:运行主站任务,观察是否能正确读取从机的输入寄存器数据。
• 启动ModbusPoll:设置波特率为9600,观察Modbus从机通信的发送和接收数据。
• 测试从机功能:运行从机任务,观察是否能正确响应主站的读取请求。
五、总结
通过上述步骤,我们成功在STM32F103开发板上移植了Agile Modbus库,实现了Modbus RTU主站和从机的功能。Agile Modbus库的轻量级特性和良好的移植性使其非常适合在STM32等嵌入式平台上使用。希望本文能为你的Modbus项目提供帮助!