030 - STM32学习笔记 - ADC(四) 独立模式多通道DMA采集

030 - STM32学习笔记 - ADC(四) 独立模式多通道DMA采集

在这里插入图片描述

中断模式和DMA模式进行单通道模拟量采集,这节继续学习独立模式多通道DMA采集,使用到的引脚有之前使用的PC3(电位器),PA4(光敏电阻)、PA6(悬空,可通过杜邦线接3V3或者GND进行测试)。对应引脚通道如下表:

在这里插入图片描述

程序仍然在上节的基础上进行修改,先附上关于GPIO宏定义的部分:

//选择ADC1
#define R_ADC                   ADC1
#define R_ADC_CLK               RCC_APB2Periph_ADC1
//电位器 PC3
#define R_ADC_GPIO_PORT1         GPIOC
#define R_ADC_GPIO_PIN1          GPIO_Pin_3
#define R_ADC_GPIO_CLK1          RCC_AHB1Periph_GPIOC
#define R_ADC_CHANNEL_PC3        ADC_Channel_13					//通道13
//光敏电阻 PA4
#define R_ADC_GPIO_PORT2         GPIOA
#define R_ADC_GPIO_PIN2          GPIO_Pin_4
#define R_ADC_GPIO_CLK2          RCC_AHB1Periph_GPIOA
#define R_ADC_CHANNEL_PA4        ADC_Channel_4					//通道4
//悬空 PA6
#define R_ADC_GPIO_PORT3         GPIOA
#define R_ADC_GPIO_PIN3          GPIO_Pin_6
#define R_ADC_GPIO_CLK3          RCC_AHB1Periph_GPIOA
#define R_ADC_CHANNEL_PA6        ADC_Channel_6					//通道6

在使用之前,先来对GPIO进行初始化配置,配置如下:

/** @brief  初始化ADC GPIO引脚* @parm   无* @retval 无*/
static void R_ADC_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_AHB1PeriphClockCmd(R_ADC_GPIO_CLK1 | R_ADC_GPIO_CLK2 | R_ADC_GPIO_CLK3,ENABLE);          //开启ADC外设引脚时钟//通用配置GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;           //配置引脚为模拟输入 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;        //配置为无上下拉//初始化引脚PC3GPIO_InitStructure.GPIO_Pin = R_ADC_GPIO_PIN1;           //配置引脚PC3引脚GPIO_Init(R_ADC_GPIO_PORT1,&GPIO_InitStructure);         //初始化引脚//初始化引脚PA4GPIO_InitStructure.GPIO_Pin = R_ADC_GPIO_PIN2;           //配置引脚PC4引脚GPIO_Init(R_ADC_GPIO_PORT2,&GPIO_InitStructure);         //初始化引脚c//初始化引脚PA6GPIO_InitStructure.GPIO_Pin = R_ADC_GPIO_PIN3;           //配置引脚PA6引脚GPIO_Init(R_ADC_GPIO_PORT3,&GPIO_InitStructure);         //初始化引脚
}

对于ADC来说,我们使用的是一个ADC,即ADC1,所以关于ADC Common的初始化部分不需要进行修改。这里代码就不网上贴了,不清楚了可以翻看上一节的内容。

下来再看ADC Init初始化结构体,这里有几处需要修改一下:

1、这次因为要对3个通道进行数据采集,因此需要将通道数改为3,为了方便后期更改,这里将通道数进行宏定义:

#define ADC_NOFChannel          3					   //宏定义通道数,位于bsp_adc.h中
ADC_InitStructure.ADC_NbrOfConversion = ADC_NOFChannel;   //转换通道为3,采用宏定义

2、通道数超过1个时,需要开启扫描模式,需要将扫描模式使能:

ADC_InitStructure.ADC_ScanConvMode = ENABLE;               //多通道下用到扫描模式

3、配置多通道的转换顺序,根据我们实际的需求,需要对多个通道的采集先后顺序进行排序,排序如下:

//配置ADC通道转换顺序为1,第一个转换,采集周期为3个周期   
ADC_RegularChannelConfig(R_ADC,R_ADC_CHANNEL_PC3,1,ADC_SampleTime_3Cycles);
//配置ADC通道转换顺序为2,第二个转换,采集周期为3个周期   
ADC_RegularChannelConfig(R_ADC,R_ADC_CHANNEL_PA4,2,ADC_SampleTime_3Cycles);
//配置ADC通道转换顺序为1,第二个转换,采集周期为3个周期
ADC_RegularChannelConfig(R_ADC,R_ADC_CHANNEL_PA6,3,ADC_SampleTime_3Cycles);

关于ADC初始化及DMA初始化的完整程序附在下面:

/** @brief  配置ADC引脚工作模式及DMA* @parm   无* @retval 无*/
static void R_ADC_Mode_Config(void)
{DMA_InitTypeDef DMA_InitStructure;ADC_InitTypeDef ADC_InitStructure;ADC_CommonInitTypeDef ADC_CommonInitStructure;//-----------------DMA Init结构体参数初始化-----------------//RCC_AHB1PeriphClockCmd(R_ADC_DMA_CLK,ENABLE);           //开启DMA时钟DMA_InitStructure.DMA_PeripheralBaseAddr = R_ADC_DR_ADDR;       //设置ADC外设基地址,为ADC数据寄存器地址DMA_InitStructure.DMA_Memory0BaseAddr = (u32)ADC_Value;        //存储器地址,地址为内部SRAM变量DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;         //配置数据传输方向为外设到存储器DMA_InitStructure.DMA_BufferSize = ADC_NOFCHANNEL;              //配置缓冲区大小,大小取决于一次传输的量DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;    //外设寄存器只有一个,不用递增DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;            //存储器地址也只有一个,不递增DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外设数据大小为半字(两个字节)DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;     //与外设相同DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                         //循环传输DMA_InitStructure.DMA_Priority = DMA_Priority_High;                     //传输优先级为高DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;                  //采用直连,不适用FIFODMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;       //FIFO禁止,下面不用配置DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;DMA_InitStructure.DMA_Channel = R_ADC_DMA_CHANNEL;              //选择DMA通道DMA_Init(R_ADC_DMA_STREAM,&DMA_InitStructure);DMA_Cmd(R_ADC_DMA_STREAM,ENABLE);RCC_APB2PeriphClockCmd(R_ADC_CLK,ENABLE);               //开启ADC时钟//-----------------ADC Common结构体参数初始化--------------//ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;        //设置模式为独立模式ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;     //设置为4分频ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;     //禁止DMA直接访问模式ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_10Cycles;       //设置采样间隔周期为10个周期ADC_CommonInit(&ADC_CommonInitStructure);//-----------------ADC Init结构体参数初始化--------------//ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;      //设置ADC采样分辨率为12位ADC_InitStructure.ADC_ScanConvMode = ENABLE;               //多通道下用到扫描模式ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;          //设置为连续转换ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;     //禁用外部边沿触发ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;      //设置为右对齐ADC_InitStructure.ADC_NbrOfConversion = ADC_NOFCHANNEL;                  //转换通道为3,采用宏定义ADC_Init(R_ADC,&ADC_InitStructure);ADC_RegularChannelConfig(R_ADC,R_ADC_CHANNEL_PC3,1,ADC_SampleTime_3Cycles);        //配置ADC通道转换顺序为1,第一个转换,采集周期为3个周期ADC_RegularChannelConfig(R_ADC,R_ADC_CHANNEL_PA4,2,ADC_SampleTime_3Cycles);        //配置ADC通道转换顺序为2,第二个转换,采集周期为3个周期ADC_RegularChannelConfig(R_ADC,R_ADC_CHANNEL_PA6,3,ADC_SampleTime_3Cycles);        //配置ADC通道转换顺序为1,第二个转换,采集周期为3个周期//ADC_ITConfig(R_ADC,ADC_IT_EOC,ENABLE);      //ADC转换结束产生中断,在中断服务程序中读取转换数值ADC_DMARequestAfterLastTransferCmd(R_ADC, ENABLE);ADC_DMACmd(R_ADC,ENABLE);ADC_Cmd(R_ADC,ENABLE);                  //使能ADCADC_SoftwareStartConv(R_ADC);           //开始ADC转换,由软件触发
}

这里我们在bsp_adc.c中定义一个数组,用来存放三个通道采集到的数据,再在main函数中用extern调用,再定义用来存放转换后的数组。main中程序如下:

extern __IO uint16_t ADC_Value[ADC_NOFCHANNEL];
float ADC_Vol[ADC_NOFCHANNEL] = {0};int main(void)
{DEBUG_USART1_Config();R_ADC_Init();SysTick_Init();printf("\r\n---------------ADC实验(独立模式多通道DMA模式)----------------\r\n");while(1){Delay_ms(1000);for(int i = 0;i <ADC_NOFCHANNEL;i++){if(i == 0)printf("-------------------电位器通道-------------------");else if(i == 1)printf("-------------------光感通道-------------------");elseprintf("-------------------悬空通道-------------------");printf("\r\n ADC数据(未转换) = 0x%04X \r\n",ADC_Value[i]);ADC_Vol[i] =(float)(ADC_Value[i]*3.3/4096); // 读取转换的 AD 值 printf("\r\n ADC数据(已转换) = %.2f V \r\n",ADC_Vol[i]);}}
}

实验效果如下:

在这里插入图片描述

1、电位器通道可以通过调整电位器阻值查看采集结果;

2、光感通道可以通过遮挡光敏电阻或者手机闪光灯照射查看采集结果(用手遮了一下光敏模块);

3、悬空通道可以接3.3V或者GND通道来查看采集结果(这里接到GND上的)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/187092.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【刷题笔记】串联所有单词的子串||暴力通过||滑动窗口

串联所有单词的子串 1 题目描述 https://leetcode.cn/problems/substring-with-concatenation-of-all-words/ 给定一个字符串 s 和一个字符串数组 words。 words 中所有字符串 长度相同。 s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。 …

基于STC12C5A60S2系列1T 8051单片机的液晶显示器LCD1602显示整数、小数应用

基于STC12C5A60S2系列1T 8051单片机的液晶显示器LCD1602显示整数、小数应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式及配置STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式介绍液晶显示器LCD1602简单介绍IIC通信简单介绍…

【每日一题】1657. 确定两个字符串是否接近-2023.11.30

题目&#xff1a; 1657. 确定两个字符串是否接近 如果可以使用以下操作从一个字符串得到另一个字符串&#xff0c;则认为两个字符串 接近 &#xff1a; 操作 1&#xff1a;交换任意两个 现有 字符。 例如&#xff0c;abcde -> aecdb操作 2&#xff1a;将一个 现有 字符的…

解决plot画图中文乱码问题(macbook上 family ‘sans-serif‘ not found)

一、matplotlib画图中文乱码问题 使用matplotlib.pyplot画图&#xff0c;有中文字体会显示乱码问题&#xff0c;这时需要添加如下代码&#xff1a; import matplotlib.pyplot as pltplt.rcParams["font.sans-serif"] ["SimHei"]二、macbook没有SimHei的…

分布式仿真SNN的思考

我之前实现的仿真完全基于如下图设计的 将整体的网络构成见一个邻接表&#xff0c;突触和神经元作为类分别存储&#xff0c;所以当一个神经元发射脉冲时&#xff0c;很容易的将脉冲传输到突触指向的后神经元。但是在分布式方丈中&#xff0c;由多个进程仿真整体的网络&#xff…

WPS导出的PDF比较糊,和原始的不太一样,将带有SVG的文档输出为PDF

一、在WPS的PPT中 你直接输出PDF可能会导致一些问题&#xff08;比如照片比原来糊&#xff09;/ 或者你复制PPT中的图片到AI中类似的操作&#xff0c;得到的照片比原来糊&#xff0c;所以应该选择打印-->高级打印 然后再另存为PDF 最后再使用AI打开PDF文件再复制到你想用…

基于单片机的排队叫号系统设计

1&#xff0e;设计任务 利用AT89C51单片机为核心控制元件,设计一个节日彩灯门&#xff0c;设计的系统实用性强、操作简单&#xff0c;实现了智能化、数字化。 基本要求&#xff1a;利用单片机AT89C51设计排队叫号机&#xff0c;能实现叫号功能。 创新&#xff1a;能显示叫号…

猫头虎分享ubuntu20.04下VSCode无法输入中文解决方法

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

【EasyExcel】导出excel并支持自定义设置数据行背景颜色等

需求背景&#xff1a; 根据查询条件将列表数据导出&#xff0c;并筛选出满足某个条件的数据&#xff0c;将满足条件的数据的背景颜色设置成黄色。 &#xff08;本文例子如&#xff1a;name出现的次数大于等于2&#xff0c;将相关数据背景颜色都设置为黄色&#xff09; …

算法通关村第一关—链表高频面试题(白银)

链表高频面试题 一、五种方法解决两个链表的第一个公共子节点的问题 面试 02.07.链表相交1.首先想到的是暴力解&#xff0c;将第一个链表中的每一个结点依次与第二个链表的进行比较&#xff0c;当出现相等的结点指针时&#xff0c;即为相交结点。虽然简单&#xff0c;但是时间…

常见智力题汇总

常见智力题汇总 扔瓶子问题扑克牌问题出队问题烧绳子问题赛马问题求出前三名求出前五名 接水问题种树问题硬币问题宝石问题核酸检测问题 笔者最近面试遇到了好几道智力题&#xff0c;这些题目特点就是如果没有见过&#xff0c;很难第一时间思考得到答案&#xff0c;因此笔者面试…

VUE2+THREE.JS项目搭建

THREE项目搭建 简介学习文档推荐搭建1.下载three.js2.新建3DWorkShop.vue文件3.创建utils/three/tool.js4.创建components/three/draw.vue[重点]4.1 引入文件4.2 初始化场景4.3 初始化渲染器4.4 初始化光源4.5 初始化相机(人眼模式)4.6 初始化控制器4.7 初始化动画4.8 添加全局…

功率信号源简介及其应用有哪些内容

功率信号源是一种能够提供稳定输出功率信号的设备或电路。它在许多领域中都有广泛的应用。以下是一些关于功率信号源的内容&#xff1a; 功率信号源简介&#xff1a;功率信号源是一种电子设备或电路&#xff0c;它能够提供稳定的输出功率信号。功率信号源通常由放大器、稳压器、…

rest_framework_django学习笔记一(序列化器)

rest_framework_django学习笔记一(序列化器) 一、引入Django Rest Framework 1、安装 pip install djangorestframework2、引入 INSTALLED_APPS [...rest_framework, ]3、原始RESTful接口写法 models.py from django.db import models 测试数据 仅供参考 INSERT INTO de…

力扣:1419. 数青蛙

题目&#xff1a; 代码&#xff1a; class Solution { public:int minNumberOfFrogs(string croakOfFrogs){string s "croak";int ns.size();//首先创建一个哈希表来标明每个元素出现的次数&#xff01;vector<int>hash(n); //不用真的创建一个hash表用一个数…

如何使用高防CDN防护HTTPS 攻击?有什么优势?

随着互联网的普及&#xff0c;网络安全问题也日益凸显。其中&#xff0c;HTTPS 攻击是一种常见的网络安全威胁&#xff0c;它通过篡改网站数据、窃取用户信息等方式&#xff0c;给网站带来巨大的风险。为了有效防御 HTTPS 攻击&#xff0c;高防 CDN 成为了一个重要的工具。下面…

(项目已开源)社区求助 哪位大佬能不能帮我 将box1 audio 和 box2 slider滑块 和 box3 歌词滚动区域 进行联动

(项目已开源)社区求助 哪位大佬能不能帮我 将box1 audio 和 box2 slider滑块 和 box3 歌词滚动区域 进行联动 链接&#xff1a;https://pan.baidu.com/s/16lpEW6L5jrHfhsG7EXocLw?pwdkryy 提取码&#xff1a;kryy <!--社区求助 哪位大佬能不能帮我 将box1 audio 和 box2 s…

Nginx实现(动静分离)

动静分离应该是听的次数较多的性能优化方案&#xff0c;那先思考一个问题&#xff1a;「「为什么需要做动静分离呢&#xff1f;它带来的好处是什么&#xff1f;」」 其实这个问题也并不难回答&#xff0c;当你搞懂了网站的本质后&#xff0c;自然就理解了动静分离的重要性。先来…

通过C#获取Windows设置的夏令时开关

C#获取Windows夏令时开关 // 获取所有的时区信息 var allTimeZones TimeZoneInfo.GetSystemTimeZones().ToList();通过接口可以看到, 字段SupportsDaylightSavingTime代表是否支持配置夏令时 // 获取当前Window设置的时区 var tmpLocal TimeZoneInfo.Local;但是取Local 信息…

Oracle 单表插入/多表插入(Single Table Insert/Multi-table Insert)

数据库应用中&#xff0c;我们经常需要向表中插入数据&#xff0c;insert语句是最常用的数据插入方式&#xff0c;根据目标表的数量&#xff0c;可以分为单表插入和多表插入。 目录 一、 单表插入&#xff08;Single Table Insert&#xff09; 二、 多表插入&#xff08;Multi-…