瑞萨单片机开发教程[二十七] DTC 外部中断触发传输实验

在这里插入图片描述

开发板官网(https://www.edevkit.com/)

本系列教程目录:
- 瑞萨单片机开发教程[一] e2-studio + DAP LINK开发环境搭建
- 瑞萨单片机开发教程[二] Keil/RASC开发环境搭建
- 瑞萨单片机开发教程[三] 新建RASC工程
- 瑞萨单片机开发教程[四] GPIO输出——led实验
- 瑞萨单片机开发教程[五] GPIO输入——按键key实验
- 瑞萨单片机开发教程[六] ICU外部中断实验
- 瑞萨单片机开发教程[七] SCI UART串口通信实验
- 瑞萨单片机开发教程[八] DMAC 串口数据传输实验
- 瑞萨单片机开发教程[九] ADC 电压采集实验


DTC 外部中断触发传输实验

本章目标:

  • 了解 RA6M5 处理器的 DTC 模块
  • 学会使用 RASC 配置 DTC 在指定内存间搬移数据

硬件设计(略,参见配套硬件原理图)

软件设计

新建工程

复制一份“07 SCI-UART_Recv_send”修改文件夹名“27 DTC_IRQ”,双击打开 EBF_RA6M5.uvprojx 工程,通过 Keil 的新建文件新建 dtc_irq.cdtc_irq.h 保存到工程目录下的 src 文件夹中。

FSP 配置

Keil 界面选择 “Tools”→“RA Smart Configurator” 打开 RASC 界面。

首先需要配置一个外部按键中断用于触发 DTC 的数据传输,参考外部按键中断实验。

在 FSP 配置界面里面点开 “Stacks” 界面,“New Stack”→“Transfer”→“r_dtc” 新建两个 DTC 模块。

添加后,点击模块,在左下角属性界面配置参数。

Name名字。 上图配置为 g_transfer_dtc
按照自己命名习惯设置、并且与代码中的对应即可。
Mode模式:DTC 传输模式选择。默认选择正常模式即可。
Transfer Size传输大小:传输数据单元的大小。默认设置为 2 字节即可。
Destination Address Mode目标地址模式:默认设置为固定。
Source Address Mode源地址模式:默认设置为固定。
Repeat Area
(Unused in Normal Mode)
重复区域(正常模式下不使用):源地址。
Destination Pointer目标指针:NULL(在这里不方便确定传输地址,后续在代码部分配置)。
Source Pointer源指针:NULL(在这里不方便确定传输地址,后续在代码部分配置)。
Interrupt Frequency中断频率(选择什么时候触发中断):
- 所有传输都完成后产生中断。
- 传输完每一个块或重复大小的数据时都产生中断。
Number of Transfers传输次数:指定正常和重复模式的传输次数。这里设置传输 1 次。
Number of Blocks
(Valid only in Block Mode)
块数量:指定要在块模式下传输的块数。
Activation Source触发源:选择用来激活 DTC 传输的事件。
注意 DTC 不可使用软件触发,这里我们选由 ICU IRQ9 触发。

配置完成之后可以按下快捷键 “Ctrl + S” 保存,最后点击 “Generate Project Content” 按钮,让软件自动生成配置代码即可。

程序设计

实现两个数组内存间数据传输,配置 DTC 的源地址和目标地址,通过按键中断触发 DTC 的传输,配置不同模式下的传输数据个数,打印每次的接收数据,观察数据。

  1. 打开 DTC 设备对象
fsp_err_t R_DTC_Open(transfer_ctrl_t * const p_ctrl, 
                   transfer_cfg_t const * const p_cfg);

p_ctrl:用来记录一些状态信息;

p_cfg:配置信息,实际上就是指向 RASC 生成的 g_dtc0_cfg 结构体;

  1. 关闭 DTC 设备对象
fsp_err_t R_DTC_Close(transfer_ctrl_t * const p_ctrl);

close 函数会将 DTC 设备对象的 open 标志位设置为 CLOSED,并且关闭中断。

  1. 使能 DTC 的数据传输
fsp_err_t R_DTC_Enable(transfer_ctrl_t * const p_ctrl);

程序编写

dtc_irq.h 头文件里定义初始化函数、设置数据地址函数和测试函数。

#ifndef __BSP_DTC_IRQ_H
#define __BSP_DTC_IRQ_H
#include "hal_data.h"

//(1)   //正常模式 
//(2)   //重复模式
//(3)   //块模式
#define DTC_TRANSFER_MODE 3        

// 用户要发送的数据大小
#define BUFFER_SIZE         32

void set_transfer_dst_src_address( transfer_cfg_t const * const p_config,
                                   void const * volatile p_src,
                                   void const * volatile p_dest );
void dtc_Init(void);
void dtc_transfer_test(void);
#endif

dtc_irq.c 里实现初始化函数、设置数据地址函数和测试函数。

#include "dtc_irq.h"
#include "led.h"
#include "key_irq.h"

/**
 * 定义 SRC_Buffer 数组作为 DMAC 传输数据源
 * const 关键字将 SRC_Buffer 数组变量定义为常量类型,数据存储在内部的FLASH中
 */
const uint32_t SRC_Buffer[BUFFER_SIZE] = {
                    0x01020304,0x05060708,0x090A0B0C,0x0D0E0F10,
                    0x11121314,0x15161718,0x191A1B1C,0x1D1E1F20,
                    0x21222324,0x25262728,0x292A2B2C,0x2D2E2F30,
                    0x31323334,0x35363738,0x393A3B3C,0x3D3E3F40,
                    0x41424344,0x45464748,0x494A4B4C,0x4D4E4F50,
                    0x51525354,0x55565758,0x595A5B5C,0x5D5E5F60,
                    0x61626364,0x65666768,0x696A6B6C,0x6D6E6F70,
                    0x71727374,0x75767778,0x797A7B7C,0x7D7E7F80 };
/**
 * 定义 DMAC 传输目标存储器
 * 存储在内部的SRAM中
 */
uint32_t DST_Buffer[BUFFER_SIZE] = {0};

#if DTC_TRANSFER_MODE == 1

/* 正常传输模式 */
transfer_info_t my_transfer_info_normal =
{
    .transfer_settings_word_b.dest_addr_mode = TRANSFER_ADDR_MODE_INCREMENTED,  //每次传输后,目标地址指针都会增加
    .transfer_settings_word_b.repeat_area    = TRANSFER_REPEAT_AREA_SOURCE,     //源区域重复 (正常模式下无效)
    .transfer_settings_word_b.irq            = TRANSFER_IRQ_END,                //传输完成后中断
    .transfer_settings_word_b.chain_mode     = TRANSFER_CHAIN_MODE_DISABLED,    //不使能(DMAC没有该功能,仅DTC有)
    .transfer_settings_word_b.src_addr_mode  = TRANSFER_ADDR_MODE_INCREMENTED,  //每次传输后,源地址指针都会增加
    .transfer_settings_word_b.size           = TRANSFER_SIZE_4_BYTE,            //每次传输4字节
    .transfer_settings_word_b.mode           = TRANSFER_MODE_NORMAL,            //正常传输模式
    .p_dest                                  = (void *) DST_Buffer,             //目标地址
    .p_src                                   = (void const *) SRC_Buffer,       //源地址
    .num_blocks = 0,  //指定传输的块数(正常模式和重复模式下均无效,仅块模式下有效)
    .length     = 8,  //指定传输的长度(即正常和重复模式下的传输次数 或 块和重复-块模式下传输的块大小)
};


#elif DTC_TRANSFER_MODE == 2

/* 重复传输模式 */
transfer_info_t my_transfer_info_repeat =
{
    .transfer_settings_word_b.dest_addr_mode = TRANSFER_ADDR_MODE_INCREMENTED,  //每次传输后,目标地址指针都会增加
    .transfer_settings_word_b.repeat_area    = TRANSFER_REPEAT_AREA_SOURCE,     //源区域重复 (正常模式下无效)
    .transfer_settings_word_b.irq            = TRANSFER_IRQ_EACH,                //传输完成后中断
    .transfer_settings_word_b.chain_mode     = TRANSFER_CHAIN_MODE_DISABLED,    //不使能(DMAC没有该功能,仅DTC有)
    .transfer_settings_word_b.src_addr_mode  = TRANSFER_ADDR_MODE_INCREMENTED,  //每次传输后,源地址指针都会增加
    .transfer_settings_word_b.size           = TRANSFER_SIZE_4_BYTE,            //每次传输4字节
    .transfer_settings_word_b.mode           = TRANSFER_MODE_REPEAT,            //重复传输模式
    .p_dest                                  = (void *) DST_Buffer,             //目标地址
    .p_src                                   = (void const *) SRC_Buffer,       //源地址
    .num_blocks = 0,  //指定传输的块数(正常模式和重复模式下均无效,仅块模式下有效)
    .length     = 2,  //指定传输的长度(即正常的传输次数或重复模式下重复大小 或 块和重复-块模式下传输的块大小)
};


#elif DTC_TRANSFER_MODE == 3

/* 块传输模式 */
transfer_info_t my_transfer_info_block =
{
    .transfer_settings_word_b.dest_addr_mode = TRANSFER_ADDR_MODE_INCREMENTED,  //每次传输后,目标地址指针都会增加
    .transfer_settings_word_b.repeat_area    = TRANSFER_REPEAT_AREA_SOURCE,     //源区域重复 (正常模式下无效)
    .transfer_settings_word_b.irq            = TRANSFER_IRQ_END,                //传输完成后中断
    .transfer_settings_word_b.chain_mode     = TRANSFER_CHAIN_MODE_DISABLED,    //不使能(DMAC没有该功能,仅DTC有)
    .transfer_settings_word_b.src_addr_mode  = TRANSFER_ADDR_MODE_INCREMENTED,  //每次传输后,源地址指针都会增加
    .transfer_settings_word_b.size           = TRANSFER_SIZE_4_BYTE,            //每次传输4字节
    .transfer_settings_word_b.mode           = TRANSFER_MODE_BLOCK,             //块传输模式
    .p_dest                                  = (void *) DST_Buffer,             //目标地址
    .p_src                                   = (void const *) SRC_Buffer,       //源地址
    .num_blocks = 1,            //指定传输的块数(正常模式下无效,仅在重复、块或重复-块模式下有效)
    .length     = 16,            //指定传输的长度(即正常的传输次数或重复模式下重复大小 或 块和重复-块模式下传输的块大小)
};


#endif


//设置传输的源地址和目的地址
void set_transfer_dst_src_address( transfer_cfg_t const * const p_config,
                                   void const * volatile p_src,
                                   void const * volatile p_dest )
{
    p_config->p_info->p_src = (void *) p_src;
    p_config->p_info->p_dest = (void *) p_dest;
}


//DMAC 初始化函数
void dtc_Init(void)
{
    fsp_err_t err;

        //设置传输的源地址和目的地址
    //set_transfer_dst_src_address(&g_transfer0_dtc0_cfg, SRC_Buffer, DST_Buffer);

    //打开 DMAC 模块
    err = R_DTC_Open(&g_transfer0_dtc0_ctrl, &g_transfer0_dtc0_cfg);
    assert(FSP_SUCCESS == err);

#if (DTC_TRANSFER_MODE == 1)   //正常模式
    err = R_DTC_Reconfigure(&g_transfer0_dtc0_ctrl, &my_transfer_info_normal);
    assert(FSP_SUCCESS == err);

#elif (DTC_TRANSFER_MODE == 2) //重复模式
    err = R_DTC_Reconfigure(&g_transfer0_dtc0_ctrl, &my_transfer_info_repeat);
    assert(FSP_SUCCESS == err);

#elif (DTC_TRANSFER_MODE == 3) //块模式
    err = R_DTC_Reconfigure(&g_transfer0_dtc0_ctrl, &my_transfer_info_block);
    assert(FSP_SUCCESS == err);
#endif 

        //使能 DMAC
        err = R_DTC_Enable(&g_transfer0_dtc0_ctrl);
        assert(FSP_SUCCESS == err);

}

//打印缓冲区数据:十六进制格式
void BufferShow_HexData(const uint32_t *pBuffer, uint16_t BufferLength)
{
    while(BufferLength)
    {
        if((BufferLength % 4) == 0)
            printf("\r\n\t");

        printf("0x%08X ", (unsigned int)*pBuffer);

        pBuffer++;
        BufferLength--;
    }

    printf("\r\n");
}

void dtc_transfer_test(void)
{

    printf("\r\nthe source data:");
  BufferShow_HexData(SRC_Buffer, BUFFER_SIZE);

    while(1)
    {
        //等待中断
        printf("wait key irq\r\n");
        while (false == key1_press);
        key1_press = false;

        LED1_TOGGLE();
        R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS); 

        printf("\r\nDST:recv"); 
        BufferShow_HexData(DST_Buffer, BUFFER_SIZE);

    }
}

hal_entry.c 文件中添加头文件 dtc_irq.h

void hal_entry(void)
{
    /* TODO: add your own code here */

    led_Init(); // LED 初始化
  uart0_Init();

    dtc_Init();
    key_IRQ_Init();

    printf("start dmac test\r\n");

    dtc_transfer_test();

    while(1)
    {
        LED1_TOGGLE();
        R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_SECONDS); //延时1秒
    }


#if BSP_TZ_SECURE_BUILD
    /* Enter non-secure code */
    R_BSP_NonSecureEnter();
#endif
}

下载验证

连接下载器,将程序编译并下载到开发板之后,按下复位按键来复位开发板,程序启动初始化完。

正常模式发送和接收的数据都相同。

修改 DTC_TRANSFER_MODE = 2 重复模式下查看数据,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

csdn杰哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值