STM32F407上移植Modbus主机从机双角色协议栈,Keil5工程源代码,编译成功的工程,可以移植到其他单片机上。 1. 平台:STM32F407 2. 采用FreeRTOS实时操作系统,代码结构清晰 3. 采用ucModbus开源协议,支持Modbus主机和从机,可根据需要调用 4. Modbus主机从机双角色协议栈

最近,我尝试在STM32F407开发板上移植一个支持Modbus主机和从机双角色的协议栈。这个项目不仅锻炼了我的嵌入式开发能力,还让我对Modbus协议有了更深入的理解。今天,我来和大家分享一下整个过程。


项目背景

Modbus是一个广泛应用于工业自动化领域的通信协议,支持多种设备之间的数据交换。在实际应用中,有时需要一个设备同时支持Modbus主机(主动发送请求)和从机(被动响应请求)两种角色。为了实现这一目标,我选择了STM32F407作为开发平台,因为它具有强大的处理能力和丰富的外设资源。


开发环境与工具

  1. 硬件平台:STM32F407开发板(基于Cortex-M4内核,带有丰富的GPIO和UART资源)。
  2. 软件开发工具
    - Keil MDK-ARM:用于编写和编译代码。
    - FreeRTOS:实时操作系统,提供任务调度和多任务支持。
    - ucModbus:开源的Modbus协议栈,功能完善且易于移植。

代码结构与功能分析

1. FreeRTOS任务配置

FreeRTOS是这个项目的基础,它帮助我们将Modbus主机和从机功能分别运行在不同的任务中。以下是创建任务的代码片段:

void vApplicationTask() {
    // 创建Modbus主机任务
    xTaskCreate(vModbusHostTask, "Modbus Host", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
    // 创建Modbus从机任务
    xTaskCreate(vModbusSlaveTask, "Modbus Slave", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
    // 创建UART中断处理任务
    xTaskCreate(vUART中断处理, "UART Interrupt", configMINIMAL_STACK_SIZE, NULL, 2, NULL);
}

这里,vModbusHostTaskvModbusSlaveTask分别负责主机和从机的Modbus通信,而vUART中断处理用于处理UART的中断事件。


2. Modbus协议栈移植

ucModbus是一个轻量级的Modbus协议栈,支持RTU、ASCII和TCP三种模式。我们选择了RTU模式,因为其适合工业现场的串口通信。

STM32F407上移植Modbus主机从机双角色协议栈,Keil5工程源代码,编译成功的工程,可以移植到其他单片机上。 1. 平台:STM32F407 2. 采用FreeRTOS实时操作系统,代码结构清晰 3. 采用ucModbus开源协议,支持Modbus主机和从机,可根据需要调用 4. Modbus主机从机双角色协议栈

以下是初始化Modbus从机的代码:

void vModbusSlaveTask(void *pvParameters) {
    // 初始化Modbus从机
    modbusSlave_Init(MODBUS_SLAVE_ADDRESS, MODBUS_BAUDRATE, MODBUS_DATABITS, MODBUS_STOPBITS);
    while(1) {
        // 处理Modbus从机请求
        modbusSlave_Process();
        // 延时处理
        vTaskDelay(pdMS_TO_TICKS(100));
    }
}

从机任务的主要工作是监听来自主机的请求,并根据请求内容返回相应的数据。ucModbus的modbusSlave_Process函数会自动处理Modbus协议的解析和响应。

同样地,主机任务代码如下:

void vModbusHostTask(void *pvParameters) {
    // 初始化Modbus主机
    modbusHost_Init(MODBUS_BAUDRATE, MODBUS_DATABITS, MODBUS_STOPBITS);
    while(1) {
        // 向从机发送读取请求
        modbusHost_SendRequest(目标地址, MODBUS_READ_COIL, 起始地址, 个数);
        // 延时处理
        vTaskDelay(pdMS_TO_TICKS(500));
    }
}

主机任务负责定期向从机发送读写请求,并通过回调函数处理从机的响应。


3. UART中断与数据收发

由于Modbus通信依赖于UART,中断处理是整个系统的关键。以下是UART中断处理的代码:

void UART_IRQHandler(void) {
    if (UART_GetITStatus(UART1, UART_IT_RXNE)) {
        uint8_t data = UART_ReceiveData(UART1);
        // 将接收到的数据放入队列
        if (xQueueSendFromISR(UART_Queue, &data, NULL) != pdPASS) {
            // 队列满,丢弃数据
        }
    }
    // 清除中断标志
    UART_ClearITPendingBit(UART1, UART_IT_RXNE);
}

通过中断方式处理UART收发,可以提高系统的实时性。


移植与优化

在移植过程中,我遇到了以下问题:

  1. 中断优先级配置:由于FreeRTOS使用中断嵌套机制,需要确保UART中断优先级高于其他任务。
  2. 任务间通信:主机和从机任务需要共享数据,因此我使用了FreeRTOS的队列机制来实现任务间的同步与数据传递。
  3. 波特率配置:通过调整波特率参数,确保主机和从机之间的通信稳定。

测试与验证

1. 测试环境

使用两块STM32F407开发板,一块配置为主机,另一块配置为从机。通过串口助手(如Teraterm)发送Modbus请求,观察响应情况。

2. 测试结果

测试结果显示,主机和从机可以正常通信,读写操作均成功。以下是从机返回的数据示例:

0x01 0x05 0x00 0x07 0x00 0x64 0xB3 0x02

这是一个典型的Modbus响应报文,表示读取到了正确的数据。


总结

通过本次实践,我成功地在STM32F407上实现了Modbus主机和从机双角色的协议栈移植。整个过程涉及FreeRTOS的任务管理、ucModbus的协议处理以及UART的中断配置。该项目不仅可以作为学习Modbus协议的实践案例,还可以为工业自动化场景提供一种灵活的通信解决方案。


如果你也有兴趣尝试类似的项目,可以参考我的代码仓库或加入相关技术论坛,互相交流学习!

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐