STM32F407单片机编程入门(十六) DMA详解及ADC-DMA方式采集含源码
文章目录
- 一.概要
- 二.STM32F407VET6单片机DMA外设特点
- 三.STM32F407单片机DMA内部结构图
- 四.DMA各通道请求
- 五.STM32F407VET6单片机ADC-DMA采集例程
- 六.工程源代码下载
- 七.小结
一.概要
基本概念:
DMA是Direct Memory Access的首字母缩写,是一种完全由硬件执行数据交换的工作方式。DMA控制器从CPU接管对总线的控制,不经过CPU直接在内存和外设之间进行批量数据交换。DMA控制器向内存发出地址和控制信号,修改地址,对传送的字的个数计数,并且以中断方式向CPU报告传送操作的结束。 DMA方式一般用于高速传送成组数据。
DMA传输的三大要素:
传输源:DMA控制器从传输源读出数据;
传输目标:DMA控制器将数据传输的目标;
触发信号:用于触发一次数据传输的动作,执行一个单位的传输源至传输目标的数据传输;可以用来控制传输的时机。
DMA的主要优点:
由于CPU根本不参加传送操作,因此就省去了CPU取指令、取数、送数等操作。在数据传送过程中,没有保存现场、恢复现场之类的工作。内存地址修改、传送字个数的计数等等,也不是由软件实现,而是用硬件线路直接实现的。所以DMA方式能满足高速I/O设备的要求,也有利于CPU效率的发挥。
二.STM32F407VET6单片机DMA外设特点
● 双 AHB 主总线架构,一个用于存储器访问,另一个用于外设访问
● 仅支持 32 位访问的 AHB 从编程接口
● 每个 DMA 控制器有 8 个数据流,每个数据流有多达 8 个通道(或称请求)
● 每个数据流有单独的四级 32 位先进先出存储器缓冲区 (FIFO),可用于 FIFO 模式或直
接模式:
— FIFO 模式:可通过软件将阈值级别选取为 FIFO 大小的 1/4、1/2 或 3/4
— 直接模式
每个 DMA 请求会立即启动对存储器的传输。当在直接模式(禁止 FIFO)下将 DMA 请求配置为以存储器到外设模式传输数据时,DMA 仅会将一个数据从存储器预加载到内部 FIFO,从而确保一旦外设触发 DMA 请求时则立即传输数据。
● 通过硬件可以将每个数据流配置为:
— 支持外设到存储器、存储器到外设和存储器到存储器传输的常规通道
— 也支持在存储器方双缓冲的双缓冲区通道
● 8 个数据流中的每一个都连接到专用硬件 DMA 通道(请求)
● DMA 数据流请求之间的优先级可用软件编程(4 个级别:非常高、高、中、低),在软
件优先级相同的情况下可以通过硬件决定优先级(例如,请求 0 的优先级高于请求 1)
● 每个数据流也支持通过软件触发存储器到存储器的传输(仅限 DMA2 控制器)
● 可供每个数据流选择的通道请求多达 8 个。此选择可由软件配置,允许几个外设启动 DMA请求
● 要传输的数据项的数目可以由 DMA 控制器或外设管理:
— DMA 流控制器:要传输的数据项的数目是 1 到 65535,可用软件编程
— 外设流控制器:要传输的数据项的数目未知并由源或目标外设控制,这些外设通过
硬件发出传输结束的信号
● 独立的源和目标传输宽度(字节、半字、字):源和目标的数据宽度不相等时,DMA 自动封装/解封必要的传输数据来优化带宽。
● 每个数据流都支持循环缓冲区管理。
● 5 个事件标志(DMA 半传输、DMA 传输完成、DMA 传输错误、DMA FIFO 错误、直接
模式错误),进行逻辑或运算,从而产生每个数据流的单个中断请求。
三.STM32F407单片机DMA内部结构图
DMA控制器由4部分组成:
AHB 从接口配置DMA
AHB主接口进行数据传输
仲裁器进行DMA请求的优先级管理
数据处理和计数
四.DMA各通道请求
多个外设请求被映射到同一个DMA通道。这些请求信号在经过逻辑或后进入DMA。通过配置对应外设的寄存器,每个外设的请求均可以独立的开启或关闭。用户必须确保同一时间,在同一个通道上仅有一个外设的请求被开启。
以ADC1为例,可以映射到DMA2的Channel0
DMA的传输模式:
循环模式:用于处理一个环形的缓冲区,每轮传输结束时数据传输的配置会自动地更新为初始状态,DMA传输会连续不断地进行。 一般采用循环模式。
普通模式:在DMA传输结束时,DMA通道被自动关闭,进一步的DMA请求将不被满足。
外设到存储器传输数据流:
五.STM32F407VET6单片机ADC-DMA采集例程
STM32F407VET6开发板的PA4 引脚上的进行 ADC 电压采集,杜邦线连接 PA4 引脚与 VDD(3.3V),应该能读到单片机供电的电压值。
打开STM32CubeMX软件,新建工程
Part Number处输入STM32F407VE,再双击就创建新的工程
配置下载口引脚
配置外部晶振引脚
PA4,PA5引脚配置成ADC
DMA配置
中断使能
配置系统主频168Mhz,使用外部晶振
配置工程文件名,保存路径,KEIL5工程输出方式
生成工程
用Keil5打开工程
主要代码:
int ADCData;
uint16_t VolDta1,VolDta2;
__IO uint16_t aADCxConvertedData[2]; //存放2组数据,分别是ADC1_CH4,ADC1_CH5
__IO uint8_t ubDmaTransferStatus = 2;//定义变量,在ADC采样结束,DMA传送完成置位,方便主程序取数据
//ADC数据采样结束回调函数,用于置位采样结束标志位
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
/* Prevent unused argument(s) compilation warning */
ubDmaTransferStatus=1;//置1
}
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
/* USER CODE BEGIN 2 */
if (HAL_ADC_Start_DMA(&hadc1,(uint32_t *)aADCxConvertedData,2) != HAL_OK)//启动ADC DMA传输
{
/* ADC conversion start error */
Error_Handler();
}
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if (ubDmaTransferStatus == 1)//判断数据是否已经转换完成
{
VolDta1=aADCxConvertedData[0]*3300/4095;//计算通道ADC1_Ch4采样到的电压值
VolDta2=aADCxConvertedData[1]*3300/4095;//计算通道ADC1_Ch5采样到的电压值
ubDmaTransferStatus = 0;//完成标志清0
}
}
/* USER CODE END 3 */
}
实验结果:
PA4引脚的电压值VolDta1为3296mV,PA5引脚的电压值VolDta2为3297mV。
六.工程源代码下载
通过网盘分享的文件:18.ADC_DMA实验.zip
链接: https://pan.baidu.com/s/1dxaaRYC9Bk7E5NJ2vWLhtg 提取码: hfn5
如果链接失效,可以联系博主给最新链接
程序下载下来之后解压就行
七.小结
使用DMA进行数据收发能够提高数据传输的效率和可靠性。其次,使用DMA进行串口数据收发可以减轻CPU的负担。