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

news2024/9/24 17:20:12

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;        //配置为无上下拉
    //初始化引脚PC3
    GPIO_InitStructure.GPIO_Pin = R_ADC_GPIO_PIN1;           //配置引脚PC3引脚
    GPIO_Init(R_ADC_GPIO_PORT1,&GPIO_InitStructure);         //初始化引脚
    //初始化引脚PA4
    GPIO_InitStructure.GPIO_Pin = R_ADC_GPIO_PIN2;           //配置引脚PC4引脚
    GPIO_Init(R_ADC_GPIO_PORT2,&GPIO_InitStructure);         //初始化引脚c
    //初始化引脚PA6
    GPIO_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;                  //采用直连,不适用FIFO
    DMA_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);                  //使能ADC
    ADC_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("-------------------光感通道-------------------");
            else
                printf("-------------------悬空通道-------------------");
            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.coloradmin.cn/o/1272206.html

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

相关文章

Peter算法小课堂—高精度乘法

给大家看个小视频13 高精度算法 乘法_哔哩哔哩_bilibili 乘法竖式 大家觉得Plan A好&#xff0c;还是Plan B好呢&#xff08;对于计算机来说&#xff09;&#xff1f;那显然是B啦 x*y问题 mul思路&#xff1a;mul()函数返回x数组乘y数组的积&#xff0c;保存在z数组。根据上…

基于SpringBoot的旅游网站的设计与实现

摘 要 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff0c;旅游网站当然也不能排除在外&#xff0c;随着旅游网站的不断成熟&#xff0c;它彻底改变了过去传统的旅游网站方式&#xff0c;不仅使旅游管理…

three.js结合vue

作者&#xff1a;baekpcyyy&#x1f41f; 1.搭建环境 ps&#xff1a;这里要按照node.js在之前有关vue搭建中有介绍 新建文件夹并在vsc终端中打开 1.输入vite创建指令 npm init vitelatest然后我们cd进入刚才创建的目录下 npm install安装所需依赖 npm run dev启动该项目 …

Python正则表达式:match()和search()函数全面解读

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 在Python中&#xff0c;正则表达式是强大的工具&#xff0c;能够用于文本匹配、搜索和替换。re模块提供了许多函数来处理正则表达式&#xff0c;其中match()和search()是两个常用的函数。本文将深入探讨这两个函…

论文复现代码《基于自适应哈夫曼编码的密文可逆信息隐藏算法》调试版

前言 本文展示论文《基于自适应哈夫曼编码的密文可逆信息隐藏算法》的复现代码。代码块的结构如下&#xff1a; 其中&#xff0c;每个代码块都包含了测试该代码块的功能的主函数代码&#xff0c;使用时可放心运行&#xff0c;前提是你按照这个包结构把文件命名改好&#xff0c…

vue3 keep-alive页面切换报错:parentComponent.ctx.deactivate is not a function

问题&#xff1a; <router-view v-slot"{ Component }"><keep-alive ><component :is"Component" v-if"$route.meta.keepAlive" /></keep-alive><component :is"Component" v-if"!$route.meta.keepA…

【软件测试】白盒测试和黑盒测试

一、软件测试基本分类 一般地&#xff0c;我们将软件测试活动分为以下几类&#xff1a;黑盒测试、白盒测试、静态测试、动态测试、手动测试、自动测试等等。 黑盒测试 黑盒测试又叫功能测试、数据驱动测试或给予需求规格说明书的功能测试。这种测试注重于测试软件的功能性需…

java二十章多线程

概念 有很多工作是可以同时完成的&#xff0c;这种思想放在Java中被称为并发&#xff0c;并发完成每一件事被称为线程。 程序员可以在程序中执行多个线程&#xff0c;每一个线程完成一个功能//与其他线程并发执行&#xff0c;这种机制被称为多线程&#xff0c;并不算所有编程…

PLC:200smart(13-16章)

PLC&#xff1a;200smart 第十三章2、带参子程序3、将子程序设置成库文件 第十三章 项目ValueValue主程序MAIN一个项目只能有一个&#xff0c;循环扫描子程序SBR_0项目中最多有128个&#xff0c;只有在调用时 才执行&#xff08;子程序可以嵌套其他子程序&#xff0c;最多八层…

广州华锐视点:基于VR元宇宙技术开展法律法规常识在线教学,打破地域和时间限制

随着科技的飞速发展&#xff0c;人类社会正逐渐迈向一个全新的时代——元宇宙。元宇宙是一个虚拟的、数字化的世界&#xff0c;它将现实世界与数字世界紧密相连&#xff0c;为人们提供了一个全新的交流、学习和娱乐平台。在这个充满无限可能的元宇宙中&#xff0c;法律知识同样…

构建个人代理池:使用GitHub项目proxy_pool的搭建配置及代码接口详解

手把手教你搭建代理IP池&#xff1a; 项目简介&#xff1a; ​ 爬虫代理IP池项目,主要功能为定时采集网上发布的免费代理验证入库&#xff0c;定时验证入库的代理保证代理的可用性&#xff0c;提供API和CLI两种使用方式。同时你也可以扩展代理源以增加代理池IP的质量和数量。…

分治法之归并排序

思路: 将待排序数组分成两个子数组&#xff0c;计算中间位置mid。对左半部分进行递归排序&#xff0c;得到一个有序的子数组。对右半部分进行递归排序&#xff0c;得到另一个有序的子数组。合并两个有序的子数组&#xff0c;得到一个完整的有序数组。 示例图: 代码: #include&…

WPF绘制进度条(弧形,圆形,异形)

前言 WPF里面圆形进度条实现还比较麻烦,主要涉及到的就是动态绘制进度条的进度需要用到简单的数学算法。其实原理比较简单,我们需要的是话两条重叠的弧线,里面的弧线要比里面的弧线要宽,这样简单的雏形就出来了。 基础写法 我们可以用Path来绘制弧线,代码如下: <Gr…

Linux:服务器管理工具宝塔(bt)安装教程

一、简介 bt宝塔Linux面板是提升运维效率的服务器管理软件&#xff0c;支持一键LAMP/LNMP/集群/监控/网站/FTP/数据库/JAVA等多项服务的管理功能 二、安装 使用 SSH 连接工具&#xff0c;如堡塔SSH终端连接到您的 Linux 服务器后&#xff0c;挂载磁盘&#xff0c;根据系统执…

C++基础——文件操作

文章目录 1 概述2 文本文件2.1 写文件2.1.1 写文件流程2.1.2 文件打开方式 2.2 读文件 3 二进制文件3.1 写文件3.2 读文件 1 概述 程序最基本的操作之一就是文件操作&#xff0c;程序运行时的数据都是临时数据&#xff0c;当程序结束后就不复存在了。通常都是通过文件或其他持…

酷狗音乐app 评论signature

文章目录 声明目标加密参数定位翻页逻辑代码实现 声明 本文章中所有内容仅供学习交流&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff0c;若有侵权&#xff0c;请私信我立即删除&#xff01; 目标 复制curl转python # -*- c…

SQL 数据操作技巧:SELECT INTO、INSERT INTO SELECT 和 CASE 语句详解

SQL SELECT INTO 语句 SELECT INTO 语句将数据从一个表复制到一个新表中。 SELECT INTO 语法 将所有列复制到新表中&#xff1a; SELECT * INTO newtable [IN externaldb] FROM oldtable WHERE condition;只复制一些列到新表中&#xff1a; SELECT column1, column2, colu…

MySQL三大日志详细总结(redo log undo log binlog)

MySQL日志 包括事务日志&#xff08;redolog undolog&#xff09;慢查询日志&#xff0c;通用查询日志&#xff0c;二进制日志&#xff08;binlog&#xff09; 最为重要的就是binlog&#xff08;归档日志&#xff09;事务日志redolog&#xff08;重做日志&#xff09;undolog…

数据结构(超详细讲解!!)第二十六节 图(上)

1.基本概念 图&#xff08;Graph&#xff09;是一种较线性表和树更为复杂的非线性结构。是对结点的前趋和后继个数不加限制的数据结构&#xff0c;用来描述元素之间“多对多”的关系(即结点之间的关系是任意的)。 一个图G &#xff08;V&#xff0c;E&#xff09;由顶点&…

从谷歌搜索结果出现 AI 生成的图片谈起:AI的利与弊

随着人工智能&#xff08;AI&#xff09;的不断发展&#xff0c;其应用领域也越来越广泛。谷歌搜索是现代人日常生活中的一个常用工具&#xff0c;经常用于获取各种信息。最近&#xff0c;谷歌搜索结果中甚至出现了由AI生成的图片&#xff0c;这引发了人们对AI技术的讨论。 首…