打印
[应用相关]

ADC通过DMA方式采样,USART打印

[复制链接]
532|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
概述
直接存储器访问(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



使用特权

评论回复
沙发
guanjiaer|  楼主 | 2021-8-3 12:06 | 只看该作者
硬件准备

首先需要准备一个开发板,这里我准备的是NUCLEO-F030R8的开发板:

选择芯片型号

使用STM32CUBEMX选择芯片stm32f030r8,如下所示:


使用特权

评论回复
板凳
guanjiaer|  楼主 | 2021-8-3 12:07 | 只看该作者
配置时钟源HSE与LSE分别为外部高速时钟和低速时钟,在本文中使用内置的时钟源,故都选择Disable选项,如下所示:
  • 1


使用特权

评论回复
地板
guanjiaer|  楼主 | 2021-8-3 12:08 | 只看该作者
配置时钟树

STM32F0的最高主频到48M,所以配置48即可:


使用特权

评论回复
5
guanjiaer|  楼主 | 2021-8-3 12:09 | 只看该作者
串口配置

本次实验使用的串口1进行串口通信,波特率配置为115200。


使用特权

评论回复
6
guanjiaer|  楼主 | 2021-8-3 12:09 | 只看该作者
ADC配置
STM32f030中,有一个ADC(模拟/数字转换器),每个 ADC 有 12 位、 10 位、 8 位和 6 位可选,每个ADC有16个外部通道、2个内部通道和一个VBAT 通道的信号。
本文将开ADC的IN0、IN1、IN4一共三个通道,来分别读取ADC,由于串口2和IN2,IN3复用,故不使用IN2、IN3。配置如下:



使用特权

评论回复
7
guanjiaer|  楼主 | 2021-8-3 12:11 | 只看该作者
开启DMA:

打开中断:

使用特权

评论回复
8
guanjiaer|  楼主 | 2021-8-3 12:12 | 只看该作者
生成工程设置

最后设置生成独立的初始化文件:


使用特权

评论回复
9
guanjiaer|  楼主 | 2021-8-3 12:13 | 只看该作者
生成代码

配置keil


使用特权

评论回复
10
guanjiaer|  楼主 | 2021-8-3 12:15 | 只看该作者
代码
在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 */


使用特权

评论回复
11
guanjiaer|  楼主 | 2021-8-3 12:16 | 只看该作者
演示效果

设定adc1口接3.3V,adc2口接GND,adc口接1.5V,输出如下。


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

72

主题

3886

帖子

2

粉丝