准备工作

工具介绍

软件

  • Keil5: 代码编译调试
  • CubeMX: 代码生成工具
  • VSCode: 代码编辑器
  • Modbus Poll && Slave: 调试工具

硬件

  • STM32F407ZGT6: 普中麒麟F407开发板
  • 两个串口转USB: 用于连接主机和从机

创建工程

CubeMX工程创建

  1. 选择芯片型号
  2. 设置时钟(外部晶振)
  3. 设置调试接口和基准时钟
  4. 配置串口(USART1~3)
  5. 开启FreeRTOS
  6. 创建3个任务
  7. 生成项目

Keil工程整合

将下载的Freemodbus源码复制到项目根目录,添加所需源文件:

  • modbus/functions/ 下所有文件
  • modbus/rtu/ 下所有文件
  • mb.cmb_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软件进行测试:

  1. 配置连接参数(波特率、校验位等)
  2. 设置从机保持寄存器默认值
  3. 观察读写数据是否正确

完整代码

GitHub: https://github.com/freedom413/ModBusDemo

包含Modbus Poll和Modbus Slave两个工程。