单片机/MCU论坛
直播中

xcs101

11年用户 118经验值
擅长:可编程逻辑,MEMS/传感技术,处理器/DSP,控制/MCU
私信 关注

【RA-Eco-RA6M4开发板评测】基于 RA6M4 MCU的工业生产线安全监测系统移植nanoMODBUS

根据工业生产线安全监测系统需求,详见项目介绍【RA-Eco-RA6M4开发板评测】基于 RA6M4 MCU的工业生产线安全监测系统项目介绍 ,今天主要实现在RA6M4开发板移植nanoMODBUS库主站功能,实现将数据发送到上位机。
将nanoMODBUS库移植到RA6M4开发板需要完成库文件整合、硬件接口适配和功能验证三个主要阶段。以下是详细的移植步骤:

一、准备工作

1. 获取必要资源

  • 下载nanoMODBUS库:从GitHub仓库获取最新版本
  • 准备RA6M4开发环境:安装e2studio和RA Family设备支持包
  • 准备RA6M4开发板硬件:确保UART接口可用(建议使用SCI_B或SCI_C)

2. 了解nanoMODBUS结构

  • 核心文件:modbus.cmodbus.h(主功能实现)
  • 接口文件:modbus_master.cmodbus_master.h(主站功能)
  • 移植关键点:硬件抽象层(HAL)适配

二、移植步骤

1. 工程配置

在e2studio中创建RA6M4新项目,启用必要的外设:

  • 配置一个UART接口(如SCI_B0)作为MODBUS通信端口

  • 配置GPIO用于状态指示(可选)

  • 配置系统时钟(建议至少48MHz)

    创建uart_config.c文件

#include "hal_data.h"

fsp_err_t uart_modbus_init(void)
{
    fsp_err_t err;
    
    // 配置SCI参数
    g_sci_b0.p_cfg->baud_rate    = 9600;       // MODBUS常用波特率
    g_sci_b0.p_cfg->data_bits    = SCI_DATA_BITS_8;
    g_sci_b0.p_cfg->parity       = SCI_PARITY_NONE;  // MODBUS RTU通常无奇偶校验
    g_sci_b0.p_cfg->stop_bits    = SCI_STOP_BITS_1;
    g_sci_b0.p_cfg->clk_src      = SCI_CLK_SRC_PCLK;
    
    // 初始化SCI
    err = R_SCI_UART_Open(&g_sci_b0_ctrl, &g_sci_b0_cfg);
    if (FSP_SUCCESS != err)
    {
        return err;
    }
    
    return FSP_SUCCESS;
}

// UART发送函数
void uart_modbus_send(uint8_t *data, uint16_t len)
{
    R_SCI_UART_Write(&g_sci_b0_ctrl, data, len);
    while (SCI_UART_STATE_TX_IDLE != R_SCI_UART_StatusGet(&g_sci_b0_ctrl))
    {
        // 等待发送完成
    }
}

// UART接收函数
uint16_t uart_modbus_receive(uint8_t *data, uint16_t max_len, uint32_t timeout_ms)
{
    uint16_t received = 0;
    fsp_err_t err;
    uint32_t start_time = R_BSP_SoftwareDelayGetTick();
    
    while (received < max_len)
    {
        err = R_SCI_UART_Read(&g_sci_b0_ctrl, &data[received], 1);
        if (FSP_SUCCESS == err)
        {
            received++;
        }
        
        // 超时检查
        if ((R_BSP_SoftwareDelayGetTick() - start_time) >= timeout_ms)
        {
            break;
        }
    }
    
    return received;
}

2. 整合nanoMODBUS库

将nanoMODBUS源文件添加到项目:

  • 复制modbus.cmodbus.hmodbus_master.cmodbus_master.h到工程目录
  • 在e2studio中右键项目→"Add"→"Existing Files..."添加这些文件

3. 实现硬件抽象层

nanoMODBUS需要以下硬件相关函数,创建modbus_hal.c进行实现:

#include "modbus.h"
#include "hal_data.h"
#include <stdint.h>

// 实现MODBUS所需的延时函数
void modbus_delay_ms(uint32_t ms)
{
    R_BSP_SoftwareDelay(ms, BSP_DELAY_UNITS_MILLISECONDS);
}

// 实现MODBUS发送函数
void modbus_send(uint8_t *data, uint16_t len)
{
    // 发送前使能RS485发送方向(如果使用RS485)
    R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_02_PIN_03, BSP_IO_LEVEL_HIGH);
    
    // 调用UART发送函数
    uart_modbus_send(data, len);
    
    // 等待发送完成
    modbus_delay_ms(1);
    
    // 切换回接收方向
    R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_02_PIN_03, BSP_IO_LEVEL_LOW);
}

// 实现MODBUS接收函数
uint16_t modbus_receive(uint8_t *data, uint16_t max_len, uint32_t timeout_ms)
{
    return uart_modbus_receive(data, max_len, timeout_ms);
}

// MODBUS主站初始化
bool modbus_master_init(void)
{
    fsp_err_t err;
    
    // 初始化UART
    err = uart_modbus_init();
    if (FSP_SUCCESS != err)
    {
        return false;
    }
    
    // 初始化RS485方向控制引脚(如果使用)
    err = R_IOPORT_Open(&g_ioport_ctrl, &g_ioport_cfg);
    if (FSP_SUCCESS != err)
    {
        return false;
    }
    
    // 初始化MODBUS主站
    modbus_init(MODBUS_MODE_RTU, 0x01);  // RTU模式,从机地址0x01
    modbus_set_response_timeout(1000);   // 1秒响应超时
    modbus_set_byte_timeout(100);        // 100ms字节超时
    
    return true;
}

4. 配置nanoMODBUS参数

modbus.h中根据需要修改配置:

// 定义缓冲区大小(根据需求调整)
#define MODBUS_MAX_FRAME_LENGTH  256
#define MODBUS_MASTER_MAX_REGS   64    // 最大寄存器数量

5. 实现主站功能函数

创建modbus_functions.c加入功能函数

#include "modbus_master.h"
#include "hal_data.h"

// 向从机写入保持寄存器
bool modbus_send_data(uint16_t start_addr, uint16_t *data, uint16_t count)
{
    modbus_error_t err;
    
    // 发送写多个寄存器命令
    err = modbus_master_write_multiple_registers(
        start_addr,    // 起始地址
        count,         // 寄存器数量
        data           // 数据指针
    );
    
    return (err == MODBUS_OK);
}

// 从从机读取保持寄存器
bool modbus_receive_data(uint16_t start_addr, uint16_t *data, uint16_t count)
{
    modbus_error_t err;
    
    // 读取多个寄存器
    err = modbus_master_read_holding_registers(
        start_addr,    // 起始地址
        count,         // 寄存器数量
        data           // 接收缓冲区
    );
    
    return (err == MODBUS_OK);
}

三、测试与调试

  1. 硬件连接
    • 将RA6M4的UART引脚通过RS485转换器连接到电脑的USB串口
    • 确保共地连接,避免通信干扰
  2. 软件测试
    • 在电脑上安装MODBUS从机测试软件(如QModMaster)
    • 配置软件与开发板相同的波特率和参数
    • 运行开发板程序,观察数据收发情况
  3. 常见问题排查
    • 通信失败:检查波特率、奇偶校验、停止位是否匹配
    • 数据错误:检查RS485方向控制是否正确
    • 超时问题:调整超时参数,检查线路长度和干扰

四、注意事项

  1. MODBUS RTU协议对时序有严格要求,确保延时函数准确
  2. 如果使用长距离通信,建议添加光耦隔离保护
  3. 实际应用中应增加错误处理和重发机制
  4. 对于高速通信,可考虑使用DMA方式处理UART数据

通过以上步骤,即可在RA6M4开发板上成功移植nanoMODBUS库并实现主站功能,实现与电脑的稳定通信。

更多回帖

发帖
×
20
完善资料,
赚取积分