细说MCU的ADC模块单通道连续采样的实现方法
目录
一、工程依赖的硬件及背景
二、设计目的
三、建立工程
1、配置GPIO
2、选择时钟源和Debug
3、配置ADC
4、配置系统时钟和ADC时钟
5、配置TIM3
6、配置串口
四、代码修改
1、重定义TIM3中断回调函数
2、启动ADC及重写其回调函数
3、定义用于存储转换结果的数组
4、重定义回调函数
5、在主程序中编写发送数据代码
6、在主程序初始化代码中使能ADC中断和TIM3中断
7、配置printf函数
五、运行并查看结果
在单次测量的例子中,当每次操作按键B1后,都要重复进行启动ADC、等待转换,然后读换结果这些步骤。实际应用中,很多时候是让ADC连续进行采样。此时,可以使能ADC的连续转换。在此转换模式下,ADC完成一次转换后会开始新的转换。
一、工程依赖的硬件及背景
文章依赖的硬件及工程配置参考本文作者的其他文章:细说MCU的ADC模块单通道单次采样的实现方法-CSDN博客文章浏览阅读1.1k次,点赞12次,收藏19次。由于希望在产生按键中断时,启动ADC采样,所以,需要重定义外部中断EXTI的回调函数。这个回调函数可以写在main.c文件后面的一个注释对中。https://wenchm.blog.csdn.net/article/details/139884221
二、设计目的
信号源:通过TIM3连续产生PWM波形,并通过LD2(PA5)显示并输出。
PA0为ADC1的信号输入,即把PA5的信号输出通过导线连接给PA0。
USART2为串口输出。ADC1_IN1采集信号源输入,达到ADCSampleFlag==1时,开始通过串口发送数据到显示设备,直到发送数据完毕时,ADCSampleFlag==0;
正常情况下:ADCSampleFlag==0时,ADC1开始采集数据到寄存器,直到达到SIZE的规模时,ADCSampleFlag==1;
注意:本例只是为了演示相关功能,事实,信号源是连续的时候,两次ADC1的采集间隔中是存在漏采的情况的。
三、建立工程
1、配置GPIO
配置PA5为输出(GPIO_Output),默认输出电平Low,推挽输出,上拉,速度High,标识为LED;PA5引脚输出高电平时LD2点亮,默认的低电平时熄灭;
2、选择时钟源和Debug
使用片外时钟晶体作为HSE的时钟源。在SYS中将Debug设置为Serial Wire。
3、配置ADC
选择Analog中的ADC1,在其模式(Mode)区,通道1(IN1)选择IN1 Single-ended(单端);其它参数设置可暂时均保持默认值。时钟预分频参数(Clock Prescaler)选择Asynchronous clock mode dividedby 1(其他选项亦可)。
4、配置系统时钟和ADC时钟
将系统时钟(SYSCLK)频率配置为170 MHz,设置ADC1的时钟频率为42.5 MHz。
设置ADC1的预分频参数为256,该参数将ADC1的时钟分频256倍,这个数值的选择与ADC1采样频率有关。
使能ADC1的连续转换模式;
在Rank下的采样时间选择为92.5个周期。这个参数决定着ADC的转换时间,则在12位分辨率时ADC1的转换时间为:92.5+12+0.5=105个ADC的时钟周期。 
使能ADC1的中断;
ADC中断优先级设置为1;
5、配置TIM3
将Clock Source选择为内部时钟,
将预分频因子和计数器周期分别设置为999,16999;
TIM3中断优先级设置为1;
6、配置串口
选择 Connectivity中的 USART2,其模式( Mode)选择异步( Asynchronous),其他参数设置均保持默认(波特率为115200 bit/ s),不开启中断。将 USART2的两个引脚 PA2和 PA3均设置为上拉。
四、代码修改
打开main.c,修改代码。
1、重定义TIM3中断回调函数
重定义 HAL_TIM_PeriodElapsedCallback(),在其中使PA5(LD2)的输出状态翻转。产生5Hz的信号源,修改预分频因子和计数器周期数值,可以改变信号源的频率。
/* USER CODE BEGIN 4 */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{ADC1ConvertedData[ADC1Data_index] = HAL_ADC_GetValue(&hadc1);if(ADCSampleFlag == 0)ADC1Data_index++;if(ADC1Data_index == ADC_CONVERTED_DATA_BUFFER_SIZE){ADCSampleFlag = 1;ADC1Data_index = 0;}
}
//信号源
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
}
//串口打印
int __io_putchar(int ch)
{HAL_UART_Transmit(&huart2,(uint8_t *)&ch,1,0xFFFF);return ch;
}
/* USER CODE END 4 */
2、启动ADC及重写其回调函数
关于ADC中断的使用,与外部中断、串口中断、定时器中断等的使用方法是类似的。关键点有两个:一是重写回调函数,二是在主程序初始化时开启中断。
ADC中断相关的回调函数可以用:
HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc);
启动ADC中断的库函数为:
HAL_ADC_Start_IT(ADC_HandleTypeDef *hadc);
3、定义用于存储转换结果的数组
定义一个数组,用于存储A/D转换结果。每执行一次回调函数,就将此次A/D转结果存入数组,直到存满。随后,在主程序中,通过串口送出数组中存储的数据。为此,需要在主程序中定义几个变量(放到注释对中):
/* USER CODE BEGIN PV */
uint16_t ADC1ConvertedData[ADC_CONVERTED_DATA_BUFFER_SIZE]={0};
uint16_t ADC1Data_index =0;
uint8_t ADCSampleFlag =0;
/* USERCODE END PV */
其中,数组长度ADC_CONVERTED_DATA_BUFFER_SIZE定义到main.h中
/* USER CODE BEGIN Private defines */
#define ADC_CONVERTED_DATA_BUFFER_SIZE (uint16_t) 65
/* USER CODE END Private defines */
4、重定义回调函数
在main.c中定义回调函数HAL_ADC_ConvCpltCallback():
/* USER CODE BEGIN 4 */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{ADC1ConvertedData[ADC1Data_index] = HAL_ADC_GetValue(&hadc1);if(ADCSampleFlag == 0)ADC1Data_index++;if(ADC1Data_index == ADC_CONVERTED_DATA_BUFFER_SIZE){ADCSampleFlag = 1;ADC1Data_index = 0;}
}
/* USER CODE END 4 */
5、在主程序中编写发送数据代码
标志位变量ADCSampleFlag的作用:当数组存满后,该标志位置1,等待串口发送数组中的数据;一旦数据发送完毕,再将该变量赋值为0,继续更新数组中数将数据发送代码放到main函数中的while(1)循环中,实现代码如下:
/* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */if(ADCSampleFlag == 1){for(uint16_ti=1;i<ADC_CONVERTED_DATA_BUFFER_SIZE;i++){printf("ADC1ConvertedData[%d] = %d\r\n",i,ADC1ConvertedData[i]);}ADCSampleFlag =0;}HAL_Delay(1000);}/* USER CODE END 3 */
6、在主程序初始化代码中使能ADC中断和TIM3中断
将HAL_ADC_Start_IT()函数与HAL_ADCEx_Calibration_Start()函数放到while(1)之前,MX_ADC1_Init()之后的注释对中:
/* USER CODE BEGIN 2 */HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED);HAL_ADC_Start_IT(&hadc1);HAL_TIM_Base_Start_IT(&htim3);
/* USER CODE END 2 */
7、配置printf函数
在回调函数的最后,使用了 printf函数,将 A/ D转换的结果通过串口送出。
使用 printf函数从串口送出数据,需要在 main.c中将 stdio.h包含进来;此外,还要给出 putchar函数的定义。
/* USER CODE BEGIN 4 */
int __io_putchar(int ch)
{HAL_UART_Transmit(&huart2,(uint8_t *)&ch,1,0xFFFF);return ch;
}
/* USER CODE END 4 */
五、运行并查看结果
示波器采集到的信号源:

串口接收到的数据:



相关文章:
细说MCU的ADC模块单通道连续采样的实现方法
目录 一、工程依赖的硬件及背景 二、设计目的 三、建立工程 1、配置GPIO 2、选择时钟源和Debug 3、配置ADC 4、配置系统时钟和ADC时钟 5、配置TIM3 6、配置串口 四、代码修改 1、重定义TIM3中断回调函数 2、启动ADC及重写其回调函数 3、定义用于存储转换结果的数…...
H2 Database Console未授权访问漏洞封堵
背景 H2 Database Console未授权访问,默认情况下自动创建不存在的数据库,从而导致未授权访问。各种未授权访问的教程,但是它怎么封堵呢? -ifExists 很简单,启动参数添加 -ifExists ,它的含义:…...
基于java+springboot+vue实现的药店管理系统(文末源码+Lw)285
摘 要 传统信息的管理大部分依赖于管理人员的手工登记与管理,然而,随着近些年信息技术的迅猛发展,让许多比较老套的信息管理模式进行了更新迭代,药品信息因为其管理内容繁杂,管理数量繁多导致手工进行处理不能满足广…...
网络爬虫基础
网络爬虫基础 网络爬虫,也被称为网络蜘蛛或爬虫,是一种用于自动浏览互联网并从网页中提取信息的软件程序。它们能够访问网站,解析页面内容,并收集所需数据。Python语言因其简洁的语法和强大的库支持,成为实现网络爬虫…...
js数组方法归纳——push、pop、unshift、shift
以下涉及到的数组的四个基础方法均会改变原数组!!! 1、 push() 该方法可以向数组的末尾添加一个或多个元素,并返回数组的新的长度可以将要添加的元素作为方法的参数传递,这样这些元素将会自动添加到数组的末尾该方法会将数组新的长度作为返回值返回 //创…...
VPN是什么?
VPN,全称Virtual Private Network,即“虚拟私人网络”,是一种在公共网络(如互联网)上建立加密、安全的连接通道的技术。简单来说,VPN就像是一条在公共道路上铺设的“秘密隧道”,通过这条隧道传输…...
浅析DDoS高防数据中心网络
随着企业业务的持续拓展和数智化转型步伐的加快,数据中心已逐渐演变为企业数据存储、处理和应用的关键部署场地,这也使得数据中心面临着日益严峻的网络安全风险,其中DDoS攻击以其高效性依旧是数据中心面临的主要威胁之一。伴随着数智化的发展…...
《安全行业大模型技术应用态势发展报告(2024)》
人工智能技术快速迭代发展,大模型应用场景不断拓展,随着安全行业对人工智能技术的应用程度日益加深,大模型在网络安全领域的应用潜力和挑战逐渐显现。安全行业大模型技术的应用实践不断涌现,其在威胁检测、风险评估和安全运营等方…...
【基于R语言群体遗传学】-4-统计建模与算法(statistical tests and algorithm)
之前的三篇博客,我们对于哈代温伯格遗传比例有了一个全面的认识,没有看的朋友可以先看一下前面的博客: 群体遗传学_tRNA做科研的博客-CSDN博客 1.一些新名词 (1)Algorithm: A series of operations executed in a s…...
Java springboot校园管理系统源码
Java springboot校园管理系统源码-014 下载地址:https://download.csdn.net/download/xiaohua1992/89364089 技术栈 运行环境:jdk8 tomcat9 mysql5.7 windows10 服务端技术:Spring Boot Mybatis VUE 使用说明 1.使用Navicati或者其它工…...
Lianwei 安全周报|2024.07.01
新的一周又开始了,以下是本周「Lianwei周报」,我们总结推荐了本周的政策/标准/指南最新动态、热点资讯和安全事件,保证大家不错过本周的每一个重点! 政策/标准/指南最新动态 01 出于安全考虑,拜登下令禁用卡巴斯基杀毒…...
柯桥职场英语学习商务英语口语生活英语培训生活口语学习
辣妹用英语怎么说? 辣妹在英语中通常被翻译为“hot girl”或“spicy girl”,但更常见和直接的是“hot chick”或简单地使用“hot”来形容。 举个例子: Shes a real hot girl with her trendy outfit and confident attitude. 她真是个辣妹࿰…...
Spring与Quartz整合
Quartz框架是一个轻量级的任务调度框架,它提供了许多内置的功能,包括:支持作业的调度、集群调度、持久化、任务持久化、任务依赖、优先级、并发控制、失败重试等。同时也支持自定义作业类型和触发器类型。与Spring整合步骤如下: …...
C++之static关键字
文章目录 前提正文多重定义extern关键字使用staticstatic 全局变量(在.cpp文件中定义)static变量存放在哪里static变量可不可以放在.h文件中 static 函数static局部变量static 成员变量static 成员函数 总结参考链接 前提 好吧,八股,我又回来了。这次想…...
嵌入式学习——硬件(Linux内核驱动编程platform、内核定时器、DS18B20)——day61
1. platform驱动框架 1.1 设备device #include <linux/init.h> #include <linux/module.h> #include <linux/platform_device.h>void led_release(struct device *dev) {printk("leds has been released\n"); }static struct resource led_resou…...
js逆向抠js要点解析与案例分享
JavaScript(JS)逆向工程是一种技术,用于分析和理解JS代码的功能和行为,尤其是在源代码不可用或被混淆的情况下。逆向JS代码可以帮助开发者理解第三方库的工作机制,或者在调试和优化过程中定位问题。 要点一࿱…...
mac安装docker
1、首先打开docker官网 https://docs.docker.com/engine/install/ 2、下载好后安装到app应用 3、安装好环境变量 #docker echo export PATH"/usr/local/Cellar/docker/20.10.11/bin:$PATH" >> .bash_profile...
PDF压缩工具选哪个?6款免费PDF压缩工具分享
PDF文件已经成为一种常见的文档格式。然而,PDF文件的体积有时可能非常庞大,尤其是在包含大量图像或复杂格式的情况下。选择一个高效的PDF压缩工具就显得尤为重要。小编今天给大家整理了2024年6款市面上反响不错的PDF压缩文件工具。轻松帮助你找到最适合自…...
Go语言--复合类型之指针与数组
分类 指针 指针是一个代表着某个内存地址的值。这个内存地址往往是在内存中存储的另一个变量的值的起始位置。Go 语言对指针的支持介于 Java 语言和 C/C语言之间,它既没有想 Java 语言那样取消了代码对指针的直接操作的能力,也避免了 C/C语言中由于对指针的滥用而造成的安全和…...
docker 环境下failed to start lsb故障解决
背景:从深信服超融合迁移虚拟机到VMWARE集群后,迁移后的虚拟机 centos 7 运行systemctl start network ,报错 Restarting network (via systemctl): Job for network.service failed. See systemctl status network.service and journalctl -xn for d…...
IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...
ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
