瑞萨RA6M4——串口DMA接收与DTC发送不定长数据

最近在开发瑞萨RA6M4单片机发现瑞萨系列不像ST系列方便配置串口空闲中断,在浏览大量资料与求助FAE实现了瑞萨串口DMA接受、DTC发送不定长数据的技术。鉴于互联网上相关技术帖较少,遂拿出与大家分享,一起进步,共同维护RA生态!

声明:一切权利归本人发帖所在公司所有,技术仅做交流使用,禁止商业行为!!!

配置部分

1. 使用瑞萨图形化配置串口

本例使用串口8,增加发送DTC配置,是能FIFO模式;

2.配置DMA接受

DMA接受是外设->内存,所以目标地址选择递增,触发方式串口的发送

3.配置DMA接受超时中断(空闲中断)

配置定时器的触发源为串口8的接受信号,原理:串口发送的时候一直触发/刷新定时器的计数值使其不超时,当发送完成时就停止刷新,超过设定时间(本例10ms)就会触发定时器中断。

4.配置elc

开启事件连接配置

代码实现

5.初始化串口、打开ELC、开启定时器


		// open uart8
		board_uart_open(BOARD_UART8);
		R_IOPORT_PinWrite(&g_ioport_ctrl,BSP_IO_PORT_01_PIN_06, BSP_IO_LEVEL_LOW);
		
		R_ELC_Open(&g_elc_ctrl,&g_elc_cfg);
		R_ELC_Enable(&g_elc_ctrl);
		dmac_open(DMAC_UART8_RX);

	    R_GPT_Open(&g_timer_uart8_idle_ctrl, &g_timer_uart8_idle_cfg);
	    R_GPT_Enable(&g_timer_uart8_idle_ctrl);	

6.dma初始化,开启fifo要注意这里重新指向的源地址FRDRL

typedef struct{
    uart_type utype;
    dmac_type dtype;
    const bsp_io_port_pin_t dir_pin;
    transfer_ctrl_t *p_ctrl;
    const transfer_cfg_t *p_cfg;
    const volatile uint8_t * p_dest;
    const  volatile uint8_t * p_src;
    uint16_t p_len;
    volatile uint8_t * my_irq;
    volatile bool* send_complete_flag;
}board_dmac_ctrl_t;

typedef struct{
    timer_type type;
    transfer_ctrl_t *p_ctrl;
    // const timer_cfg_t *p_cfg;
    //const bsp_io_port_pin_t dir_pin;
    bool* recv_complete_flag;
   // uint8_t *recv_buf;
    uint32_t recv_buflen;
    volatile uint32_t* uart_recv_idx;
    volatile uint32_t* uart_recv_head;
}board_timer_ctrl_t;

typedef enum{
    DMAC_UART4_RX = 0,
    DMAC_UART4_TX,
    DMAC_UART8_RX,
    DMAC_UART8_TX,
    DMAC_SPI0_RX,
    DMAC_SPO0_TX,
}dmac_no;

board_timer_ctrl_t board_timer_ctrl[] = 
{
	{UART, &g_transfer_uart4_dmac_rx_ctrl, &uart_recv_complete_flag[BOARD_UART4], UART_RCVBUF_LEN, &recv_idx[BOARD_UART4], &recv_head[BOARD_UART4]},
	{UART, &g_transfer_uart8_dmac_rx_ctrl, &uart_recv_complete_flag[BOARD_UART8], UART_RCVBUF_LEN, &recv_idx[BOARD_UART8], &recv_head[BOARD_UART8]},
};
transfer_properties_t dmainfo;

board_dmac_ctrl_t board_dmac_ctrl[] =
{
	 {RS485,UART_RX,BSP_IO_PORT_02_PIN_05,
	  &g_transfer_uart4_dmac_rx_ctrl,&g_transfer_uart4_dmac_rx_cfg,uart_receive_buffers[BOARD_UART4],
	  &R_SCI4->FRDRL,sizeof(uart_receive_buffers[BOARD_UART4]),NULL,NULL,
	 },
	 
	 {RS485,UART_TX,BSP_IO_PORT_02_PIN_05,
	  &g_transfer_uart4_dmac_tx_ctrl,&g_transfer_uart4_dmac_tx_cfg,&R_SCI4->FTDRL,
	  NULL,0,&R_SCI4->SSR,&uart_send_complete_flag[BOARD_UART4],    //FTDRL
	 },
	 
	 {RS485,UART_RX,BSP_IO_PORT_01_PIN_06,
	  &g_transfer_uart8_dmac_rx_ctrl,&g_transfer_uart8_dmac_rx_cfg,uart_receive_buffers[BOARD_UART8],
	  &R_SCI8->FRDRL,sizeof(uart_receive_buffers[BOARD_UART8]),NULL,NULL,
	 },
	 
	 {RS485,UART_TX,BSP_IO_PORT_01_PIN_06,
	  &g_transfer_uart8_dmac_tx_ctrl,&g_transfer_uart8_dmac_tx_cfg,&R_SCI8->TDR,
	  NULL,0,&R_SCI8->SSR,&uart_send_complete_flag[BOARD_UART8],
	 },
};
void dmac_open(dmac_no port)
{
    fsp_err_t err = FSP_SUCCESS;
    if(board_dmac_ctrl[port].dtype == UART_RX)
    {
        board_dmac_ctrl[port].p_cfg->p_info->p_dest  =  (void * volatile)board_dmac_ctrl[port].p_dest;
        board_dmac_ctrl[port].p_cfg->p_info->p_src   =  (void const * volatile)board_dmac_ctrl[port].p_src;
        board_dmac_ctrl[port].p_cfg->p_info->length  =  board_dmac_ctrl[port].p_len;
        err = R_DMAC_Open(board_dmac_ctrl[port].p_ctrl, board_dmac_ctrl[port].p_cfg);
        assert(FSP_SUCCESS == err);
        err = R_DMAC_Enable(board_dmac_ctrl[port].p_ctrl);
        assert(FSP_SUCCESS == err);
    }
    else
    {
        board_dmac_ctrl[port].p_cfg->p_info->p_dest = (void * volatile)board_dmac_ctrl[port].p_dest;
        err = R_DMAC_Open(board_dmac_ctrl[port].p_ctrl, board_dmac_ctrl[port].p_cfg);
        assert(FSP_SUCCESS == err);
    }
}
void dmac_reset(dmac_no port)
{
//	FSP_PARAMETER_NOT_USED (port);
	dmac_close(port);
	dmac_open(port);
}

7.接受处理函数

/*******************************************************************************************************************//**
 * @brief      g_timer_uart8_idle_callback
 *
 * @param[in]  timer_callback_args_t  Callback function parameter data
 * @retval     None
 **********************************************************************************************************************/
void g_timer_uart8_idle_callback(timer_callback_args_t *p_args)
{
    (void)p_args;
    g_timer_uart_idle_process(TIME_UART8);
	board_uart_put(BOARD_UART8, uart_receive_buffers[BOARD_UART8], *board_timer_ctrl[TIME_UART8].uart_recv_idx);
	dmac_reset(DMAC_UART8_RX);
}

/*******************************************************************************************************************//**
 * @brief      g_timer_uart_idle_process
 *
 * @param[in]  timer_callback_args_t  Callback function parameter data
 * @retval     None
 **********************************************************************************************************************/
void g_timer_uart_idle_process(timer_to_uart port)
{
    R_DMAC_InfoGet(board_timer_ctrl[port].p_ctrl,&dmainfo);
    *board_timer_ctrl[port].uart_recv_idx = board_timer_ctrl[port].recv_buflen - dmainfo.transfer_length_remaining;
    *board_timer_ctrl[port].recv_complete_flag = true;
}

至此完成DMA方式接受不定长数据,DTC方式发送。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值