根据工业生产线安全监测系统需求,详见项目介绍【RA-Eco-RA6M4开发板评测】基于 RA6M4 MCU的工业生产线安全监测系统项目介绍 ,今天主要实现在RA6M4开发板移植nanoMODBUS库主站功能,实现将数据发送到上位机。
将nanoMODBUS库移植到RA6M4开发板需要完成库文件整合、硬件接口适配和功能验证三个主要阶段。以下是详细的移植步骤:
modbus.c、modbus.h(主功能实现)modbus_master.c、modbus_master.h(主站功能)在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;
}
将nanoMODBUS源文件添加到项目:
modbus.c、modbus.h、modbus_master.c、modbus_master.h到工程目录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;
}
在modbus.h中根据需要修改配置:
// 定义缓冲区大小(根据需求调整)
#define MODBUS_MAX_FRAME_LENGTH 256
#define MODBUS_MASTER_MAX_REGS 64 // 最大寄存器数量
创建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开发板上成功移植nanoMODBUS库并实现主站功能,实现与电脑的稳定通信。
更多回帖