这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
icore3l_15 [2020/11/11 10:15] zgf |
icore3l_15 [2020/11/11 10:26] (当前版本) zgf |
||
---|---|---|---|
行 92: | 行 92: | ||
- DMA_SxNDTR计数器在数据存储结束后递减,该计数器中包含仍需执行的事务数。在产生事件后,外设会向DMA控制器发送请求信号。DMA控制器根据通道优先级处理该请求。只要DMA控制器访问外设,DMA控制器就会向外设发送确认信号。外设获得DMA控制器的确认信号后,便会立即释放其请求。一旦外设使请求失效,DMA控制器就会释放确认信号。如果有更多请求,外设可以启动下一个事务。 | - DMA_SxNDTR计数器在数据存储结束后递减,该计数器中包含仍需执行的事务数。在产生事件后,外设会向DMA控制器发送请求信号。DMA控制器根据通道优先级处理该请求。只要DMA控制器访问外设,DMA控制器就会向外设发送确认信号。外设获得DMA控制器的确认信号后,便会立即释放其请求。一旦外设使请求失效,DMA控制器就会释放确认信号。如果有更多请求,外设可以启动下一个事务。 | ||
==== 四、实验程序 ==== | ==== 四、实验程序 ==== | ||
+ | === 1.主函数 === | ||
+ | <code c> | ||
+ | //定义src_buffer数组作为DMA传输数据源 | ||
+ | //const关键字将src_buffer数组变量定义为常量类型 | ||
+ | //表示数据存储在内部的FLASH中 | ||
+ | const unsigned long int 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}; | ||
+ | //定义DMA传输目标存储器 | ||
+ | //存储在内部的SRAM中 | ||
+ | unsigned long int dst_buffer[BUFFER_SIZE] = {0}; | ||
+ | int main(void) | ||
+ | { | ||
+ | int i; | ||
+ | HAL_Init(); | ||
+ | SystemClock_Config(); | ||
+ | MX_GPIO_Init(); | ||
+ | MX_DMA_Init(); | ||
+ | HAL_DMA_Start(&hdma_memtomem_dma2_stream0,(unsigned long int)src_buffer,(unsigned long int)dst_buffer,(unsigned | ||
+ | long int)BUFFER_SIZE); | ||
+ | while(__HAL_DMA_GET_FLAG(&hdma_memtomem_dma2_stream0,DMA_FLAG_TCIF0_4) == SET); | ||
+ | for(i = 0;i < BUFFER_SIZE;i++) | ||
+ | { | ||
+ | if(dst_buffer[i] != src_buffer[i]) //测试失败 | ||
+ | { | ||
+ | while(1) | ||
+ | { | ||
+ | HAL_Delay(500); | ||
+ | LED_RED_ON; | ||
+ | HAL_Delay(500); | ||
+ | LED_RED_OFF; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | LED_RED_ON; //测试成功 | ||
+ | While(1) | ||
+ | { | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
+ | === 2.DMA初始化函数 === | ||
+ | <code c> | ||
+ | void MX_DMA_Init(void) | ||
+ | { | ||
+ | //使能DMA控制器时钟 | ||
+ | __HAL_RCC_DMA2_CLK_ENABLE(); //配置DMA工作方式 | ||
+ | hdma_memtomem_dma2_stream0.Instance = DMA2_Stream0; | ||
+ | hdma_memtomem_dma2_stream0.Init.Request = DMA_REQUEST_MEM2MEM; | ||
+ | hdma_memtomem_dma2_stream0.Init.Direction = DMA_MEMORY_TO_MEMORY;//方向为存储器到存储器 | ||
+ | hdma_memtomem_dma2_stream0.Init.PeriphInc = DMA_PINC_ENABLE; | ||
+ | hdma_memtomem_dma2_stream0.Init.MemInc = DMA_MINC_ENABLE; | ||
+ | hdma_memtomem_dma2_stream0.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; //外设数据宽度 | ||
+ | hdma_memtomem_dma2_stream0.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; //存储器数据宽度 | ||
+ | hdma_memtomem_dma2_stream0.Init.Mode = DMA_NORMAL; | ||
+ | hdma_memtomem_dma2_stream0.Init.Priority = DMA_PRIORITY_HIGH; //优先级别为高 | ||
+ | hdma_memtomem_dma2_stream0.Init.FIFOMode = DMA_FIFOMODE_ENABLE; | ||
+ | hdma_memtomem_dma2_stream0.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; | ||
+ | hdma_memtomem_dma2_stream0.Init.MemBurst = DMA_MBURST_SINGLE; //存储器突发单次传输 | ||
+ | hdma_memtomem_dma2_stream0.Init.PeriphBurst = DMA_PBURST_SINGLE; //外设突发单次传输 | ||
+ | if (HAL_DMA_Init(&hdma_memtomem_dma2_stream0) != HAL_OK) | ||
+ | { | ||
+ | Error_Handler(); | ||
+ | } | ||
+ | //DMA2中断配置 | ||
+ | HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0); | ||
+ | HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn); | ||
+ | } | ||
+ | </code> | ||
+ | === 3.DMA寄存器结构体 === | ||
+ | DMA相关的寄存器是通过HAL库中的结构体DMA_TypeDef 和DMA_Stream_TypeDef定义的 | ||
+ | <code c> | ||
+ | typedef struct | ||
+ | { | ||
+ | __IO uint32_t CR; /* DMA stream x 配置寄存器 */ | ||
+ | __IO uint32_t NDTR; /* DMA stream x 数据寄存器数 */ | ||
+ | __IO uint32_t PAR; /* DMA stream x 外设地址寄存器 */ | ||
+ | __IO uint32_t M0AR; /* DMA stream x 存储器0地址寄存器 */ | ||
+ | __IO uint32_t M1AR; /* DMA stream x 存储器1地址寄存器 */ | ||
+ | __IO uint32_t FCR; /* DMA stream x FIFO控制寄存器 */ | ||
+ | } | ||
+ | DMA_Stream_TypeDef; | ||
+ | typedef struct | ||
+ | { | ||
+ | __IO uint32_t LISR; /* DMA低中断状态寄存器,地址偏移量:0x00 */ | ||
+ | __IO uint32_t HISR; /* DMA高中断状态寄存器,地址偏移量:0x04 */ | ||
+ | __IO uint32_t LIFCR; /* DMA低中断标志清除寄存器,地址偏移量:0x08 */ | ||
+ | __IO uint32_t HIFCR; /* DMA高中断标志清除寄存器,地址偏移量:0x0C */ | ||
+ | } | ||
+ | DMA_TypeDef; | ||
+ | </code> | ||
+ | === 4.DMA句柄结构体DMA_HandleTypeDef === | ||
+ | HAL库在DMA_TypeDef的基础上封装了一个结构体DMA_HandleTypeDef,定义如下: | ||
+ | <code c> | ||
+ | typedef struct __DMA_HandleTypeDef | ||
+ | { | ||
+ | void *Instance; /* 注册基地址 */ | ||
+ | DMA_InitTypeDef Init; /* DMA通讯参数 */ | ||
+ | HAL_LockTypeDef Lock; /* DMA锁定对象 */ | ||
+ | __IO HAL_DMA_StateTypeDef State; /* DMA传输状态 */ | ||
+ | void *Parent; /* 父对象状态 */ | ||
+ | void (* XferCpltCallback)( struct __DMA_HandleTypeDef * hdma); | ||
+ | /* DMA传输完成回调 */ | ||
+ | void (* XferHalfCpltCallback)( struct __DMA_HandleTypeDef * hdma); | ||
+ | /* DMA半传输完成回调 */ | ||
+ | void (* XferM1CpltCallback)( struct __DMA_HandleTypeDef * hdma); | ||
+ | /* DMA传输完成Memory1回调 */ | ||
+ | void (* XferM1HalfCpltCallback)( struct __DMA_HandleTypeDef * hdma); | ||
+ | /* DMA传输半完成Memory1回调 */ | ||
+ | void (* XferErrorCallback)( struct __DMA_HandleTypeDef * hdma); | ||
+ | /* DMA传输错误回调 */ | ||
+ | void (* XferAbortCallback)( struct __DMA_HandleTypeDef * hdma); | ||
+ | /* DMA传输中止回调 */ | ||
+ | __IO uint32_t ErrorCode; /* DMA错误代码 */ | ||
+ | uint32_t StreamBaseAddress; /* DMA流基址 */ | ||
+ | uint32_t StreamIndex; /* DMA流索引 */ | ||
+ | DMAMUX_Channel_TypeDef *DMAmuxChannel; /* DMAMUX通道基地址 */ | ||
+ | DMAMUX_ChannelStatus_TypeDef *DMAmuxChannelStatus; | ||
+ | /* DMAMUX通道状态基地址 */ | ||
+ | uint32_t DMAmuxChannelStatusMask; /* DMAMUX通道状态掩码 */ | ||
+ | DMAMUX_RequestGen_TypeDef *DMAmuxRequestGen; /* DMAMUX请求生成器基地址 */ | ||
+ | DMAMUX_RequestGenStatus_TypeDef *DMAmuxRequestGenStatus; | ||
+ | /* DMAMUX请求生成器状态地址 */ | ||
+ | uint32_t DMAmuxRequestGenStatusMask; /* DMAMUX请求生成器状态掩码 */ | ||
+ | }DMA_HandleTypeDef; | ||
+ | </code> | ||
+ | ==== 五、实验步骤 ==== | ||
+ | - 把仿真器与iCore3L的SWD调试口相连(直接相连或者通过转接器相连); | ||
+ | - 把iCore3L通过Micro USB线与计算机相连,为iCore3L供电; | ||
+ | - 打开Keil MDK 开发环境,并打开本实验工程; | ||
+ | - 烧写程序到iCore3L上; | ||
+ | - 也可以进入Debug 模式,单步运行或设置断点验证程序逻辑。 | ||
+ | ==== 六、实验现象 ==== | ||
+ | 实验成功红色LED灯常亮,实验失败红色LED灯闪烁。 |