您的当前位置:首页STM32标准库-DMA实验

STM32标准库-DMA实验

来源:小侦探旅游网

1.1 STM32 DMA 简介

DMA支持各种外设、闪存、SRAM作为数据源和数据目标,具体可查表。 同时仅一个有效。

STM32的DMA特性包括:

  •         专用硬件请求与软件触发配置灵活。
  •         四级优先权设置,同优先权时硬件决定顺序。
  •         支持字节、半字、全字传输宽度,需对齐源和目标地址
  •         循环缓冲管理功能。
  •         三事件标志(半传输、完成、出错)可组合为中断请求。
  •         支持存储器间、外设与存储器间传输。
  •         闪存、SRAM、APB1/2、AHB外设均可作为源和目标。
  •         可编程传输数目,最大65536。

        STM32F103ZET6 有两个 DMA 控制器,DMA1 和 DMA2。

        外设(如TIMx、ADC、SPIx、I2Cx、USARTx)产生的DMA请求经逻辑或处理后输入DMA控制器,确保同时仅一个有效,通过仲裁器和DMA_CCRx的优先级配置裁决哪个先执行

        通道1的多个DMA1请求(如ADC1、TIM2_CH3、TIM4_CH1)通过逻辑或运算合并,确保同一时间仅一个请求能被响应,其他通道同理。

        例如我们想使用 USART1,查表可知需用到DMA1的通道4和通道5。

中断状态寄存器(DMA_ISR)

        由于DMA1有7个通道,每个通道有传输错误标志半传输标志传输完成标志全局中断标志,因此DMA_ISR作为32位寄存器使用了4*7=28位。

        半传输指数据已经传输缓冲区的一半。

        全局中断指传输错误、半传输、传输完成任意一个满足都触发。

        最常用的是传输完成标志。如果开启了这些中断,达到条件后就会跳到中断服务函数。

        可通过查询中断状态寄存器DMA_ISR来获得当前DMA的状态

中断标志清除寄存器(DMA_IFCR) 

         DMA_ISR是只读寄存器,可以用来获得DMA的传输错误半传输传输完成全局中断标志。要清除 DMA_ISR的标志位需要使用中断标志清除寄存器DMA_IFCR

        传输错误、半传输、传输完成、全局中断标志位,仍然是32位寄存器使用了4*7=28。

通道x配置寄存器(DMA_CCRx)

        通道x配置寄存器DMA_CCRx用来配置

  •                 模式(存储器到存储器模式,寄存器到存储器模式)、
  •                 通道优先级(低、中、高、最高),
  •                 存储器数据宽度(8位、16位、32位、保留),
  •                 外设数据宽度(8位、16位、32位、保留),
  •                 存储器地址增量模式(0,1),  传输完成后地址自增,用于连续传输
  •                 外设地址增量模式(0,1),
  •                 循环模式(0,1),
  •                 数据传输方向(从外设读,从存储器读),
  •                 允许错误传输中断(0,1),
  •                 允许半传输中断(0,1),
  •                 允许传输完成中断(0,1),
  •                 通道开启(0,1)

通道x数据量寄存器(DMA_CNDTRx)

        通道x传输数据量寄存器DMA_CNDTRx,用来控制DMA通道x每次要传输的数据量,范围为0~65535,字节。该寄存器的值会随着传输的进行而减少,数据量寄存器的值为0表示传输完成。所以可通过传输量寄存器的值得知当前传输进度Channel x Number of Data to Transfer Register

通道x外设地址寄存器(DMA_CPARx)

DMA Channel x Peripheral Address Register

1.2 串口1发送配置步骤

1)使能DMA时钟:

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

2)初始化DMA通道4参数:

        创建并填充DMA_InitTypeDef结构体,

                传输方向(如DMA_DIR_PeripheralDST)、

                传输数据量

                数据宽度

                传输模式(如DMA_Mode_Normal)、

                优先级

                是否存储器到存储器传输等。

        调用

        DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct)

        函数进行初始化。

DMA_InitTypeDef DMA_InitStructure;  
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR; // 外设地址  
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)cmar; // 内存地址  
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; // 内存到外设  
DMA_InitStructure.DMA_BufferSize = 64; // 传输数据量  
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 外设地址不递增  
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // 内存地址递增  
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 8位  
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; // 8位  
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; // 正常模式  
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; // 中优先级  
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; // 非内存到内存  
DMA_Init(DMA1_Channel4, &DMA_InitStructure); // 初始化DMA1通道4

3)使能串口DMA发送

USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); // 使能USART1的DMA发送

4)启动DMA传输

DMA_Cmd(DMA1_Channel4, ENABLE); // 启动DMA1通道4

5)查询DMA传输状态

// 查询DMA1通道4是否传输完成  
FlagStatus status = DMA_GetFlagStatus(DMA1_FLAG_TC4);  
  
// 获取DMA1通道4剩余数据量  
uint16_t remainingData = DMA_GetCurrDataCounter(DMA1_Channel4);

因篇幅问题不能全部显示,请点此查看更多更全内容