准备工作
工具介绍
软件
- Keil5: 代码编译调试
- CubeMX: 代码生成工具
- VSCode: 代码编辑器
- Modbus Poll && Slave: 调试工具
硬件
- STM32F407ZGT6: 普中麒麟F407开发板
- 两个串口转USB: 用于连接主机和从机
创建工程
CubeMX工程创建
- 选择芯片型号
- 设置时钟(外部晶振)
- 设置调试接口和基准时钟
- 配置串口(USART1~3)
- 开启FreeRTOS
- 创建3个任务
- 生成项目
Keil工程整合
将下载的Freemodbus源码复制到项目根目录,添加所需源文件:
modbus/functions/下所有文件modbus/rtu/下所有文件mb.c和mb_m.c
移植详解
port.c - 临界区实现
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
void EnterCriticalSection(void) {
taskENTER_CRITICAL();
}
void ExitCriticalSection(void) {
taskEXIT_CRITICAL();
}
portevent.c - 事件标志
使用FreeRTOS事件组实现Modbus事件通知。
portserial.c - 串口收发
实现串口初始化、收发控制,使用FIFO缓冲区接收数据。
porttimer.c - 定时器
实现Modbus帧间隔检测,波特率大于19200时固定为1750us。
主机移植
主机移植与从机类似,主要区别在于:
portevent_m.c中添加了响应事件标志- 使用信号量实现主机操作同步
主机使用示例
void MasterTaskFun(void *argument) {
for(;;) {
eMBMasterPoll();
}
}
void MasterSendTaskFun(void *argument) {
uint16_t data[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for(;;) {
eMBMasterReqWriteMultipleHoldingRegister(1, 0, 10, data, 100);
for (uint16_t i = 0; i < 10; i++) {
data[i] += 1;
}
osDelay(1000);
}
}
从机使用示例
void Slave_TaskFun(void *argument) {
for(;;) {
eMBPoll();
}
}
测试
使用Modbus Poll和Modbus Slave软件进行测试:
- 配置连接参数(波特率、校验位等)
- 设置从机保持寄存器默认值
- 观察读写数据是否正确
完整代码
GitHub: https://github.com/freedom413/ModBusDemo
包含Modbus Poll和Modbus Slave两个工程。