【瑞萨 RA6M4】开发环境搭建(1)
【瑞萨 RA6M4】快速傅里叶变换(FFT)测试(2)
【瑞萨 RA6M4】定时器实现SPWM(3)
【瑞萨 RA6M4】基于RS232 接口的 Modbus-RTU 从机实现 (4)
【瑞萨 RA6M4】基于FSP的FreeRTOS移植 (5)


1、modbus 协议是工业运用比较成熟的通信协议,本例基于瑞萨RA6M4单片机进行modbus协议的实现,开源的modbus 协议较多,本例以移植Xtiny-Modbus为展示:
(1)、第一步:搭建硬件环境
   由于开发板没有带串口,需要外接一个串口收发模块
image.png
(2)、第二步:下载开源的源码,下载地址:Xtiny-Modbus移植示例
(3)、第三步:建立工程,配置时钟
由于外部高速晶振24MHz没有焊接,需要配置为内部晶振16MHz,然后再2分频
image.png
(4)、第四步:配置串口
设置波特率、回调函数、中断优先级
image.png
(5)、第五步:配置定时器

设置定时器计时的周期,回调函数、中断优先级
image.png
(6)、第六步:编写串口驱动函数
#include "usart3.h"
  • #include "Sys_Config.h"
  • #if MD_USD_SALVE
  • #include "MDS_RTU_Serial.h"
  • #else
  • #include "MDM_RTU_Serial.h"
  • #include "MD_RTU_SysInterface.h"
  • #include "MDM_RTU_Fun.h"
  • #endif
  • volatile uint8_t flag=false;
  • void RS485RWConvInit(void)
  • {
  •         //收发引脚配置
  • //        R_IOPORT_Open(&g_ioport_ctrl,g_ioport.p_cfg);
  • //        R_IOPORT_PinWrite(&g_ioport_ctrl,BSP_IO_PORT_05_PIN_03,BSP_IO_LEVEL_LOW);
  • }
  • //串口1配置
  • void init_usart3(void)
  • {
  •         R_SCI_UART_Open(&g_uart0_ctrl,g_uart0.p_cfg);
  •         RS485RWConvInit();
  • }
  • void usart3_send_byte(uint8_t byte)
  • {
  •         R_SCI_UART_Write(&g_uart0_ctrl,(uint8_t*)(&(byte)),1);
  •         while(flag!=true);
  •         flag=false;
  • }
  • void usart3_send_bytes(uint8_t *bytes,int len)
  • {
  •         int i;
  •         for(i=0;i<len;i++){
  •                 usart3_send_byte(bytes[i]);
  •         }
  • }
  • void usart3_send_string(char *string)
  • {
  •         while(*string)
  •         {
  •                 usart3_send_byte(*string++);
  •         }
  • }
  • void uart_callback(uart_callback_args_t *arg)
  • {
  •         uint8_t data_r;
  •         
  •         switch(arg->event)
  •         {
  •                 case UART_EVENT_RX_CHAR:
  • //                        R_SCI_UART_Read(&g_uart0_ctrl,(u8*)(&(data_r)),1);
  •                         data_r=(uint8_t)(arg->data);
  •                         #if !MD_RTU_USED_OS
  •                                 #if MD_USD_SALVE
  •                                         MDSSerialRecvByte(data_r);
  •                                 #else
  •                                         #if MDM_USD_USART3
  •                                                 MDMSerialRecvByte(data);
  •                                         #endif
  •                                 #endif
  •                         #else
  •                                 extern Modbus_RTU modbus_RTU;
  •                                 MD_RTU_MsgPut((PModbusBase)(&modbus_RTU), MD_RTU_MSG_HANDLE_ARG(&modbus_RTU),(void*)(data),0);
  •                         #endif
  •                         break;
  •                
  •                 case UART_EVENT_TX_COMPLETE:
  •                         flag=true;
  •                         break;
  •                
  •                 default:
  •                         break;
  •         }
  •         
  • }
  • 复制代码
    (7)、第7步编写定时器驱动程序:
    #include "tim3.h"
  • #include "Sys_Config.h"
  • #if MD_USD_SALVE
  • #include "MDS_RTU_Serial.h"
  • //#include "MDS_RTU_Serial_1.h"
  • #else
  • #include "MDM_RTU_Serial.h"
  • #endif
  • volatile uint32_t sys_tick_100us=0;
  • void TIM3_Int_Init(void)
  • {
  •         R_AGT_Open(&g_timer0_ctrl,g_timer0.p_cfg);
  •         R_AGT_Start(&g_timer0_ctrl);
  • }
  • void timer_callback(timer_callback_args_t *arg)                                                                                                   
  • {
  •         if(arg->event==TIMER_EVENT_CYCLE_END)
  • //        if (timer_interrupt_flag_get(TIMER5, TIMER_INT_FLAG_UP) != RESET)         
  •         {                  
  •                 sys_tick_100us++;
  •                 #if !MD_RTU_USED_OS
  •                         #if MD_USD_SALVE
  •                         MDSTimeHandler100US(sys_tick_100us);
  •                         #else
  •                         MDMTimeHandler100US(sys_tick_100us);
  •                         #endif
  •                 #endif
  •         }
  • }
  • 复制代码
    (8)、第八步:编写应用程序
    static void MDS_RTU_UserUpdate(void){
  •         uint16 temp=0xff;
  •         uint16 temp1[]={1,2,3,4,5};
  •         MDS_RTU_WriteCoils(&modbusS_RTU,1,5,&temp);
  •         MDS_RTU_WriteHoldReg(&modbusS_RTU,11, temp);
  •         MDS_RTU_WriteHoldRegs(&modbusS_RTU,5,5,temp1);
  • }
  • 复制代码
    (9)、第九步:编写处理程序
    #include "hal_data.h"
  • #include "tim3.h"
  • #include "Sys_Config.h"
  • #if MD_USD_SALVE
  • #include "MDS_RTU_APP.h"
  • #else
  • #include "MDM_RTU_APP.h"
  • #include "MDM_RTU_Fun.h"
  • #include "MDM_RTU_User_Fun.h"
  • #endif
  • FSP_CPP_HEADER
  • void R_BSP_WarmStart(bsp_warm_start_event_t event);
  • FSP_CPP_FOOTER
  • /*******************************************************************************************************************//**
  • * main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used.  This function
  • * is called by main() when no RTOS is used.
  • **********************************************************************************************************************/
  • void hal_entry(void)
  • {
  •     /* TODO: add your own code here */
  •         
  •         #if MD_RTU_USED_OS
  •         OSInit();         
  •                  #endif
  •         //delay_init();
  • #if MD_USD_SALVE
  •                 MDS_RTU_APPInit();
  • #else
  •                 MDM_RTU_APPInit();
  •          
  • #endif
  •         TIM3_Int_Init();
  •          
  •         
  •         #if MD_RTU_USED_OS
  •         task1=OSCreateTask(mdTestTask0,NULL,6,256);
  •         task2=OSCreateTask(mdTestTask1,NULL,6,256);
  •         SysTick_Config(SystemCoreClock / OS_TICKS_PER_SEC);
  •         OSStart();
  •         #endif
  •         while(1){
  •                 #if !MD_RTU_USED_OS
  •                         #if MD_USD_SALVE
  •                         MDS_RTU_Loop();
  •                         #else
  •                         MDM_RTU_Loop();
  •                         MDM_RW_CtrlLoop();
  •                         #endif
  •                 #endif
  •         }
  • #if BSP_TZ_SECURE_BUILD
  •     /* Enter non-secure code */
  •     R_BSP_NonSecureEnter();
  • #endif
  • }
  • 复制代码
    (10)、第十步:连接Modbus 主机,查看结果
    image.png