基于瑞萨RL78F24的UART的DTC实战配置教程

**前言:**RL78F24作为一款瑞萨的经典车规级应用的16bit的MCU,以其超低功耗而闻名。当有大量高频数据发送或接受的应用场景时,就需要用到其DTC,不同于32bitMCU的DMA,DTC属于轻量级的数据传输控制器。本篇博客就详细的介绍一下当有高频UART数据传输需求的时候,使用DTC的应用案例。


1,应用背景

使用两个UART,一个只负责接收数据,一个只负责发送数据。并且两者都使用对应的DTC进行数据的搬运以减轻CPU的负担。

使用的MCU与IDE工具

MCU:R7F124FGJ(48PIN、256KB Flash、24KB RAM)

CS+ for CC V8.13.00 [05 Dec 2024]

Renesas Smart Configurator for RL78 Version: 1.13.0

2,资源介绍

当然,要配置RL78F24的UART的DTC,我们首先得了解一下这款MCU的基本外设分布情况

此款MCU有两路UART,DTC有44种触发源可供选择,最多有38个IO口资源可供使用。并且DTC最多可以配置24通道。

3,实现原理

分别配置两个DTC为UART0发送结束触发和UART1接收完成触发,当对应的发送与接收数据缓冲寄存器被填充的时候触发DTC,DTC再将源地址的数据搬运到目标地址上面。宏观来看,对于UART的发送接收而言,其触发源为发送传输结束与接收传输结束。

由于DTC控制器可以直接访问RAM与外设寄存器,并且和CPU共享系统总线,其直接做了原本属于CPU要做的事情,所以在DTC承担数据搬运任务的时候,CPU也就是MCU的内核就可以腾出手来完成其他的更为重要的任务。所以加上DTC的UART无论发送接收多大的数据量都不会影响CPU的负载率。

RL78 DTC 特点

▪ 单次外设自动搬运

▪ 一般不支持内存 ↔ 内存

▪ 没有复杂链表

▪ 只在事件触发下执行

RL78 DTC 与 RH850 DMA的对比

Aspect RH850 DMA RL78 DTC
通道数量 多(具体看型号,如 8/12/16 通道) 少(通常 1~4 通道)
内存访问宽度 支持 8/16/32/64 位甚至更大块 一般 8/16/32 位
内存 ↔ 内存 支持 ✔ 支持 ✘ 通常不支持
外设 ↔ 内存 支持 ✔ 强 ✔ 支持(受限触发)
触发源数量 多路 主要外设中断触发

4,smart configurator配置

调整串口的时钟,使得波特率调为19200,数据长度为8位

UART0从mcu发送数据到上位机,因此DTCD0的激活源设置为UART0发送传输结束

UART1从上位机发送数据到MCU,因此DTCD1的激活源设置为UART1接收传输结束

UART0的缓存寄存器为SDR00,地址为0xFF10

UART1的缓存寄存器为SDR11,地址为0xFF4A

UART0的TXD0为P15管脚

UART1的RXD1为P11管脚

UART配置

DTC配置

以上配置的是normal模式的时候,DTC搬运一次数据之后就会将计数值归零,要再次搬运就是需要重新设置地址与传输的数据大小。当设置成repeat模式的时候,再次传输的时候可以不用再重载设置地址与传输数据大小,除了对应的Repeat area setting项对应选择的地址的首8BIT是00之外,其他的均不变,不需要再次重载。

全部配置完成之后直接生成代码即可。

5,代码实现

定义数组buf:

UART0_tx_buf为通过UART0从MCU发送到上位机的数据,首地址为0xf9f0a

UART1_rx_buf为通过UART1 MCU接收到上位机的数据,首地址为0xf9f12

以下代码可以实现环形接收UART的数据,并且可以周期性的发送UART数据。

main.c

cpp 复制代码
#include "r_cg_macrodriver.h"
#include "r_cg_userdefine.h"
#include "Config_DTC.h"
#include "Config_UART0.h"
#include "Config_UART1.h"
#include "Config_TAU0_1.h"

uint8_t UART0_tx_buf[8]={0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88};

uint8_t UART1_rx_buf[8]={0x00};

extern uint8_t t;

void main(void);

void main(void)
{
	__DI();
	R_Config_UART0_Start();//TXD0:P15
	R_Config_UART1_Start();//RXD1:P11
	R_Config_TAU0_1_Start();
		
	R_DTCD0_Start();
	R_DTCD1_Start();
	
	__EI();
	
	/* DTC UART0 TX Trigger */ 
	SDR00 = UART0_tx_buf[0];

	/* DTC UART1 RX Trigger */ 
	UART1_rx_buf[0] = SDR11;
	
	while(1)
	{
		if(t > 10)
		{
			/* DTC UART0 Continue Sent*/
			user_DTC_UART0TX_reload();
			SDR00 = UART0_tx_buf[0];
			
			t = 0;
		}
	}
}

Config_DTC.c

cpp 复制代码
#include "r_cg_macrodriver.h"
#include "r_cg_userdefine.h"
#include "Config_DTC.h"
/* Start user code for include. Do not edit comment generated here */
/* End user code. Do not edit comment generated here */

/***********************************************************************************************************************
Pragma directive
***********************************************************************************************************************/
/* Start user code for pragma. Do not edit comment generated here */
/* End user code. Do not edit comment generated here */

/***********************************************************************************************************************
Global variables and functions
***********************************************************************************************************************/
/* Start user code for global. Do not edit comment generated here */
extern uint8_t UART0_tx_buf[8];
/* End user code. Do not edit comment generated here */
#pragma address dtc_vectortable = 0x0FFD00U
uint8_t __near dtc_vectortable[46U];

#pragma address dtc_controldata_0 = 0x0FFD40U
st_dtc_data_t __near dtc_controldata_0;

#pragma address dtc_controldata_1 = 0x0FFD48U
st_dtc_data_t __near dtc_controldata_1;

/***********************************************************************************************************************
* Function Name: R_Config_DTC_Create
* Description  : This function initializes the DTC module.
* Arguments    : None
* Return Value : None
***********************************************************************************************************************/
void R_Config_DTC_Create(void)
{
    /* Enable input clock supply */
    DTCEN = 1U;
    /* Disable all DTC channels operation */
    DTCEN0 = 0x00U;
    DTCEN1 = 0x00U;
    DTCEN2 = 0x00U;
    DTCEN3 = 0x00U;
    DTCEN4 = 0x00U;
    DTCEN5 = 0x00U;
    /* Set base address */
    DTCBAR = 0xFDU;
    /* Set DTCD0 */
    dtc_vectortable[11U] = 0x40U;
    dtc_controldata_0.dtccr = _00_DTC_DATA_SIZE_8BITS | _00_DTC_CHAIN_TRANSFER_DISABLE | _00_DTC_DEST_ADDR_FIXED | 
                              _04_DTC_SOURCE_ADDR_INCREMENTED | _00_DTC_TRANSFER_MODE_NORMAL;
    dtc_controldata_0.dtbls = _01_DTCD0_TRANSFER_BLOCKSIZE;
    dtc_controldata_0.dtcct = _08_DTCD0_TRANSFER_BYTE;
    dtc_controldata_0.dtrld = 0x00U;
    dtc_controldata_0.dtsar = _9F0A_DTCD0_SRC_ADDRESS;
    dtc_controldata_0.dtdar = _FF10_DTCD0_DEST_ADDRESS;
    /* Set DTCD1 */
    dtc_vectortable[12U] = 0x48U;
    dtc_controldata_1.dtccr = _00_DTC_DATA_SIZE_8BITS | _00_DTC_CHAIN_TRANSFER_DISABLE | 
                              _08_DTC_DEST_ADDR_INCREMENTED | _00_DTC_SOURCE_ADDR_FIXED | _00_DTC_TRANSFER_MODE_NORMAL;
    dtc_controldata_1.dtbls = _01_DTCD1_TRANSFER_BLOCKSIZE;
    dtc_controldata_1.dtcct = _08_DTCD1_TRANSFER_BYTE;
    dtc_controldata_1.dtrld = 0x00U;
    dtc_controldata_1.dtsar = _FF4A_DTCD1_SRC_ADDRESS;
    dtc_controldata_1.dtdar = _9F12_DTCD1_DEST_ADDRESS;
    /* Set DTCH0 */
    SELHS0 = 0x24U;
    HDTCCR0 = _00_DTC_DATA_SIZE_8BITS | _00_DTC_CHAIN_TRANSFER_DISABLE | _00_DTC_DEST_ADDR_FIXED | 
              _00_DTC_SOURCE_ADDR_FIXED | _00_DTC_TRANSFER_MODE_NORMAL;
    HDTCCT0 = _01_DTCH0_TRANSFER_BYTE;
    HDTRLD0 = 0x00U;
    HDTSAR0 = _0000_DTCH0_SRC_ADDRESS;
    HDTDAR0 = _0000_DTCH0_DEST_ADDRESS;

    R_Config_DTC_Create_UserInit();
}

/***********************************************************************************************************************
* Function Name: R_DTCD0_Start
* Description  : This function starts DTCD0 module operation.
* Arguments    : None
* Return Value : None
***********************************************************************************************************************/
void R_DTCD0_Start(void)
{
    DTCEN1 |= _10_DTC_UART0T_ACTIVATION_ENABLE;
}

/***********************************************************************************************************************
* Function Name: R_DTCD0_Stop
* Description  : This function stops DTCD0 module operation.
* Arguments    : None
* Return Value : None
***********************************************************************************************************************/
void R_DTCD0_Stop(void)
{
    DTCEN1 &= (uint8_t)~_10_DTC_UART0T_ACTIVATION_ENABLE;
}

/***********************************************************************************************************************
* Function Name: R_DTCD1_Start
* Description  : This function starts DTCD1 module operation.
* Arguments    : None
* Return Value : None
***********************************************************************************************************************/
void R_DTCD1_Start(void)
{
    DTCEN1 |= _08_DTC_UART1R_ACTIVATION_ENABLE;
}

/***********************************************************************************************************************
* Function Name: R_DTCD1_Stop
* Description  : This function stops DTCD1 module operation.
* Arguments    : None
* Return Value : None
***********************************************************************************************************************/
void R_DTCD1_Stop(void)
{
    DTCEN1 &= (uint8_t)~_08_DTC_UART1R_ACTIVATION_ENABLE;
}

/***********************************************************************************************************************
* Function Name: R_DTCH0_Start
* Description  : This function starts DTCH0 module operation.
* Arguments    : None
* Return Value : None
***********************************************************************************************************************/
void R_DTCH0_Start(void)
{
    DTCEN4 |= _08_DTC_TAU10_ACTIVATION_ENABLE;
}

/***********************************************************************************************************************
* Function Name: R_DTCH0_Stop
* Description  : This function stops DTCH0 module operation.
* Arguments    : None
* Return Value : None
***********************************************************************************************************************/
void R_DTCH0_Stop(void)
{
    DTCEN4 &= (uint8_t)~_08_DTC_TAU10_ACTIVATION_ENABLE;
}

/* Start user code for adding. Do not edit comment generated here */
void user_DTC_UART0TX_reload(void)
{
    R_DTCD0_Start();
    /* Set DTCD0 */
    dtc_controldata_0.dtbls = _01_DTCD0_TRANSFER_BLOCKSIZE;
    dtc_controldata_0.dtcct = _08_DTCD0_TRANSFER_BYTE;
    dtc_controldata_0.dtsar = _9F0A_DTCD0_SRC_ADDRESS;
    dtc_controldata_0.dtdar = _FF10_DTCD0_DEST_ADDRESS;
}

void user_DTC_UART1RX_reload(void)
{
    R_DTCD1_Start();
    /* Set DTCD1 */
    dtc_controldata_1.dtbls = _01_DTCD1_TRANSFER_BLOCKSIZE;
    dtc_controldata_1.dtcct = _08_DTCD1_TRANSFER_BYTE;
    dtc_controldata_1.dtsar = _FF4A_DTCD1_SRC_ADDRESS;
    dtc_controldata_1.dtdar = _9F12_DTCD1_DEST_ADDRESS;
}

/* End user code. Do not edit comment generated here */

Config_UART1_user.c

cpp 复制代码
#include "r_cg_macrodriver.h"
#include "r_cg_userdefine.h"
#include "Config_UART1.h"
/* Start user code for include. Do not edit comment generated here */
/* End user code. Do not edit comment generated here */

/***********************************************************************************************************************
Pragma directive
***********************************************************************************************************************/
#pragma interrupt r_Config_UART1_interrupt_receive(vect=INTSR1)
/* Start user code for pragma. Do not edit comment generated here */
/* End user code. Do not edit comment generated here */

/***********************************************************************************************************************
Global variables and functions
***********************************************************************************************************************/
extern volatile uint8_t * gp_uart1_rx_address;    /* uart1 receive buffer address */
extern volatile uint16_t g_uart1_rx_count;        /* uart1 receive data number */
extern uint16_t g_uart1_rx_length;                /* uart1 receive data length */
/* Start user code for global. Do not edit comment generated here */
/* End user code. Do not edit comment generated here */

/***********************************************************************************************************************
* Function Name: R_Config_UART1_Create_UserInit
* Description  : This function adds user code after initializing UART1.
* Arguments    : None
* Return Value : None
***********************************************************************************************************************/
void R_Config_UART1_Create_UserInit(void)
{
    /* Start user code for user init. Do not edit comment generated here */
    /* End user code. Do not edit comment generated here */
}

/***********************************************************************************************************************
* Function Name: r_Config_UART1_callback_receiveend
* Description  : This function is a callback function when UART1 finishes reception.
* Arguments    : None
* Return Value : None
***********************************************************************************************************************/
static void r_Config_UART1_callback_receiveend(void)
{
    /* Start user code for r_Config_UART1_callback_receiveend. Do not edit comment generated here */
    /* End user code. Do not edit comment generated here */
}

/***********************************************************************************************************************
* Function Name: r_Config_UART1_callback_error
* Description  : This function is a callback function when UART1 reception error occurs.
* Arguments    : err_type -
*                    error type info
* Return Value : None
***********************************************************************************************************************/
static void r_Config_UART1_callback_error(uint8_t err_type)
{
    /* Start user code for r_Config_UART1_callback_error. Do not edit comment generated here */
    /* End user code. Do not edit comment generated here */
}

/***********************************************************************************************************************
* Function Name: r_Config_UART1_callback_softwareoverrun
* Description  : This function is a callback when UART1 receives an overflow data.
* Arguments    : rx_data -
*                    receive data
* Return Value : None
***********************************************************************************************************************/
static void r_Config_UART1_callback_softwareoverrun(uint16_t rx_data)
{
    /* Start user code for r_Config_UART1_callback_softwareoverrun. Do not edit comment generated here */
    // DTC continue RX TEST
    user_DTC_UART1RX_reload();
    /* End user code. Do not edit comment generated here */
}

/***********************************************************************************************************************
* Function Name: r_Config_UART1_interrupt_receive
* Description  : This function is UART1 receive interrupt service routine.
* Arguments    : None
* Return Value : None
***********************************************************************************************************************/
static void __near r_Config_UART1_interrupt_receive(void)
{
    uint8_t rx_data;
    uint8_t err_type;

    err_type = (uint8_t)(SSR11 & 0x0007U);
    SIR11 = (uint16_t)err_type;

    if (0U != err_type)
    {
        r_Config_UART1_callback_error(err_type);
    }

    rx_data = SDR11L;

    if (g_uart1_rx_length > g_uart1_rx_count)
    {
        *gp_uart1_rx_address = rx_data;
        gp_uart1_rx_address++;
        g_uart1_rx_count++;

        if (g_uart1_rx_length == g_uart1_rx_count)
        {
            r_Config_UART1_callback_receiveend();
        }
    }
    else
    {
        r_Config_UART1_callback_softwareoverrun(rx_data);
    }
}

/* Start user code for adding. Do not edit comment generated here */
/* End user code. Do not edit comment generated here */

6,功能测试

无论是UART0的数据接收还是UART1的数据发送经过重加载之后均可以重复发送或者接收数据。

相关推荐
YJlio13 小时前
1.7 通过 Sysinternals Live 在线运行工具:不下载也能用的“云端工具箱”
c语言·网络·python·数码相机·ios·django·iphone
不做无法实现的梦~15 小时前
ros2实现路径规划---nav2部分
linux·stm32·嵌入式硬件·机器人·自动驾驶
Lbs_gemini060319 小时前
01-01-01 C++编程知识 C++入门 工具安装
c语言·开发语言·c++·学习·算法
熊猫_豆豆20 小时前
同步整流 Buck 降压变换器
单片机·嵌入式硬件·matlab
shihui200321 小时前
两个8*8点阵流水屏
c语言·51单片机·proteus
ghx_echo21 小时前
c/c++结构体对齐,extern “C”与关键字const
c语言·c++
IvanCodes1 天前
五、C语言数组
c语言·开发语言
chenchen000000001 天前
49元能否买到四核性能?HZ-RK3506G2_MiniEVM开发板评测:MCU+三核CPU带来的超高性价比
单片机·嵌入式硬件
雪域迷影1 天前
MacOS下源码安装SDL3并运行hello.c示例程序
c语言·开发语言·macos·sdl3
孤芳剑影1 天前
反馈环路设计总结
嵌入式硬件·学习