细说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…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...

网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...

如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...