【瑞萨RA_FSP】DMAC/DTC编程实战

news2024/11/27 12:26:01

文章目录

  • 一、DMAC存储器到存储器传输
  • 二、DTC外部中断触发传输


一、DMAC存储器到存储器传输

1. FSP配置
打开该工程的 FSP 配置界面。然后按如图步骤加入 DMAC。
在这里插入图片描述
加入 DMAC 后如下图所示。
在这里插入图片描述
单击上图中新添加的 r_dmac 框,然后在左下角的“属性”窗口配置 DMAC 模块的各个属性参数。 按照如下图所示来配置即可。

在这里插入图片描述
在上图中,实际上只需配置框中的那部分属性,其他的属性均按照默认即可。

DMAC 的配置项(与上图相对应):

在这里插入图片描述

2. 定义传输源和目标存储器
首先,要使用 DMA 传输,就肯定要有一个源地址和一个目标地址, 这里定义 SRC_Buffer 数组的首地址作为源地址, DST_Buffer 数组的首地址作为DMAC传输的目标地址。 SRC_Buffer 数组由于有 const 声明为常量,因此其数据存储在内部 Flash 中, DST_Buffer 为普通的全局变量,其数据存储在 RAM 中。这两个数组的大小由宏定义 BUFFER_SIZE 来决定。

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

 /**
 * 定义 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};

3. 设置源地址和目标地址函数
DMAC 传输的配置,可以选择在 FSP 配置界面中进行配置, 但是要注意,在 FSP 配置界面中进行配置的话是不方便配置传输地址的, 所以此时我们其实还没有配置传输的源地址和目标地址,这部分需要在代码里面配置。

 /* 设置传输的源地址和目的地址 */
 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;
 }

4. 使用FSP配置器生成的配置
前面在 FSP 配置界面上的配置其实是保存在 hal_data.c 文件中。如下图所示。
在这里插入图片描述
完全可以在 hal_data.c 文件中找到定义好的数据,重新复制一份,再改个变量名,在此基础上重新配置各个参数。 为了使用宏去方便切换不同模式的配置代码,在代码中配置 DMAC。 在头文件 “bsp_dmac_m2m.h” 中,默认定义了宏 USE_MY_TRANSFER_INFOR_CONFIG 来选择 使用在代码里自定义的传输信息配置,但是现在让先注释掉这个宏定义,从而选择使用在 FSP 配置界面上的配置。

下面的是与之前在 FSP 配置界面上的配置等效的配置代码:

 /* FSP配置界面的传输信息配置(正常传输模式)等效于下面 fsp_transfer_info_normal 里的配置(除了源地址和目标地址)
   源地址和目标地址在FSP配置界面设置的话不太方便,我们会在 DMAC_Init 函数里设置。
   关于偏移值(Offset value)和源缓冲大小(Source Buffer Size),在 transfer_info_t 里没有这两项设置,建议在FSP配置界面设置
   - 偏移值只有在地址模式是偏移模式的情况下才会用到;
   - 而源缓冲大小与之相关的功能本例程不会涉及到,所以暂不考虑。
   下面的 fsp_transfer_info_normal 仅作为对比参考,在本例程中是没有用到的。
 */
 //transfer_info_t fsp_transfer_info_normal =
 //{
 //    .transfer_settings_word_b.dest_addr_mode = TRANSFER_ADDR_MODE_FIXED,        //每次传输后,目标地址指针固定不变
 //    .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_FIXED,        //每次传输后,源地址指针固定不变
 //    .transfer_settings_word_b.size           = TRANSFER_SIZE_2_BYTE,            //每次传输2字节
 //    .transfer_settings_word_b.mode           = TRANSFER_MODE_NORMAL,            //正常传输模式
 //    .p_dest                                  = (void *) DST_Buffer,             //目标地址
 //    .p_src                                   = (void const *) SRC_Buffer,       //源地址
 //    .num_blocks = 0,            //指定传输的块数(正常模式下无效,仅在重复、块或重复-块模式下有效)
 //    .length     = 1,            //指定传输的长度(即正常和重复模式下的传输次数 或 块和重复-块模式下传输的块大小)
 //};
 // 按照上述传输信息配置,期待的正确传输结果为:
 uint32_t Expected_DST_Buffer[BUFFER_SIZE] = {
                     0x00000304,0x00000000,0x00000000,0x00000000,
                     0x00000000,0x00000000,0x00000000,0x00000000,
                     0x00000000,0x00000000,0x00000000,0x00000000,
                     0x00000000,0x00000000,0x00000000,0x00000000,
                     0x00000000,0x00000000,0x00000000,0x00000000,
                     0x00000000,0x00000000,0x00000000,0x00000000,
                     0x00000000,0x00000000,0x00000000,0x00000000,
                     0x00000000,0x00000000,0x00000000,0x00000000 };

可以看到,上述代码中的传输信息结构体变量 fsp_transfer_info_normal 被完全注释掉了。

需要用到的是 Expected_DST_Buffer 数组, 其中保存的数据是根据源数据 SRC_Buffer 和当前的传输配置得出的正确结果, 在进行实际上的传输结束后也应该在 DST_Buffer 数组中获得这样的数据。 换句话说,SRC_Buffer 保存了要传输的源数据,DST_Buffer 保存了传输后的实际结果, Expected_DST_Buffer 则保存的是传输后的正确结果, 后面还会通过 DST_Buffer 与 Expected_DST_Buffer 数组中数据的对比,来判断传输是否成功。

5. 使用代码配置:正常传输模式
下面是 DMAC 在正常模式下传输的配置代码:

 /* 正常传输模式 */
 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     = BUFFER_SIZE,  //指定传输的长度(即正常和重复模式下的传输次数 或 块和重复-块模式下传输的块大小)
 };
 // 按照上述传输信息配置,期待的正确传输结果为:
 uint32_t Expected_DST_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 };

注:使用以上代码需在头文件 “bsp_dmac_m2m.h” 中定义宏 USE_MY_TRANSFER_INFOR_CONFIG, 并且定义宏 DMAC_TRANSFER_MODE 等于 DMAC_TRANSFER_NORMAL_MODE 来选择传输模式为: 正常传输模式。

传输信息结构体变量 my_transfer_info_normal 用于对 DMAC 的传输进行重配置。

6. 使用代码配置:重复传输模式
上面使用完正常传输模式,下面来试一下重复传输模式, 其实无非就是在正常模式下多了 可以指定重复传输的次数 的功能, 就变成了重复传输模式。可以结合地址递增模式、重复区域,来实现环形队列。

下面是 DMAC 在重复传输模式下传输的配置代码:

/* 重复传输模式 */
 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_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_REPEAT,            //重复传输模式
     .p_dest                                  = (void *) DST_Buffer,             //目标地址
     .p_src                                   = (void const *) SRC_Buffer,       //源地址
     .num_blocks = 8,            //指定传输的块数(正常模式下无效,仅在重复、块或重复-块模式下有效)
     .length     = 4,            //指定传输的长度(即正常的传输次数或重复模式下重复大小 或 块和重复-块模式下传输的块大小)
 };
 // 按照上述传输信息配置,期待的正确传输结果为:
 uint32_t Expected_DST_Buffer[BUFFER_SIZE] = {
                     0x01020304,0x05060708,0x090A0B0C,0x0D0E0F10,
                     0x01020304,0x05060708,0x090A0B0C,0x0D0E0F10,
                     0x01020304,0x05060708,0x090A0B0C,0x0D0E0F10,
                     0x01020304,0x05060708,0x090A0B0C,0x0D0E0F10,
                     0x01020304,0x05060708,0x090A0B0C,0x0D0E0F10,
                     0x01020304,0x05060708,0x090A0B0C,0x0D0E0F10,
                     0x01020304,0x05060708,0x090A0B0C,0x0D0E0F10,
                     0x01020304,0x05060708,0x090A0B0C,0x0D0E0F10 };

注:使用以上代码需在头文件 “bsp_dmac_m2m.h” 中定义宏 USE_MY_TRANSFER_INFOR_CONFIG, 并且定义宏 DMAC_TRANSFER_MODE 等于 DMAC_TRANSFER_REPEAT_MODE 来选择传输模式为: 重复传输模式。

传输信息结构体变量 my_transfer_info_repeat 用于对 DMAC 的传输进行重配置。

7. 使用代码配置:块传输模式
下面是 DMAC 在块传输模式下传输的配置代码:

 /* 块传输模式 */
 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 = 4,            //指定传输的块数(正常模式下无效,仅在重复、块或重复-块模式下有效)
     .length     = 8,            //指定传输的长度(即正常的传输次数或重复模式下重复大小 或 块和重复-块模式下传输的块大小)
 };
 // 按照上述传输信息配置,期待的正确传输结果为:
 uint32_t Expected_DST_Buffer[BUFFER_SIZE] = {
                     0x01020304,0x05060708,0x090A0B0C,0x0D0E0F10,
                     0x11121314,0x15161718,0x191A1B1C,0x1D1E1F20,
                     0x01020304,0x05060708,0x090A0B0C,0x0D0E0F10,
                     0x11121314,0x15161718,0x191A1B1C,0x1D1E1F20,
                     0x01020304,0x05060708,0x090A0B0C,0x0D0E0F10,
                     0x11121314,0x15161718,0x191A1B1C,0x1D1E1F20,
                     0x01020304,0x05060708,0x090A0B0C,0x0D0E0F10,
                     0x11121314,0x15161718,0x191A1B1C,0x1D1E1F20 };

注:使用以上代码需在头文件 “bsp_dmac_m2m.h” 中定义宏 USE_MY_TRANSFER_INFOR_CONFIG, 并且定义宏 DMAC_TRANSFER_MODE 等于 DMAC_TRANSFER_BLOCK_MODE 来选择传输模式为: 块传输模式。

传输信息结构体变量 my_transfer_info_block 用于对 DMAC 的传输进行重配置。

8. 使用代码配置:重复-块传输模式
下面是 DMAC 在重复-块传输模式下传输的配置代码:

 /* 重复-块传输模式 */
 transfer_info_t my_transfer_info_repeat_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_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_BLOCK,      //重复-块传输模式
     .p_dest                                  = (void *) DST_Buffer,             //目标地址
     .p_src                                   = (void const *) SRC_Buffer,       //源地址
     .num_blocks = 4,            //指定传输的块数(正常模式下无效,仅在重复、块或重复-块模式下有效)
     .length     = 2,           //指定传输的长度(即正常的传输次数或重复模式下重复大小 或 块和重复-块模式下传输的块大小)
 };
 // 按照上述传输信息配置,期待的正确传输结果为:
 uint32_t Expected_DST_Buffer[BUFFER_SIZE] = {
                     0x01020304,0x01020304,0x01020304,0x01020304,
                     0x01020304,0x01020304,0x01020304,0x01020304,
                     0x01020304,0x01020304,0x01020304,0x01020304,
                     0x01020304,0x01020304,0x01020304,0x01020304,
                     0x01020304,0x01020304,0x01020304,0x01020304,
                     0x01020304,0x01020304,0x01020304,0x01020304,
                     0x01020304,0x01020304,0x01020304,0x01020304,
                     0x01020304,0x01020304,0x01020304,0x01020304 };

注:使用以上代码需在头文件 “bsp_dmac_m2m.h” 中定义宏 USE_MY_TRANSFER_INFOR_CONFIG, 并且定义宏 DMAC_TRANSFER_MODE 等于 DMAC_TRANSFER_REPEAT_BLOCK_MODE 来选择传输模式为: 重复-块传输模式。

传输信息结构体变量 my_transfer_info_repeat_block 用于对 DMAC 的传输进行重配置。

9. DMAC初始化函数
若是使用 FSP 配置,需要设置传输地址, 通过调用 set_transfer_dst_src_address 函数来设置。

然后,调用 R_DMAC_Open 函数打开 DMAC。 需要注意,R_DMAC_Open 函数需要在 set_transfer_dst_src_address 函数之后调用, 因为在 R_DMAC_Open 函数内部会根据传输信息(包括传输地址等)来配置底层寄存器。

若是使用代码配置 DMAC 的传输信息(即定义了宏 USE_MY_TRANSFER_INFOR_CONFIG), 则还需要对 DMAC 进行重配置,方法是调用 R_DMAC_Reconfigure 函数, 并传入用于 DMAC 的传输信息配置的结构体变量(比如 my_transfer_info_normal)的首地址。

使用宏 DMAC_TRANSFER_MODE 来判断传输模式, 并根据不同的传输模式选择使用以下的传输信息变量来进行重配置: my_transfer_info_normal / my_transfer_info_repeat / my_transfer_info_repeat / my_transfer_info_block / my_transfer_info_repeat_block。

DMAC 初始化函数如下所示:

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

     /* 使用 FSP 界面的配置:需要先重新设置传输的源地址和目的地址 */
 #ifndef USE_MY_TRANSFER_INFOR_CONFIG
     set_transfer_dst_src_address(&g_transfer_dmac0_cfg, SRC_Buffer, DST_Buffer);
 #endif

     /* 打开 DMAC 模块 */
     err = R_DMAC_Open(&g_transfer_dmac0_ctrl, &g_transfer_dmac0_cfg);
     assert(FSP_SUCCESS == err);


     /* 使用我们新的自定义的传输信息:重新配置传输 */
 #ifdef USE_MY_TRANSFER_INFOR_CONFIG

     // 根据我们要使用的传输模式进行选择配置:
 #if (DMAC_TRANSFER_MODE == DMAC_TRANSFER_NORMAL_MODE)           //正常模式
     err = R_DMAC_Reconfigure(&g_transfer_dmac0_ctrl, &my_transfer_info_normal);
     assert(FSP_SUCCESS == err);

 #elif (DMAC_TRANSFER_MODE == DMAC_TRANSFER_REPEAT_MODE)         //重复模式
     err = R_DMAC_Reconfigure(&g_transfer_dmac0_ctrl, &my_transfer_info_repeat);
     assert(FSP_SUCCESS == err);

 #elif (DMAC_TRANSFER_MODE == DMAC_TRANSFER_BLOCK_MODE)          //块模式
     err = R_DMAC_Reconfigure(&g_transfer_dmac0_ctrl, &my_transfer_info_block);
     assert(FSP_SUCCESS == err);

 #elif (DMAC_TRANSFER_MODE == DMAC_TRANSFER_REPEAT_BLOCK_MODE)   //重复-块模式
     err = R_DMAC_Reconfigure(&g_transfer_dmac0_ctrl, &my_transfer_info_repeat_block);
     assert(FSP_SUCCESS == err);
 #endif //DMAC_TRANSFER_MODE

 #endif //USE_MY_TRANSFER_INFOR_CONFIG
 }

10. DMAC中断回调函数
DMAC 中断回调函数如下所示:

// DMA 传输完成标志位
 volatile bool dmac0_complete_transmission_sign = false;
 // 传输次数计数(中断次数)
 volatile uint16_t dmac0_transfer_count;

 /* DMAC 中断回调函数 */
 void dmac0_callback(dmac_callback_args_t *p_args)
 {
     (void)(p_args);
     dmac0_complete_transmission_sign = true;

     dmac0_transfer_count ++;
 }

dmac0_transfer_count 用于记录 DMAC 产生中断的次数。

11. hal_entry入口函数
在 hal_entry 函数中,程序遵循以下步骤来执行:

  • 调用 DMAC_Init 函数初始化 DMAC。

  • 调用 R_DMAC_Enable 函数使能 DMAC 使之可以响应传输请求。

  • 调用 R_DMAC_SoftwareStart 函数来发起软件触发请求信号来启动 DMAC 传输。

  • 通过一定的延时等待所有传输完成,因为在产生多次的中断的情况下,仅通过中断标志位判断可能出错。

  • 在传输完成之后,比较传输目标地址的数据(DST_Buffer)和期待的正确数据(Expected_DST_Buffer)是否一致。

传入 R_DMAC_SoftwareStart 函数的参数 TRANSFER_START_MODE_SINGLE 和 TRANSFER_START_MODE_REPEAT 的区别如下:

  • 传入参数为 TRANSFER_START_MODE_SINGLE 时, 正常模式和重复模式下每发起一次软件请求只会传输一个数据单元大小(transfer_size_t size)的数据。 块模式下则是只会传输一个块大小(transfer_info_t::length)的数据。
  • 传入参数为 TRANSFER_START_MODE_REPEAT 时, 会自动重复地触发传输,期间可能会产生多次中断,直至所有数据都传输完成为止。

hal_entry 入口函数如下所示。

 /* 用户头文件包含 */
 #include "led/bsp_led.h"
 #include "debug_uart/bsp_debug_uart.h"
 #include "dmac/bsp_dmac_m2m.h"


 extern const uint32_t SRC_Buffer[BUFFER_SIZE];
 extern uint32_t DST_Buffer[BUFFER_SIZE];
 extern uint32_t Expected_DST_Buffer[BUFFER_SIZE];
 extern volatile bool dmac0_complete_transmission_sign;
 extern volatile uint16_t dmac0_transfer_count;

 uint8_t BufferCompare(const uint32_t *pBuffer1, const uint32_t *pBuffer2, uint16_t BufferLength);
 void    BufferShow_HexData(const uint32_t *pBuffer, uint16_t BufferLength);


 void hal_entry(void)
 {
     /* TODO: add your own code here */
     fsp_err_t err = FSP_SUCCESS;
     uint8_t res;

     LED_Init();         // LED 初始化
     Debug_UART4_Init(); // SCI4 UART 调试串口初始化

     /* 初始化 DMAC */
     DMAC_Init();
     dmac0_complete_transmission_sign = false; //传输完成标志位清零

     printf("这是一个 DMAC 存储器到存储器的传输实验例程\r\n");
     printf("打开串口助手,查看接收窗口打印的相关提示信息\r\n");
     printf("观察板载LED灯,本实验使用两个LED灯来指示 DMAC 传输结果\r\n");
     printf("- DMA 数据传输失败,则 LED1 亮(红色)\r\n");
     printf("- DMA 数据传输成功,则 LED2 亮(蓝色)\r\n");
     printf("--------------------------------------------\r\n");

     /* 使能 DMAC 使之可以响应传输请求 */
     R_DMAC_Enable(&g_transfer_dmac0_ctrl);

     /************************************/
     /* 使用软件触发的方式启动 DMAC 传输 */
     /************************************/

 #ifndef USE_MY_TRANSFER_INFOR_CONFIG
     /* 根据 FSP 配置界面的传输信息配置进行传输 */

     //可以用下面这种方式:
     R_DMAC_SoftwareStart(&g_transfer_dmac0_ctrl, TRANSFER_START_MODE_REPEAT);

     //也可以用这种方式:
     //for (uint16_t i = 0; i < 1; i++)
     //{
     //    err = R_DMAC_SoftwareStart(&g_transfer_dmac0_ctrl, TRANSFER_START_MODE_SINGLE);
     //    assert(FSP_SUCCESS == err);
     //}

 #else   // 下面的这些是使用自定义的传输配置信息配置

 #if (DMAC_TRANSFER_MODE == DMAC_TRANSFER_NORMAL_MODE)           //正常模式(相当于重复次数为1的重复模式)
     //可以用下面这种方式:
     R_DMAC_SoftwareStart(&g_transfer_dmac0_ctrl, TRANSFER_START_MODE_REPEAT);

     //也可以用这种方式:
     //for (uint16_t i = 0; i < BUFFER_SIZE; i++)
     //{
     //    err = R_DMAC_SoftwareStart(&g_transfer_dmac0_ctrl, TRANSFER_START_MODE_SINGLE);
     //    assert(FSP_SUCCESS == err);
     //}

 #elif (DMAC_TRANSFER_MODE == DMAC_TRANSFER_REPEAT_MODE)         //重复模式
     //可以用下面这种方式:
     R_DMAC_SoftwareStart(&g_transfer_dmac0_ctrl, TRANSFER_START_MODE_REPEAT);

     //也可以用这种方式:
     //for (uint16_t i = 0; i < BUFFER_SIZE; i++)
     //{
     //    err = R_DMAC_SoftwareStart(&g_transfer_dmac0_ctrl, TRANSFER_START_MODE_SINGLE);
     //    assert(FSP_SUCCESS == err);
     //}

 #elif (DMAC_TRANSFER_MODE == DMAC_TRANSFER_BLOCK_MODE)          //块模式
     //可以用下面这种方式:
     R_DMAC_SoftwareStart(&g_transfer_dmac0_ctrl, TRANSFER_START_MODE_REPEAT);

     //也可以用这种方式:
     //for (uint16_t i = 0; i < 4; i++)
     //{
     //    err = R_DMAC_SoftwareStart(&g_transfer_dmac0_ctrl, TRANSFER_START_MODE_SINGLE);
     //    assert(FSP_SUCCESS == err);
     //
     //    //加个小延时,确保DMAC通道0传输完成之后才再次软件触发启动,否则传输可能出错
     //    R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_MILLISECONDS);
     //}

 #elif (DMAC_TRANSFER_MODE == DMAC_TRANSFER_REPEAT_BLOCK_MODE)   //重复-块模式
     //可以用下面这种方式:
     R_DMAC_SoftwareStart(&g_transfer_dmac0_ctrl, TRANSFER_START_MODE_REPEAT);

     //也可以用这种方式:
     //for (uint16_t i = 0; i < 4; i++)
     //{
     //    err = R_DMAC_SoftwareStart(&g_transfer_dmac0_ctrl, TRANSFER_START_MODE_SINGLE);
     //    assert(FSP_SUCCESS == err);
     //
     //    //加个小延时,确保DMAC通道0传输完成之后才再次软件触发启动,否则传输可能出错
     //    R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_MILLISECONDS);
     //}

 #endif //DMAC_TRANSFER_MODE

 #endif //USE_MY_TRANSFER_INFOR_CONFIG


     /* 判断传输完成中断(需至少触发过1次) */
     while (false == dmac0_complete_transmission_sign);
     /* 等待所有传输完成(如果是TRANSFER_IRQ_EACH模式,传输过程中可能会触发多次中断) */
     R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);   //加上延时确保所有传输都已完成
     printf("\r\n传输计数(中断次数):dmac0_transfer_count = %d\r\n", dmac0_transfer_count);


     /* 将传输后的数据与我们所期待的结果相比较 */
     res = BufferCompare(DST_Buffer, Expected_DST_Buffer, BUFFER_SIZE);

     printf("传输结果:");
     /* 根据两者数据的比较结果进行判断 */
     if( res != 0)
     {
         /* 源数据与传输后数据不相等时,LED1 亮(红色),表示传输失败 */
         LED1_ON;
         printf("<传输失败>\r\n");
     }
     else
     {
         /* 源数据与传输后数据相等时,LED1 亮(蓝色),表示传输成功 */
         LED2_ON;
         printf("<传输成功>\r\n");
     }

     printf("\r\nSRC:");
     BufferShow_HexData(SRC_Buffer, BUFFER_SIZE);
     printf("\r\nDST:(应与 Expected_DST 一致)");
     BufferShow_HexData(DST_Buffer, BUFFER_SIZE);
     printf("\r\nExpected_DST:");
     BufferShow_HexData(Expected_DST_Buffer, BUFFER_SIZE);

     while(1)
     {

     }


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

12. 缓冲区数据比较函数

 /* 缓冲区数据比较函数
   返回 0 表示两个缓冲区数据一致
 */
 uint8_t BufferCompare(const uint32_t *pBuffer1, const uint32_t *pBuffer2, uint16_t BufferLength)
 {
     /* 数据长度递减 */
     while(BufferLength--)
     {
         /* 判断两个数据源是否对应相等 */
         if(*pBuffer1 != *pBuffer2)
         {
             /* 对应数据源不相等马上退出函数,并返回1 */
             return 1;
         }
         /* 递增两个数据源的地址指针 */
         pBuffer1++;
         pBuffer2++;
     }
     /* 完成判断并且两组数据完全一致 */
     return 0;
 }

13. 打印缓冲区数据函数

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

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

         pBuffer++;
         BufferLength--;
     }

     printf("\r\n");
 }

二、DTC外部中断触发传输

1. FSP配置

先加入外部中断。 点到“Pins”页面,在 ICU0 里面找到 IRQ09,这里选用 P004 引脚(SW2按键连接的引脚)连接到外部中断 IRQ09。

在这里插入图片描述
然后点到“Stacks”页面,按照“New Stack”→“Input”→“External IRQ”的步骤添加一个ICU模块来配置外部中断。 ICU 模块的配置可按照如下图所示进行配置,中断触发方式默认选择上升沿触发, 中断优先级设置比 UART 中断大一点,设置为优先级 10。
在这里插入图片描述
接着在“Stacks”页面继续加入 DTC 模块,按如下图所示步骤添加。
在这里插入图片描述
按如下图配置一下 DTC:
在这里插入图片描述
DTC 配置项(与上图相对应):
在这里插入图片描述
配置完成后,直接右上角点击生成代码。

2. 使用FSP配置器生成的配置
下面的是与之前在 FSP 配置界面上的配置等效的配置代码:

 /* FSP配置界面的传输信息配置(正常传输模式)等效于下面 fsp_transfer_info_normal 里的配置(除了源地址和目标地址)
   源地址和目标地址在FSP配置界面设置的话不太方便,我们会在 DTC_Init 函数里设置。
   关于偏移值(Offset value)和源缓冲大小(Source Buffer Size),在 transfer_info_t 里没有这两项设置,建议在FSP配置界面设置
   - 偏移值只有在地址模式是偏移模式的情况下才会用到;
   - 而源缓冲大小与之相关的功能本例程不会涉及到,所以暂不考虑。
   下面的 fsp_transfer_info_normal 仅作为对比参考,在本例程中是没有用到的。
 */
 //transfer_info_t fsp_transfer_info_normal =
 //{
 //    .transfer_settings_word_b.dest_addr_mode = TRANSFER_ADDR_MODE_FIXED,        //每次传输后,目标地址指针固定不变
 //    .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_FIXED,        //每次传输后,源地址指针固定不变
 //    .transfer_settings_word_b.size           = TRANSFER_SIZE_2_BYTE,            //每次传输2字节
 //    .transfer_settings_word_b.mode           = TRANSFER_MODE_NORMAL,            //正常传输模式
 //    .p_dest                                  = (void *) DST_Buffer,             //目标地址
 //    .p_src                                   = (void const *) SRC_Buffer,       //源地址
 //    .num_blocks = 0,            //指定传输的块数(正常模式和重复模式下均无效,仅块模式下有效)
 //    .length     = 1,            //指定传输的长度(即正常的传输次数或重复模式下重复大小 或 块模式下传输的块大小)
 //};
 // 按照上述传输信息配置,期待的正确传输结果为:
 uint32_t Expected_DST_Buffer[BUFFER_SIZE] = {
                     0x00000304,0x00000000,0x00000000,0x00000000,
                     0x00000000,0x00000000,0x00000000,0x00000000,
                     0x00000000,0x00000000,0x00000000,0x00000000,
                     0x00000000,0x00000000,0x00000000,0x00000000,
                     0x00000000,0x00000000,0x00000000,0x00000000,
                     0x00000000,0x00000000,0x00000000,0x00000000,
                     0x00000000,0x00000000,0x00000000,0x00000000,
                     0x00000000,0x00000000,0x00000000,0x00000000 };

3. 使用代码配置:正常传输模式
下面是 DTC 在正常模式下传输的配置代码:

 /* 正常传输模式 */
 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     = 1,            //指定传输的长度(即正常的传输次数或重复模式下重复大小 或 块模式下传输的块大小)
 };
 // 按照上述传输信息配置,期待的正确传输结果为:
 uint32_t Expected_DST_Buffer[BUFFER_SIZE] = {
                     0x01020304,0x00000000,0x00000000,0x00000000,
                     0x00000000,0x00000000,0x00000000,0x00000000,
                     0x00000000,0x00000000,0x00000000,0x00000000,
                     0x00000000,0x00000000,0x00000000,0x00000000,
                     0x00000000,0x00000000,0x00000000,0x00000000,
                     0x00000000,0x00000000,0x00000000,0x00000000,
                     0x00000000,0x00000000,0x00000000,0x00000000,
                     0x00000000,0x00000000,0x00000000,0x00000000 };

4. 使用代码配置:重复传输模式
下面是 DTC 在重复传输模式下传输的配置代码:

 /* 重复传输模式 */
 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,            //指定传输的长度(即正常的传输次数或重复模式下重复大小 或 块模式下传输的块大小)
 };
 // 按照上述传输信息配置,期待的正确传输结果为:
 uint32_t Expected_DST_Buffer[BUFFER_SIZE] = {
                     0x01020304,0x05060708,0x01020304,0x05060708,
                     0x00000000,0x00000000,0x00000000,0x00000000,
                     0x00000000,0x00000000,0x00000000,0x00000000,
                     0x00000000,0x00000000,0x00000000,0x00000000,
                     0x00000000,0x00000000,0x00000000,0x00000000,
                     0x00000000,0x00000000,0x00000000,0x00000000,
                     0x00000000,0x00000000,0x00000000,0x00000000,
                     0x00000000,0x00000000,0x00000000,0x00000000 };

5. 使用代码配置:块传输模式
下面是 DTC 在块传输模式下传输的配置代码:

 /* 块传输模式 */
 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     = BUFFER_SIZE,  //指定传输的长度(即正常的传输次数或重复模式下重复大小 或 块模式下传输的块大小)
 };
 // 按照上述传输信息配置,期待的正确传输结果为:
 uint32_t Expected_DST_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 };

6. DTC初始化函数
DTC 初始化函数如下所示:

/* DTC 初始化函数 */
 void DTC_Init(void)
 {
     fsp_err_t err;

     /* 使用 FSP 界面的配置:需要先重新设置传输的源地址和目的地址 */
 #ifndef USE_MY_TRANSFER_INFOR_CONFIG
     set_transfer_dst_src_address(&g_transfer_dtc_cfg, SRC_Buffer, DST_Buffer);
 #endif

     err = R_DTC_Open(&g_transfer_dtc_ctrl, &g_transfer_dtc_cfg);
     assert(FSP_SUCCESS == err);


     /* 使用我们新的自定义的传输信息:重新配置传输 */
 #ifdef USE_MY_TRANSFER_INFOR_CONFIG

     // 根据我们要使用的传输模式进行选择配置:
 #if (DTC_TRANSFER_MODE == DTC_TRANSFER_NORMAL_MODE)           //正常模式
     err = R_DTC_Reconfigure(&g_transfer_dtc_ctrl, &my_transfer_info_normal);
     assert(FSP_SUCCESS == err);

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

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

 #endif //USE_MY_TRANSFER_INFOR_CONFIG
 }

7. 按键外部中断回调函数
按键外部中断回调函数如下所示:

 /* 按键按下标志 */
 volatile bool key_sw2_press = false;

 /* 按键中断回调函数 */
 void icu_external_irq_callback(external_irq_callback_args_t *p_args)
 {
     /* 判断中断通道 */
     if (9 == p_args->channel)
     {
         key_sw2_press = true;   // 按键SW2按下
     }
 }

8. hal_entry入口函数

/* 用户头文件包含 */
 #include "led/bsp_led.h"
 #include "debug_uart/bsp_debug_uart.h"
 #include "dtc/bsp_dtc.h"


 extern const uint32_t SRC_Buffer[BUFFER_SIZE];
 extern uint32_t DST_Buffer[BUFFER_SIZE];
 extern uint32_t Expected_DST_Buffer[BUFFER_SIZE];
 extern volatile bool dtc_complete_transmission_sign;

 uint8_t BufferCompare(const uint32_t *pBuffer1, const uint32_t *pBuffer2, uint16_t BufferLength);
 void    BufferShow_HexData(const uint32_t *pBuffer, uint16_t BufferLength);


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

     LED_Init();         // LED 初始化
     Debug_UART4_Init(); // SCI4 UART 调试串口初始化

     /* 初始化 DTC */
     DTC_Init();

     printf("这是一个 DTC 存储器到存储器的传输实验例程\r\n");
     printf("打开串口助手,查看接收窗口打印的相关提示信息\r\n");
     printf("按下按键 SW2 激活 DTC 传输\r\n");
     printf("观察板载LED灯,本实验使用两个LED灯来指示 DTC 传输结果\r\n");
     printf("- DTC 数据传输失败,则 LED1 亮(红色)\r\n");
     printf("- DTC 数据传输成功,则 LED2 亮(蓝色)\r\n");
     printf("--------------------------------------------\r\n");


     /* Open ICU module */
     R_ICU_ExternalIrqOpen(&g_external_irq9_ctrl, &g_external_irq9_cfg);
     /* 允许中断 */
     R_ICU_ExternalIrqEnable(&g_external_irq9_ctrl);


     /* 使能 DTC 模块 */
     R_DTC_Enable(&g_transfer_dtc_ctrl);

     /*************************************/
     /* 使用按键外部中断触发激活 DTC 传输 */
     /*************************************/

 #ifndef USE_MY_TRANSFER_INFOR_CONFIG
     /* 根据 FSP 配置界面的传输信息进行传输 */

     /* 等待激活 DTC 传输 */
     for (uint16_t i = 0; i < 1; i++)
     {
         /* 等待按键按下,按键按下一次即激活一次 DTC 传输 */
         while (false == key_sw2_press);
         key_sw2_press = false;
         /* 等待本次传输完成 */
         R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);   //加上延时确保传输完成
     }

 #else   // 下面的这些是使用自定义的传输配置信息配置

 #if (DTC_TRANSFER_MODE == DTC_TRANSFER_NORMAL_MODE)           //正常模式

     /* 等待激活 DTC 传输 */
     for (uint16_t i = 0; i < 1; i++)
     {
         /* 等待按键按下,按键按下一次即激活一次 DTC 传输 */
         while (false == key_sw2_press);
         key_sw2_press = false;
         /* 等待本次传输完成 */
         R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);   //加上延时确保传输完成
     }

 #elif (DTC_TRANSFER_MODE == DTC_TRANSFER_REPEAT_MODE)         //重复模式

     /* 等待激活 DTC 传输 */
     for (uint16_t i = 0; i < 4; i++)
     {
         /* 等待按键按下,按键按下一次即激活一次 DTC 传输 */
         while (false == key_sw2_press);
         key_sw2_press = false;
         /* 等待本次传输完成 */
         R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);   //加上延时确保传输完成
     }

 #elif (DTC_TRANSFER_MODE == DTC_TRANSFER_BLOCK_MODE)          //块模式

     /* 等待激活 DTC 传输 */
     for (uint16_t i = 0; i < 1; i++)
     {
         /* 等待按键按下,按键按下一次即激活一次 DTC 传输 */
         while (false == key_sw2_press);
         key_sw2_press = false;
         /* 等待本次传输完成 */
         R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);   //加上延时确保传输完成
     }

 #endif //DTC_TRANSFER_MODE

 #endif //USE_MY_TRANSFER_INFOR_CONFIG


     /* 将传输后的数据与我们所期待的结果相比较 */
     res = BufferCompare(DST_Buffer, Expected_DST_Buffer, BUFFER_SIZE);

     printf("传输结果:");
     /* 根据两者数据的比较结果进行判断 */
     if( res != 0)
     {
         /* 源数据与传输后数据不相等时,LED1 亮(红色),表示传输失败 */
         LED1_ON;
         printf("<传输失败>\r\n");
     }
     else
     {
         /* 源数据与传输后数据相等时,LED1 亮(蓝色),表示传输成功 */
         LED2_ON;
         printf("<传输成功>\r\n");
     }

     printf("\r\nSRC:");
     BufferShow_HexData(SRC_Buffer, BUFFER_SIZE);
     printf("\r\nDST:(应与 Expected_DST 一致)");
     BufferShow_HexData(DST_Buffer, BUFFER_SIZE);
     printf("\r\nExpected_DST:");
     BufferShow_HexData(Expected_DST_Buffer, BUFFER_SIZE);

     while(1)
     {

     }


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

实验现象
首先通过宏 USE_MY_TRANSFER_INFOR_CONFIG (在 bsp_dtc.h 文件中) 来选择是使用自定义的传输信息,还是使用在 FSP 配置界面配置的传输信息。

其次通过宏 DMAC_TRANSFER_MODE (在 bsp_dtc.h 文件中)来选择不同的传输模式。

最后编译工程并下载到开发板上,打开串口助手可以查看程序运行打印的提示信息。 按下启明6M5开发板上的按键 SW2,即触发 DTC 传输。 如果 DTC 传输成功,则蓝色 LED2 亮起,如果传输失败则红色 LED1 亮起。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/590660.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一分钟学一个 Linux 命令 - cd

前言 大家好&#xff0c;我是 god23bin。欢迎来到这个系列&#xff0c;每天只需一分钟&#xff0c;记住一个 Linux 命令不成问题。今天让我们从 cd 命令开始&#xff0c;掌握在 Linux 系统中切换目录的技巧。 什么是 cd 命令&#xff1f; cd 命令来自这么一个词语&#xff0…

liftOver 不同版本基因组文件相互转化

大家好&#xff0c;我是邓飞。前一段时间有小伙伴在星球提问&#xff1a;想将不同版本的SNP数据合并&#xff0c;不想重新call snp&#xff0c;想把绵羊的V2和V4版本的数据合并&#xff0c;具体来说&#xff0c;是V2转为V4然后与V4合并。 我建议用liftOver软件进行处理&#xf…

SAP-MM-采购折扣知识与会计处理

采购折扣&#xff0c;按折扣的方式和性质可以分为商业折扣和现金折扣两种方式。 商业折扣是指购货方批量进货时&#xff0c;要求销货方按零售价格打一个折扣而少支付的货款金额。企业之间的商品购销活动中&#xff0c;商业折扣是一种较常见的交易现象。 现金折扣则是指在赊购条…

数列DP进阶

目录 一&#xff0c;斜率优化 1&#xff0c;斜率优化原理 2&#xff0c;凸包和斜率计算 3&#xff0c;实战 黑暗爆炸 - 4709 柠檬 二&#xff0c;else 力扣 644. 子数组最大平均数 II&#xff08;最大子段和二分&#xff09; ​力扣 646. 最长数对链 力扣 1235. 规划兼…

浅科普一下计算机发展史阶段及那些不为人知的重要里程碑

目录 〇、前言 一、计算机发展历史阶段 二、计算机发展史中重要的里程碑 三、计算机对人类社会发展的重要性 四、计算机的应用领域 五、常见计算机辅助技术 六、总结 〇、前言 计算机的诞生无疑对人类社会的发展起着至关重要的巨大作用。计算机发明者名叫约翰冯诺依曼&a…

SAP-MM-发票-采购运费

采购运费是采购业务中一种特殊的定价&#xff0c;在SAP系统中&#xff0c;交货成本和其相近&#xff0c;是指在货物交付过程中发生的运输成本&#xff0c;只要有货物交付&#xff0c;就会有运费&#xff0c;而运费或者由采购方承担&#xff0c;或者由销售方承担&#xff0c;国内…

03SpringCloud Docker

Docker (1&#xff09;从VM与Docker框架中&#xff0c;直观上VM多了一层Guest OS&#xff0c;同时Hypervisor会对硬件资源进行虚拟化&#xff0c;docker直接使用硬件资源&#xff0c;所以资源利用率相对docker低。 &#xff08;2&#xff09;openstack能够以10台/min的速度创建…

SSM框架学习-拦截器

1. 简介 在Spring框架中&#xff0c;拦截器是一种很重要的组件&#xff0c;它们允许在请求到达控制器之前或之后执行一些代码。拦截器在请求处理的特定点进行拦截&#xff0c;然后通过逻辑来决定是否将控制器的处理传递给下一个处理程序。 在Spring中&#xff0c;拦截器是由实现…

【MATLAB速成】知识点总结(通俗易懂,学不会来打我)

【MATLAB速成】知识点总结&#xff08;通俗易懂&#xff0c;学不会来打我&#xff09; 一、概念 MATLAB的中文名称是&#xff08;矩阵实验室&#xff09;&#xff0c;英文全称是&#xff08;Matrix Laboratory&#xff09;&#xff0c;是一种以&#xff08;矩阵计算&#xff…

【学习日记2023.5.30】之 管理端订单模块完善_调用百度地图优化用户端提交订单是否超出配送距离

文章目录 9. 管理端订单模块完善9.1 需求分析和涉及9.2 代码开发Controller层Service层接口Service层实现类Mapper层 9.3 功能测试9.4 提交代码9.5 优化用户下单功能&#xff0c;引入距离判断 9. 管理端订单模块完善 订单搜索各个状态的订单数量统计查询订单详情接单拒单取消订…

古诗生成-pytorch

本文为RNN做古诗生成的一个小demo&#xff0c;只要是为了完成课上的作业&#xff08;由于训练比较慢&#xff0c;所以周期仅设置为3&#xff0c;大一点性能可能会更好&#xff09;&#xff0c;如有需要可以在这基础之上进行加工&#xff0c;数据集没办法上传&#xff0c;如有需…

FreeRTOS_从底层学习实时操作系统

目录 1. 裸机系统和多任务系统 2. 任务的定任务切换的实现 2.1 什么是任务&#xff1f; 2.2 调度器 2.3 临界段 3. 空闲任务和阻塞延迟 4. 时间片 1. 裸机系统和多任务系统 裸机系统&#xff1a; 裸机系统分为轮询系统和前后台系统&#xff1b;&#xff08;51单片机就属…

八大排序:直接插入排序、希尔排序、选择排序、堆排序、冒泡排序、快速排序、归并排序、计数排序

文章目录 排序概念常见的排序算法常见排序算法的实现直接插入排序希尔排序选择排序堆排序冒泡排序快速排序递归实现Hoare版本挖坑法前后指针法 非递归实现Hoare版本挖坑法前后指针法 快速排序俩个优化 归并排序递归实现非递归实现外排序 计数排序 常见排序算法的性能分析 排序概…

【已完美解决】scons问题求助:如何设置编译输出目录搞清楚后,有些编译输出的obj文件却在源码目录,而不是设置的输出目录。

【已完美解决】scons问题求助&#xff1a;如何设置编译输出目录搞清楚后&#xff0c;有些编译输出的obj文件却在源码目录&#xff0c;而不是设置的输出目录。 文章目录 1 前置背景2 我的疑问3 一手点拨4 问题解决 1 前置背景 最近在基于目前已有的rt-thread构建框架&#xff0…

【Spring源码解读一】IoC容器之AnnotationConfigApplicationContext

根据AnnotationConfigApplicationContext类去阅读其将Bean对象交给IoC容器管理的过程。以下这三个代码块是将配置类注册进IoC容器的例子。下面是关于这个类的继承与实现的类图关系树。 public class Test {public static void main(String[] args) {// 配置类注册进IoC容器App…

解决Ubuntu16中安装opencv后找不到vtk库的问题

最近一个项目中要用到OpenCV的VTK库&#xff0c;但引入头文件#include <opencv2/viz.hpp>时却说找不到这个库&#xff0c;网上搜了下说在编译opencv源码的时候&#xff0c;需要加上编译VTK库的选项&#xff0c;于是重新下载、编译、安装了源码&#xff0c;在cmake时加上了…

最流行的AI绘图工具Midjourney,你不得不知道的使用技巧

​关注文章下方公众号&#xff0c;可免费获取AIGC最新学习资料 本文字数&#xff1a;1500&#xff0c;阅读时长大约&#xff1a;10分钟 Midjourney成为了最受欢迎的生成式AI工具之一。它的使用很简单。输入一些文本&#xff0c;Midjourney背后的大脑&#xff08;或计算机&#…

Linux 权限

目录 一、 从问题开始 问题一: 什么叫shell? 问题二: 为什么不能直接使用kernel呢? 问题三: shell 与bash 有什么不同吗? 二、 Linux权限 0x01 Linux用户 0x02 切换用户命令 0x03 sudo命令 0x04 权限的相关概念 0x05 chmod 0x06 chown 0x07 chgrp 0x08 文件权…

重磅!软著申请不需要邮寄纸质材料啦,附软著申请流程。

重磅&#xff01;软著申请不需要邮寄纸质材料啦&#xff0c;附软著申请流程。 最新消息申请流程一&#xff0c;准备申请材料二&#xff0c;申请人填写申请表三&#xff0c;提交申请材料四&#xff0c;补正五&#xff0c;审查六&#xff0c;发布公告七&#xff0c;接受异议八&am…

力扣---二叉树OJ题(多种题型二叉树)

文章目录 前言&#x1f31f;一、剑指 Offer 55 - I. 二叉树的深度&#x1f30f;1.1 链接&#xff1a;&#x1f30f;1.2 代码一&#xff1a;&#x1f30f;1.3 代码二&#xff1a;&#x1f30f;1.4 流程图&#xff1a; &#x1f31f;二、100. 相同的树&#x1f30f;2.1 链接&…