根据工业生产线安全监测系统需求,详见项目介绍【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.c、modbus.h(主功能实现)
- 接口文件:
modbus_master.c、modbus_master.h(主站功能)
- 移植关键点:硬件抽象层(HAL)适配
二、移植步骤
1. 工程配置
在e2studio中创建RA6M4新项目,启用必要的外设:
#include "hal_data.h"
fsp_err_t uart_modbus_init(void)
{
fsp_err_t err;
g_sci_b0.p_cfg->baud_rate = 9600;
g_sci_b0.p_cfg->data_bits = SCI_DATA_BITS_8;
g_sci_b0.p_cfg->parity = SCI_PARITY_NONE;
g_sci_b0.p_cfg->stop_bits = SCI_STOP_BITS_1;
g_sci_b0.p_cfg->clk_src = SCI_CLK_SRC_PCLK;
err = R_SCI_UART_Open(&g_sci_b0_ctrl, &g_sci_b0_cfg);
if (FSP_SUCCESS != err)
{
return err;
}
return FSP_SUCCESS;
}
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))
{
}
}
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.c、modbus.h、modbus_master.c、modbus_master.h到工程目录
- 在e2studio中右键项目→"Add"→"Existing Files..."添加这些文件
3. 实现硬件抽象层
nanoMODBUS需要以下硬件相关函数,创建modbus_hal.c进行实现:
#include "modbus.h"
#include "hal_data.h"
#include <stdint.h>
void modbus_delay_ms(uint32_t ms)
{
R_BSP_SoftwareDelay(ms, BSP_DELAY_UNITS_MILLISECONDS);
}
void modbus_send(uint8_t *data, uint16_t len)
{
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_02_PIN_03, BSP_IO_LEVEL_HIGH);
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);
}
uint16_t modbus_receive(uint8_t *data, uint16_t max_len, uint32_t timeout_ms)
{
return uart_modbus_receive(data, max_len, timeout_ms);
}
bool modbus_master_init(void)
{
fsp_err_t err;
err = uart_modbus_init();
if (FSP_SUCCESS != err)
{
return false;
}
err = R_IOPORT_Open(&g_ioport_ctrl, &g_ioport_cfg);
if (FSP_SUCCESS != err)
{
return false;
}
modbus_init(MODBUS_MODE_RTU, 0x01);
modbus_set_response_timeout(1000);
modbus_set_byte_timeout(100);
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);
}
三、测试与调试
- 硬件连接
- 将RA6M4的UART引脚通过RS485转换器连接到电脑的USB串口
- 确保共地连接,避免通信干扰
- 软件测试
- 在电脑上安装MODBUS从机测试软件(如QModMaster)
- 配置软件与开发板相同的波特率和参数
- 运行开发板程序,观察数据收发情况
- 常见问题排查
- 通信失败:检查波特率、奇偶校验、停止位是否匹配
- 数据错误:检查RS485方向控制是否正确
- 超时问题:调整超时参数,检查线路长度和干扰
四、注意事项
- MODBUS RTU协议对时序有严格要求,确保延时函数准确
- 如果使用长距离通信,建议添加光耦隔离保护
- 实际应用中应增加错误处理和重发机制
- 对于高速通信,可考虑使用DMA方式处理UART数据
通过以上步骤,即可在RA6M4开发板上成功移植nanoMODBUS库并实现主站功能,实现与电脑的稳定通信。