STM32CUBEMX--3ADC通过DMA方式采样,USART打印
- 概述
- 硬件准备
- 选择芯片型号
- 配置时钟源
- 配置时钟树
- 串口配置
- ADC配置
- 生成工程设置
- 生成代码
- 配置keil
- 代码
- 演示效果
- 教学视频
- 最后
概述 直接存储器访问(DMA)用于在外设与存储器之间以及存储器与存储器之间提供高速数据传输。可以在无需任何CPU操作的情况下通过DMA快速传输传输。这样节省的CPU资源可供其它操作使用。
DMA允许在后台执行数据传输,无需Cortex-MO处理器干预。在此操作过程中,主处理器可以执行其它任务,仅当整个数据块需要处理时,才会中断主处理器。这样即使传输大量数据也不会对系统性能造成太大影响。
DMA主要用于为不同的外设模块实现集中数据缓冲存储(通常在系统SRAM中)。与分布式解决方案(其中每个外设都需要实现自己的本地数据存储)相比,DMA解决方案在硅片成本和功耗方面的成本较低。
根据使用的产品型号的不同,有一个或两个DMA模块。
STM32F0XX DMA控制器总共有5个通道用于DMA1,每个通道都专门管理来自一个或多个外设的存储器访问请求。它具有一个仲裁器,用于处理不同的DMA请求的优先级。
本篇文章主要介绍如何使用STM32CubeMX实现ADC在DMA下快速采集,并且打印出去。
非DMA接收请查看:https://blog.csdn.net/qq_24312945/article/details/109685401
文章图片
硬件准备 首先需要准备一个开发板,这里我准备的是NUCLEO-F030R8的开发板:
文章图片
选择芯片型号 使用STM32CUBEMX选择芯片stm32f030r8,如下所示:
文章图片
配置时钟源
HSE与LSE分别为外部高速时钟和低速时钟,在本文中使用内置的时钟源,故都选择Disable选项,如下所示:
文章图片
配置时钟树 STM32F0的最高主频到48M,所以配置48即可:
文章图片
串口配置 本次实验使用的串口1进行串口通信,波特率配置为115200。
文章图片
ADC配置 STM32f030中,有一个ADC(模拟/数字转换器),每个 ADC 有 12 位、 10 位、 8 位和 6 位可选,每个ADC有16个外部通道、2个内部通道和一个VBAT 通道的信号。
本文将开ADC的IN0、IN1、IN4一共三个通道,来分别读取ADC,由于串口2和IN2,IN3复用,故不使用IN2、IN3。配置如下:
文章图片
开启DMA:
文章图片
打开中断:
文章图片
生成工程设置 最后设置生成独立的初始化文件:
文章图片
生成代码
文章图片
配置keil 【单片机|STM32CUBEMX(3)--ADC通过DMA方式采样,USART打印】
文章图片
代码 在main.c中,添加头文件,若不添加会出现 identifier “FILE” is undefined报错。
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */
函数声明和串口重定向:
/* USER CODE BEGIN PFP */
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/* USER CODE END PFP */
/* USER CODE BEGIN 0 */
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
/* USER CODE END 0 */
变量定义:
/* USER CODE BEGIN 1 */
uint32_t ADC_1, ADC_2,ADC_3;
//各采样30次,故30*3为90
uint32_t ADC_Value[90];
uint8_t i;
/* USER CODE END 1 */
使用DMA传输:
/* USER CODE BEGIN 2 */
HAL_ADC_Start_DMA(&hadc,(uint32_t*)&ADC_Value,90);
//使用DMA传输
/* USER CODE END 2 */
主循环:
/* USER CODE BEGIN WHILE */
while (1)
{
//放个延迟,防止程序运行第一次读出数据有误
HAL_Delay(100);
ADC_1=0;
ADC_2=0;
ADC_3=0;
for(i=0,ADC_1=0,ADC_2=0;
i<90;
)
{
ADC_1+=ADC_Value[i++];
ADC_2+=ADC_Value[i++];
ADC_3+=ADC_Value[i++];
}
printf("ADC数据如下\n");
//除以30为求30次平均ADC值,乘以3.3为以3.3电压为基准,除以4096为ADC配置为12位printf("ADC_IN0=%1.4f\r\n",ADC_1/30*3.3f/4096);
printf("ADC_IN1=%1.4f\r\n",ADC_2/30*3.3f/4096);
printf("ADC_IN2=%1.4f\r\n",ADC_3/30*3.3f/4096);
/* USER CODE END WHILE *//* USER CODE BEGIN 3 */
HAL_Delay(900);
}
/* USER CODE END 3 */
演示效果 设定adc1口接3.3V,adc2口接GND,adc口接1.5V,输出如下。
文章图片
教学视频 https://www.bilibili.com/video/BV1R541137rT
最后 以上的代码会在Q群里分享。QQ群:615061293。
或者关注微信公众号『记贴』,持续更新文章和学习资料,可加作者的微信交流学习!
文章图片
推荐阅读
- #应广单片机|应广PMS154C(1)--11位PWM输出
- #涂鸦|涂鸦模组开发(压力传感器HX711)——3. 涂鸦模组数据通信
- 笔记|4G/5G远程网络遥控,图传系统-无人车-无人船-无人机械制作方法
- 数据结构与算法|315,关于《C程序设计伴侣》一书致人民邮电出版社的公开信
- 编程语言|华为天才少年自制B站百大Up奖杯!网友(技术难度不高,但侮辱性极强)
- Linux|I.MX6ULL学习笔记(二)—uboot移植
- 服务器应用散热控制专用灵动微32位MCU应用案例
- Arduino|Arduino光敏传感器控制LED灯亮度
- 嵌入式|以太网口&arm&mos&推挽开漏&上下拉&高低边&时域频域傅里叶