欢迎光临
我们一直在努力

ESP32 使用ESP-IDF实现Modbus RTU主机通信源码分享

ESP32 使用ESP-IDF实现Modbus RTU主机通信源码分享

  • 一、源码分享
    • 1、效果展示
    • 2、开发环境搭建
    • 3、源码分享
      • 3.1、modbus组件添加
      • 3.2、 main.c
  • 二、modbus rtu详解
    • 1、协议概述
    • 2、报文结构
    • 3、 核心功能码
    • 4、数据寻址
    • 5、 通信时序
  • 三、ESP-IDF详解
    • 1、ESP32 概述
    • 2、 ESP-IDF 详解
      • 2.1 、ESP-IDF 的核心组件与架构
      • 2.2 、ESP-IDF 开发环境与工具链
      • 2.3 、ESP-IDF 开发流程简述
      • 2.4、 示例代码结构 (最简单的 Hello World)
      • 2.5、 优势与特点
      • 2.6 、适用场景
    • 3、总结

在这里插入图片描述

一、源码分享

1、效果展示

在这里插入图片描述

2、开发环境搭建

参考我这篇博文:VS Code 在线安装ESP-IDF,ESP32开发环境搭建详细教程

3、源码分享

3.1、modbus组件添加

Ctrl + Shift+P打开组件管理器 在这里插入图片描述 搜索modbus 在这里插入图片描述 选中espressif/esp-modbus点击install 在这里插入图片描述 等待加载完成

3.2、 main.c

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/projdefs.h"
#include "freertos/task.h"
#include "mbcontroller.h"
#include "driver/gpio.h"

typedef enum {
MODBUS_FC_READ_COILS = 0x01,
MODBUS_FC_READ_DISCRETE_INPUTS = 0x02,
MODBUS_FC_READ_HOLDING_REGISTERS = 0x03,
MODBUS_FC_READ_INPUT_REGISTERS = 0x04,
MODBUS_FC_WRITE_SINGLE_COIL = 0x05,
MODBUS_FC_WRITE_SINGLE_REGISTER = 0x06,
MODBUS_FC_WRITE_MULTIPLE_COILS = 0x0F,
MODBUS_FC_WRITE_MULTIPLE_REGISTERS = 0x10
} modbus_function_code_t;

void app_main(void)
{
uint16_t data[5];
static void *master_handle = NULL;
mb_communication_info_t comm = {
.ser_opts.port = UART_NUM_1,
.ser_opts.mode = MB_RTU,
.ser_opts.baudrate = 9600,
.ser_opts.parity = MB_PARITY_NONE,
.ser_opts.uid = 0,
.ser_opts.response_tout_ms = 1000,
.ser_opts.data_bits = UART_DATA_8_BITS,
.ser_opts.stop_bits = UART_STOP_BITS_1
};

esp_err_t err = mbc_master_create_serial(&comm, &master_handle);

if( master_handle == NULL)
{
ESP_LOGE("MASTER", "Failed to create master handle.");
return;
}
err = uart_set_pin(UART_NUM_1, GPIO_NUM_17, GPIO_NUM_16,
GPIO_NUM_18, UART_PIN_NO_CHANGE);
if (err != ESP_OK) {
ESP_LOGE("UART", "Failed to set UART pins. Error = %s", esp_err_to_name(err));
return;
}
err = uart_set_mode(UART_NUM_1, UART_MODE_UART);
if (err != ESP_OK) {
ESP_LOGE("UART", "Failed to set UART mode. Error = %s", esp_err_to_name(err));
return;
}
err = mbc_master_start(master_handle);
if (err != ESP_OK)
{
ESP_LOGE("MASTER", "Failed to start master.");
return;
}

while (1)
{
mb_param_request_t req =
{
.slave_addr = 1,
.command = MODBUS_FC_READ_HOLDING_REGISTERS,
.reg_start = 0,
.reg_size = 5
};

err = mbc_master_send_request(master_handle, &req, data);
if (err != ESP_OK)
{
ESP_LOGE("CUSTOM_DATA", "Send custom request fail.");
}
else
{
ESP_LOGI("CUSTOM_DATA", "Received data: %d %d %d %d %d", data[0], data[1], data[2], data[3], data[4]);
}
vTaskDelay(pdTICKS_TO_MS(500));
}

}

二、modbus rtu详解

1、协议概述

Modbus RTU是一种基于串行通信的工业控制协议,采用二进制编码格式。其物理层通常为RS-485或RS-232接口,遵循主从(Master/Slave)通信模式。主站主动发起请求,从站响应数据,通信速率范围为1200bps至115200bps。

2、报文结构

RTU报文由以下部分组成:

  • 地址域:1字节,范围

    0

    247

    0\\sim247

    0247(0为广播地址)

  • 功能码:1字节,定义操作类型(如03H读寄存器)
  • 数据域:长度可变,包含寄存器地址、数据值等
  • CRC校验:2字节,采用CRC-16算法

典型报文格式示例:

[地址][功能码][数据][CRC低字节][CRC高字节]

在这里插入图片描述

3、 核心功能码

功能码名称作用
01H 读线圈状态 读取开关量输出
02H 读离散输入 读取开关量输入
03H 读保持寄存器 读取可读写寄存器
04H 读输入寄存器 读取只读寄存器
05H 写单个线圈 修改单个开关量
06H 写单个寄存器 修改单个寄存器值
10H 写多个寄存器 批量修改寄存器

4、数据寻址

采用零基址映射:

  • 线圈地址范围:

    0000

    9999

    0000\\sim9999

    00009999(对应功能码01H/05H)

  • 寄存器地址范围:

    0000

    9999

    0000\\sim9999

    00009999(对应功能码03H/06H/10H) 实际物理地址通过偏移量计算:

    物理地址

    =

    协议地址

    +

    基址偏移量

    \\text{物理地址} = \\text{协议地址} + \\text{基址偏移量}

    物理地址=协议地址+基址偏移量

5、 通信时序

  • 帧间隔:至少3.5字符时间(T1.5规则)
  • 字节间隔:小于1.5字符时间 字符时间计算公式:

    T

    char

    =

    11

    ×

    1000

    波特率

    (ms)

    T_{\\text{char}} = \\frac{11 \\times 1000}{\\text{波特率}} \\text{(ms)}

    Tchar=波特率11×1000(ms)

三、ESP-IDF详解

1、ESP32 概述

ESP32 是由乐鑫科技(Espressif Systems)推出的一款高性能、低功耗、高集成度的 Wi-Fi & 蓝牙双模系统级芯片(SoC)。它广泛应用于物联网(IoT)、智能家居、工业控制等领域。其关键特性包括:

  • 双核处理器(通常为 Xtensa LX6,某些型号为 RISC-V)
  • 集成 Wi-Fi (802.11 b/g/n) 和蓝牙 (包括经典蓝牙和低功耗蓝牙 BLE)
  • 丰富的外设接口:

    S

    P

    I

    SPI

    SPI,

    I

    2

    C

    I2C

    I2C,

    I

    2

    S

    I2S

    I2S,

    U

    A

    R

    T

    UART

    UART,

    A

    D

    C

    ADC

    ADC,

    D

    A

    C

    DAC

    DAC,

    P

    W

    M

    PWM

    PWM, 触摸传感器等

  • 充足的内存(RAM 和 Flash 选项多样)
  • 强大的安全特性(如加密加速器)
  • 超低功耗设计,支持多种休眠模式

2、 ESP-IDF 详解

ESP-IDF (Espressif IoT Development Framework) 是乐鑫官方为 ESP32、ESP32-S 系列、ESP32-C 系列等芯片提供的开发框架和 SDK(软件开发工具包)。它是开发基于 ESP32 芯片应用程序的首选和官方推荐工具。

2.1 、ESP-IDF 的核心组件与架构

ESP-IDF 是一个分层、模块化的框架:

  • 硬件抽象层 (HAL): 提供对芯片硬件资源(如 GPIO、UART、SPI、I2C、定时器、ADC、DAC、RTC、Wi-Fi、蓝牙等)进行操作的统一接口,屏蔽底层硬件细节。
  • 驱动 (Drivers): 在 HAL 之上,提供更易用、功能更丰富的设备驱动(如 SPI Flash 驱动、SD 卡驱动、以太网驱动等)。
  • FreeRTOS: ESP-IDF 深度集成了开源的 FreeRTOS 实时操作系统内核。它提供了任务管理、队列、信号量、软件定时器、中断管理等机制,充分利用 ESP32 的多核特性(任务可以在不同核心上运行)。
  • 中间件:
    • Wi-Fi 协议栈: 实现 Wi-Fi 的 Station(客户端)、SoftAP(接入点)、Promiscuous(监听)模式。
    • 蓝牙协议栈: 实现经典蓝牙和低功耗蓝牙 (BLE) 的各种角色(如 GATT Client/Server, GAP Central/Peripheral)。
    • TCP/IP 协议栈 (lwIP): 轻量级的 TCP/IP 协议栈,支持 IPv4/IPv6 (部分型号)、DHCP、DNS、Socket API 等。
    • 文件系统 (FATFS/VFS): 支持在 SPI Flash 或外部存储设备上使用 FAT 文件系统。
    • 加密库: 提供 AES、SHA、RSA 等加密算法的软件和硬件加速实现。
    • HTTP/WebSocket/MQTT 等协议库: 方便构建网络应用。
  • 应用程序: 用户编写的业务逻辑代码,运行在 FreeRTOS 的任务中,通过调用下层 API 实现功能。

2.2 、ESP-IDF 开发环境与工具链

  • 工具链: 基于 GNU GCC 编译器(针对 Xtensa 或 RISC-V 架构)。
  • 构建系统: 使用 CMake(早期版本使用 GNU Make)。开发者编写 CMakeLists.txt 文件来定义项目结构、源文件、依赖组件等。
  • 配置工具: menuconfig。这是一个基于文本的图形化配置工具(类似于 Linux Kernel 的 make menuconfig),用于配置 ESP-IDF 的众多选项,如:
    • 选择目标芯片型号
    • 配置 Wi-Fi/BT 参数
    • 调整 FreeRTOS 设置(任务栈大小、优先级等)
    • 配置日志输出级别和方式
    • 配置内存布局
    • 启用/禁用特定功能和外设驱动
  • 核心工具 – idf.py: 这是 ESP-IDF 提供的命令行工具,用于执行构建、烧录、调试、监视串口输出等几乎所有开发任务。常用命令如:
    • idf.py set-target esp32 (设置目标芯片)
    • idf.py menuconfig (启动配置工具)
    • idf.py build (编译项目)
    • idf.py -p PORT flash (烧录固件到设备,PORT 为串口,如 COM3 或 /dev/ttyUSB0)
    • idf.py -p PORT monitor (启动串口监视器,查看设备日志输出)
    • idf.py fullclean (彻底清理构建目录)

2.3 、ESP-IDF 开发流程简述

  • 环境搭建: 在 Windows、Linux 或 macOS 上安装 ESP-IDF 开发环境(包括工具链、Python、Git 等)。
  • 创建项目: 使用 idf.py create-project 或复制示例项目模板。
  • 编写代码: 在 main 目录下编写应用程序代码 (通常是 main.c 或 app_main() 函数)。
  • 配置项目: 运行 idf.py menuconfig 根据需求进行配置。
  • 编译项目: 运行 idf.py build 生成可执行固件 (.bin 文件)。
  • 烧录固件: 将 ESP32 开发板连接到电脑,运行 idf.py -p PORT flash 将固件烧录到设备 Flash 中。
  • 监视输出: 运行 idf.py -p PORT monitor 查看设备运行日志,进行调试。可以使用 ESP_LOGx (如 ESP_LOGI, ESP_LOGE) 函数打印不同级别的日志。
  • 2.4、 示例代码结构 (最简单的 Hello World)

    #include "freertos/FreeRTOS.h"
    #include "freertos/task.h"
    #include "esp_log.h"

    static const char *TAG = "MAIN";

    void app_main(void)
    {
    while (1) {
    ESP_LOGI(TAG, "Hello World!"); // 打印 Info 级别日志
    vTaskDelay(pdMS_TO_TICKS(1000)); // 延时 1000 毫秒 (FreeRTOS 延时)
    }
    }

    2.5、 优势与特点

    • 官方支持: 由芯片原厂维护,更新及时,与新芯片特性同步快。
    • 功能全面: 提供对 ESP32 所有硬件特性和外设的底层访问。
    • 性能优化: 针对 ESP32 硬件进行了深度优化(如 Wi-Fi/BT 共存)。
    • 稳定性高: 经过大量商业产品验证。
    • 社区活跃: 用户多,社区支持好,问题容易找到解决方案。
    • 文档完善: 官方提供详尽的 API 参考指南、编程指南和示例代码。
    • 模块化: 易于扩展和复用代码,方便管理大型项目。
    • 开源免费: 基于 Apache 2.0 许可证。

    2.6 、适用场景

    ESP-IDF 适用于需要深度控制硬件、追求高性能、高稳定性或需要使用 ESP32 特有功能(如超低功耗协处理器 ULP)的应用开发。对于快速原型开发,也可以考虑基于 ESP-IDF 构建的更高级框架(如 Arduino for ESP32、MicroPython),但这些框架最终都依赖于 ESP-IDF 的底层功能。

    3、总结

    ESP-IDF 是开发 ESP32 系列芯片的强大、灵活且功能完备的官方框架。它提供了从硬件操作到网络协议栈的全套解决方案,结合 FreeRTOS 实现了高效的多任务处理。虽然其学习曲线相对陡峭,尤其是对于不熟悉嵌入式开发和 RTOS 的开发者,但它提供了最直接、最强大的方式来充分利用 ESP32 的潜力,是开发复杂或高性能 ESP32 应用的基石。掌握 idf.py 工具链和 menuconfig 配置是使用 ESP-IDF 的关键。

    在这里插入图片描述

    赞(0)
    未经允许不得转载:171主机测评 » ESP32 使用ESP-IDF实现Modbus RTU主机通信源码分享
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址