流水源 发表于 2026-8-5 23:49:44

【瑞萨RA-eco-RA6M4评测】实现串口发送接收shell

今天学习RA6M4的串口发送接收功能。实现shell命令测试。开发板上有个USB转串口接口,这次就用这个测试串口发送接收数据。
!(https://www.eefocus.com/forum/data/attachment/forum/202608/05/233414shyuuyyouzuctzyh.png)

根据电路图,我们知道了串口使用引脚为P109和P110。下面打开RASC软件配置串口功能。利用上次的例子工程,我们继续添加串口外设。
先配置P109和P110为SCI9的串口。
!(https://www.eefocus.com/forum/data/attachment/forum/202608/05/233928ny1x8778tutrhn7e.png)
!(https://www.eefocus.com/forum/data/attachment/forum/202608/05/234018sqxg6zx6m22cd2xm.png)

然后添加串口通信功能配置。这里配置串口为SCI的第9通道,115200波特率。

!(https://www.eefocus.com/forum/data/attachment/forum/202608/05/233821ap5mq5ia6ua55555.png)

!(https://www.eefocus.com/forum/data/attachment/forum/202608/05/234125pdnrqilpq3tzikz9.png)
在组件里面添加串口外设驱动。
!(https://www.eefocus.com/forum/data/attachment/forum/202608/05/234326gwtx7tx17y4vbfwb.png)

最后生成keil代码工程。
!(https://www.eefocus.com/forum/data/attachment/forum/202608/05/234415pvmdwm9nwyztnakd.png)

添加串口发送接收函数驱动。

```
/******************************************************************************
* Include files
******************************************************************************/
#include "main.h"
#include "shell_uart.h"
#include "hal_data.h"

#include<RTE_Components.h>
#undef __USE_EVENT_RECORDER__
#if defined(RTE_Compiler_EventRecorder) || defined(RTE_CMSIS_View_EventRecorder)
#   define __USE_EVENT_RECORDER__1
#endif
#if __USE_EVENT_RECORDER__
#   include <EventRecorder.h>
#   include "EventRecorderConf.h"
#endif

typedef struct ra6m4_uart_para_t
{
    sci_uart_instance_ctrl_t   *_uart;
    uint32_t                  channel;
   
    uint8_t   uart_recv_buff;
    uint8_t   uart_send_buff;
}ra6m4_uart_para_t;
ra6m4_uart_para_t    ra6m4_uart_p;

shell_uart_buffer_tg_shell_uart;

//RS485 CTRL GPIO
#define   RS485_DISABLE_UART_SEND(i)      //recv start status //TE485 =0;RE485=1;        //RS485,L发送关闭,H接收使能
#define   RS485_ENABLE_UART_SEND(i)       //send start status //TE485 =1;RE485=0;        //RS485,H发送使能,L接收使能


static void uart_get_data_send(uint8_t index)
{
    uint32_t    i;
    //
    for(i=0;i<128;i++)
    {
      if(g_shell_uart.tx.read_i != g_shell_uart.tx.write_i)
      {
            ((ra6m4_uart_para_t *)g_shell_uart.userdata)->uart_send_buff = g_shell_uart.tx.buff.tx.read_i++];
            g_shell_uart.tx.read_i &= (UART_FIFO_BUFF_LEN-1); //256Byte
      }else break;
    }
    if(i)
    {
      RS485_ENABLE_UART_SEND(index);
      g_shell_uart.tx_cpl = 1;
      //R_SCI_UART_Write(&g_uart0_ctrl, (uint8_t *)&ch, 1);
      R_SCI_UART_Write(((ra6m4_uart_para_t *)g_shell_uart.userdata)->_uart,
                         ((ra6m4_uart_para_t *)g_shell_uart.userdata)->uart_send_buff,i);
    }
}

uint8_t uart_flush_data(uint8_t index)
{
    if(g_shell_uart.tx_cpl == 0)
    {
      uart_get_data_send(index);
    }
    if(g_shell_uart.tx.read_i != g_shell_uart.tx.write_i) return 1;
    else return g_shell_uart.tx_cpl;
}


uint8_t uart_send_char(uint8_t index, uint8_t ch)
{
    while(((g_shell_uart.tx.write_i+1) & (UART_FIFO_BUFF_LEN-1)) == g_shell_uart.tx.read_i)
    {
      //fifo buffer full
      if(!(g_shell_uart.tx_cpl))
      {
            uart_get_data_send(index);
      }
    }
   
    g_shell_uart.tx.buff.tx.write_i++] = ch;
    g_shell_uart.tx.write_i &= (UART_FIFO_BUFF_LEN-1);//256Byte
   
    return uart_flush_data(index);
}

uint8_t uart_recv_char(uint8_t index, uint8_t *ch)
{
    if(g_shell_uart.rx.read_i != g_shell_uart.rx.write_i)
    {
      *ch = g_shell_uart.rx.buff.rx.read_i++];
      g_shell_uart.rx.read_i &= (UART_FIFO_BUFF_LEN-1); //256Byte
      return 0;
    }
    return 1;
}

int uart_send_str(uint8_t index, const char* str, uint32_t len)
{
    char *s= (char*)str;
    int sl = (int)len;
    while(len --)   uart_send_char(index, *s++);
    return sl;
}

int uart_recv_str(uint8_t index, const char* str, uint32_t len)
{
    uint8_t *s= (uint8_t *)str;
    int rlen = 0;
   
    for(uint32_t i=0;i<len;i++)
    {
      if(0 == uart_recv_char(index, &s))
      {
            rlen++;
      }
    }
    return rlen;
}

//////////////////////////////////////////////////////////////////////////////
//中断处理
void user_sci_uart9_isr_callback (uart_callback_args_t * p_args)
{
    if(p_args->event == UART_EVENT_TX_COMPLETE)
    {
      for(uint8_t i=0;i<UART_DEV_NUM;i++)
      {
            if(p_args->channel == ((ra6m4_uart_para_t *)g_shell_uart.userdata)->channel)   //shell
            {
                g_shell_uart.tx_cpl = 0;
                uart_get_data_send(i);
            }
      }
    }
   
    if(p_args->event == UART_EVENT_RX_CHAR)
    {
      for(int i=0;i<UART_DEV_NUM;i++)
      {
            if(p_args->channel == ((ra6m4_uart_para_t *)g_shell_uart.userdata)->channel)   //shell
            {
                if(((g_shell_uart.rx.write_i+1) & (UART_FIFO_BUFF_LEN-1)) != g_shell_uart.rx.read_i)
                {
                  g_shell_uart.rx.buff.rx.write_i++] = (uint8_t)p_args->data;
                  g_shell_uart.rx.write_i &= (UART_FIFO_BUFF_LEN-1);//256Byte
                }
                RS485_DISABLE_UART_SEND(i);            //recv start status
            }
      }
    }
}

extern int stdout_putchar (int ch);
#if __USE_EVENT_RECORDER__ == 0
int stdout_putchar (int ch)
{
    uart_send_char(UART_SHELL_DEV_INDEX, ch & 0xff);
    return ch;
}

int fputc(int ch,FILE *f)
{
    uart_send_char(UART_SHELL_DEV_INDEX, ch & 0xff);
    return ch;
}

#endif

uint8_t USART_PutChar(uint8_t ch)
{
    uart_send_char(UART_SHELL_DEV_INDEX, ch);
    return 0;
}

uint8_t USART_GetChar(uint8_t *ch)
{
    return uart_recv_char(UART_SHELL_DEV_INDEX, ch);
}


int USART_PutStr(const char* str, uint32_t len)
{
    char *s= (char*)str;
    int sl = (int)len;
    while(len --)   uart_send_char(UART_SHELL_DEV_INDEX, *s++);
    return sl;
}

int USART_GetStr(const char* str, uint32_t len)
{
    uint8_t *s= (uint8_t *)str;
    int rlen = 0;
   
    for(uint32_t i=0;i<len;i++)
    {
      if(0 == uart_recv_char(UART_SHELL_DEV_INDEX, &s))
      {
            rlen++;
      }
    }
    return rlen;
}


void shell_usart_init(void)
{
    ra6m4_uart_p._uart = &g_uart0_ctrl;
    ra6m4_uart_p.channel = 9;
   
    g_shell_uart.tx.read_i = 0;
    g_shell_uart.tx.write_i = 0;
    g_shell_uart.rx.read_i = 0;
    g_shell_uart.rx.write_i = 0;
    g_shell_uart.tx_cpl = 0;
    g_shell_uart.userdata = &ra6m4_uart_p;


#if __USE_EVENT_RECORDER__
    EventRecorderInitialize(0, 1);
#endif
   
   
#ifdef UART_SHELL
#if UART_SHELL == 1
    userShellInit(); //LETTER_SHELL
#elif UART_SHELL == 2
    shell_init();   //NR_MICRO_SHELL
#elif UART_SHELL == 3
    // 配置IO操作
    shell_io_ops_t io_ops = {
      .send    = USART_PutStr,
    };
    lsy_shell_init(&io_ops);   //LSY_SHELL
#else
   
#endif
#endif
    /* 启动非阻塞式读取接收数据 */
    for(int i=0;i<UART_DEV_NUM;i++)
    {
      RS485_DISABLE_UART_SEND(i);            //recv start status
      
    }
}


void shell_usart_loop(void)
{
    uint8_t ch;
   
    if(0 == uart_recv_char(UART_SHELL_DEV_INDEX, &ch))
    {
#ifdef UART_SHELL
      #if UART_SHELL == 1
            shellHandler(&shell, ch); //letter shell
      #elif UART_SHELL == 2
            shell(ch);
      #elif UART_SHELL == 3
            lsy_shell_input(ch);
      #else
            USART_PutChar(ch);
      #endif
#endif
    }
   
    //将串口FIFO内数据继续发送
    for(uint8_t i=0;i<UART_DEV_NUM;i++)
    {
      uart_flush_data(i);
    }
}
```

将串口输出重定向到printf输出。
!(https://www.eefocus.com/forum/data/attachment/forum/202608/05/234608gqag7mzgg07b3w7m.png)

继续添加nr_micro_shell代码,实现shell命令功能。
!(https://www.eefocus.com/forum/data/attachment/forum/202608/05/234751poo4vk9qukpe3zss.png)

最终编译下载就可以看到串口输出了。
!(https://www.eefocus.com/forum/data/attachment/forum/202608/05/234840iqacxwgikxc5viav.png)



页: [1]
查看完整版本: 【瑞萨RA-eco-RA6M4评测】实现串口发送接收shell