IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> Cubemx与HAL库系列教程|ADC+DMA多通道采集详解 -> 正文阅读

[嵌入式]Cubemx与HAL库系列教程|ADC+DMA多通道采集详解

什么是ADC

资料获取见文末

你以为的ADC

哈哈,开个玩笑~~~

说起来ADC,先来聊聊模拟信号与数字信号,简单来说就是

模拟信号与数字信号简介

  • 模拟信号

模拟电压信号在时间上和幅值上均是连续的信号叫做模拟信号。此类信号的特点是,在一定动态范围内幅值可取任意值。

  • 数字信号

与模拟信号相对应,时间和幅值均离散( 不连续 ) 的信号叫做数字信号。数字信号的特点是幅值只可以取有限个值。

下文引自:

https://baijiahao.baidu.com/s?id=1701463655357562703&wfr=spider&for=pc

通过观察声音的波形我们就会发现:

模拟信号在一段连续的时间范围内可以在任意时间点呈现任意数值,但是这种数值是随着时间连续变化。

数字信号的取值是离散的二进制数,它和具有连续波形的模拟信号所展现出来的东西千差万别。

模拟信号与数字信号如何相互转换

模拟信号一般通过脉码调制PCM的方法量化调制成数字信号,这个动作叫做模数转换。模拟信号会经过采样、量化、编码等一系列的动作最终转化成能被存储介质存储的一串0和1组成的数字信号。

也即是我们本次要介绍的ADC(analogue-to-digital conversion),模数转换。

数字信号也可以还原成模拟信号。这种转化器件简称DAC,基本由即权电阻网络、运算放大器、基准电源和模拟开关组成。

STM32 ADC介绍

上面说了一大堆,还是属于比较基础的介绍,有兴趣的小伙伴可以多多了解下AD转换器构成,实现原理,通信原理相信都学过,PCM编码都忘了吧,哈哈,好巧,我也忘了...

STM32 拥有 1~3 个 ADC(STM32F101/102 系列只有 1 个 ADC),这些 ADC 可以独立使用, 也可以使用双重模式(提高采样率)。

STM32 的 ADC 是 12 位逐次逼近型的模拟数字转换器。 它有 18 个通道,可测量 16 个外部和 2 个内部信号源。各通道的 A/D 转换可以单次、连续、扫 描或间断模式执行。ADC 的结果可以左对齐或右对齐方式存储在 16 位数据寄存器中。

STM32 的 ADC 最大的转换速率为 1Mhz,也就是转换时间为 1us(在 ADCCLK=14M,采样周期为 1.5 个 ADC 时钟下得到),不要让 ADC 的时钟超过 14M,否则将导致结果准确度下降

  • 转换时间

采样周期最小是 1.5 个,即如果我们要达到最快的采样,那么应该设置采样周期为 1.5 个周期,这里说的周期就是1/ADC_CLK

ADC 的总转换时间跟 ADC 的输入时钟和采样时间有关,其公式如下:

Tconv = 采样时间 + 12.5 个周期

其中 Tconv 为 ADC 总转换时间,当 ADC_CLK=14Mhz 的时候,并设置 1.5 个周期的采样时间,则 Tcovn=1.5+12.5=14 个周期=1us。通常经过 ADC 预分频器能分频到最大的时钟只能是 12M,采样周期设置为 1.5 个周期,算出最短的转换时间为 1.17us

外部的 16 个通道在转换的时候可分为 2 组通道:规则通道组和注入通道组,其中规则通道组最多有 16 路,注入通道组最多有 4 路

  • 规则通道组:

从名字来理解,规则通道就是一种规规矩矩的通道,类似于正常执行的程序。通常我们使用的都是这个通道

  • 注入通道组:

从名字来理解,注入即为插入,是一种不安分的通道,类似于中断。当程序正常往下执行时,中断可以打断程序的执行。同样如果在规则通道转换过程中,有注入通道插队,那么就要先转换完注入通道,等注入通道转换完成后,再回到规则通道的转换流程

  • DMA 请求

规则和注入通道转换结束后,除了产生中断外,还可以产生 DMA 请求,把转换好的数据直接存储在内存里面。

要注意的是只有 ADC1 和 ADC3 可以产生DMA 请求。一般我们在使用 ADC 的时候都会开启 DMA 传输

  • 转换方式

单次转换: 顾名思义,ADC 执行一次转换。想要在转换需要再次开启

连续转换:

ADC 结束一个转换后立即启动一个新的转换,需要注意的是:此模式无法连续转换注入通道。连续模式下唯一的例外情况是,注入通道配置为在规则通道之后自动转换

STM ADC引脚映射

有些没有的管脚就不用关心了,比如F1的没有PF6-10引脚

DMA通道映射

cubemx 配置

时钟之类的配置,劳烦各位小伙伴补补课,翻翻小飞哥前面的文章哈,直接进入正题

单通道DMA转换

时钟配置为分频之后为12MHZ

选择 ADC1->IN8->PB0

需要关注的几个点,扫描模式,这个在单通道时是无法使能的,只有多通道才可以开启,连续转换模式,根据自己实际需求决定是连续转换还是单次转换,触发方式,触发方式是非常多的,可以软件触发,PWM触发,定时器触发,也是根据自己的需要选择即可

中断,需要就开启,不需要就不用开启,直白~

DMA配置,DMA的中断是默认开启的,并且无法配置关闭

配置很简单,你学废了吗...

代码实现

ADC配置的代码

关于DMA的配置

extern?ADC_HandleTypeDef?hadc1;
extern?DMA_HandleTypeDef?hdma_adc1;

uint16_t?adc_buffer[50]?=?{0};
static?void?prvPrintTask(?void?*pvParameters?)
{
?float?adc_value?=?0;
?
?HAL_ADCEx_Calibration_Start(&hadc1);
?HAL_ADC_Start_DMA(&hadc1,(uint32_t?*)adc_buffer,50);
?int?iIndexToString;
?/*?Two?instances?of?this?task?are?created.?The?task?parameter?is?used?to?pass
?an?index?into?an?array?of?strings?into?the?task.?Cast?this?to?the?required?type.?*/
?iIndexToString?=?(?int?)?pvParameters;
?for(?;;?)
?{

?for(int?index?=0;index?<?50;index++)
?{
??adc_value?+=?adc_buffer[index];
?}
?adc_value/=50;
?
?adc_value?=?adc_value?*3.3/(1<<12);
?debug_printf("\nadc_value?=?%.2f\n",adc_value);
??
?vTaskDelay(?(?rand()?&?0x1FF?)?);
?}
}

配置为连续模式,DMA为循环模式,数据在buffer中不断循环更新

配置为不连续模式,只转换一次

我是直接接到3.3V测试的,精度还可以

接GND,是有一些非零值的,所以必要的滤波还是要做的,这里我是用了最简单的均值滤波处理

多通道DMA转换

配置和单通道有些不同,扫描模式就可以打开了,通道数可以选择,我们选择4即可,下面的顺序就是我们要转换的顺序

/*?ADC1?init?function?*/
void?MX_ADC1_Init(void)
{

??/*?USER?CODE?BEGIN?ADC1_Init?0?*/

??/*?USER?CODE?END?ADC1_Init?0?*/

??ADC_ChannelConfTypeDef?sConfig?=?{0};

??/*?USER?CODE?BEGIN?ADC1_Init?1?*/

??/*?USER?CODE?END?ADC1_Init?1?*/
??/**?Common?config
??*/
??hadc1.Instance?=?ADC1;
??hadc1.Init.ScanConvMode?=?ADC_SCAN_ENABLE;
??hadc1.Init.ContinuousConvMode?=?ENABLE;
??hadc1.Init.DiscontinuousConvMode?=?DISABLE;
??hadc1.Init.ExternalTrigConv?=?ADC_SOFTWARE_START;
??hadc1.Init.DataAlign?=?ADC_DATAALIGN_RIGHT;
??hadc1.Init.NbrOfConversion?=?4;
??if?(HAL_ADC_Init(&hadc1)?!=?HAL_OK)
??{
????Error_Handler();
??}
??/**?Configure?Regular?Channel
??*/
??sConfig.Channel?=?ADC_CHANNEL_8;
??sConfig.Rank?=?ADC_REGULAR_RANK_1;
??sConfig.SamplingTime?=?ADC_SAMPLETIME_1CYCLE_5;
??if?(HAL_ADC_ConfigChannel(&hadc1,?&sConfig)?!=?HAL_OK)
??{
????Error_Handler();
??}
??/**?Configure?Regular?Channel
??*/
??sConfig.Channel?=?ADC_CHANNEL_9;
??sConfig.Rank?=?ADC_REGULAR_RANK_2;
??if?(HAL_ADC_ConfigChannel(&hadc1,?&sConfig)?!=?HAL_OK)
??{
????Error_Handler();
??}
??/**?Configure?Regular?Channel
??*/
??sConfig.Channel?=?ADC_CHANNEL_10;
??sConfig.Rank?=?ADC_REGULAR_RANK_3;
??if?(HAL_ADC_ConfigChannel(&hadc1,?&sConfig)?!=?HAL_OK)
??{
????Error_Handler();
??}
??/**?Configure?Regular?Channel
??*/
??sConfig.Channel?=?ADC_CHANNEL_11;
??sConfig.Rank?=?ADC_REGULAR_RANK_4;
??if?(HAL_ADC_ConfigChannel(&hadc1,?&sConfig)?!=?HAL_OK)
??{
????Error_Handler();
??}
??/*?USER?CODE?BEGIN?ADC1_Init?2?*/

??/*?USER?CODE?END?ADC1_Init?2?*/

}

主函数中编写如下代码:

为了更直观的观察效果,定义二维数组,每个存储4个值,可以看到,4个通道是依次转换的,各取10个值,求平均值

extern?ADC_HandleTypeDef?hadc1;
extern?DMA_HandleTypeDef?hdma_adc1;

uint16_t?adc_buffer[10][4]?=?{0,0};
??
static?void?prvPrintTask(?void?*pvParameters?)
{
?float?adc_value[4]?=?{0};
?HAL_ADCEx_Calibration_Start(&hadc1);
?HAL_ADC_Start_DMA(&hadc1,(uint32_t?*)adc_buffer,40);
?int?iIndexToString;
?/*?Two?instances?of?this?task?are?created.?The?task?parameter?is?used?to?pass
?an?index?into?an?array?of?strings?into?the?task.?Cast?this?to?the?required?type.?*/
?iIndexToString?=?(?int?)?pvParameters;
?for(?;;?)
?{
??for(int?i=0;i<4;i++)
??{
???for(int?j=0;j<10;j++)
???{
????adc_value[i]+=adc_buffer[j][i];
???}
??adc_value[i]=(float)adc_value[i]/(10*4096)*3.3;//求平均值并转换成电压值
??//ADC_Value[i]=(float)sum/10;
??printf("ADC_Value[%d]?=?%.2f\n",i,adc_value[i]);
?}??
??vTaskDelay(?(?rand()?&?0x1FF?)?);
??}
}

经验交流

关注公众号,后台回复“ADC”,即可获取本文源码~

欢迎添加小飞哥好友,进群一起交流有趣的话题,探讨有趣的知识

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-10-30 12:41:30  更:2021-10-30 12:42:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 8:29:01-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码