细说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 */

五、运行并查看结果

        示波器采集到的信号源:

         串口接收到的数据:

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【深度学习练习】心脏病预测

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 一、什么是RNN RNN与传统神经网络最大的区别在于&#xff0c;每次都会将前一次的输出结果&#xff0c;带到下一隐藏层中一起训练。如下图所示&#xff1a; …

macOS版ChatGPT更新:修复AI对话纯文本存储问题

猫头虎 &#x1f42f; 建联猫头虎&#xff0c;商务合作&#xff0c;产品评测&#xff0c;产品推广&#xff0c;个人自媒体创作&#xff0c;超级个体&#xff0c;涨粉秘籍&#xff0c;一起探索编程世界的无限可能&#xff01; macOS版ChatGPT更新&#xff1a;修复AI对话纯文本…

C++ 空间和时间高效的二项式系数(Space and time efficient Binomial Coefficient)

这里函数采用两个参数n和k&#xff0c;并返回二项式系数 C(n, k) 的值。 例子&#xff1a; 输入&#xff1a; n 4 和 k 2 输出&#xff1a; 6 解释&#xff1a; 4 C 2 等于 4!/(2!*2!) 6 输入&#xff1a; n 5 和 k 2 输出&#xff1a; 10 解释&#xff1a; 5 C …

maven项目、idea抽风问题解决

开发的时候遇到奇奇怪怪的非技术问题&#xff0c;解决起来会费时间&#xff0c;做无用功。   这里记录常见的情况和解决方法 1.未识别maven项目 文件的图标变成了这种橙色的&#xff0c;而且有主启动函数也不能run 右键pom文件&#xff0c;点击Add as Maven Project 如果…

揭开梵蒂冈秘密档案馆的神秘面纱

关注我们 - 数字罗塞塔计划 - PART 01 深邃的历史 梵蒂冈秘密档案馆起源于公元8世纪&#xff0c;负责保存官方文书和教皇书信。9世纪开始在圣彼得大教堂设立档案库&#xff0c;负责保管外交和法律文件&#xff0c;在帕拉蒂诺山塔内保存经济和行政方面的档案。11至13世纪&…

SpringBoot AOP面向切面编程 基础

介绍 在 Spring Boot 中&#xff0c;AOP&#xff08;面向切面编程&#xff09;是一种强大的技术&#xff0c;它允许你在应用程序中横切关注点&#xff0c;比如日志记录、事务管理、性能监控等&#xff0c;从而避免重复代码和混乱 可以记录操作日志 权限控制 。 依赖 <dep…

HTMLCSS(入门)

HTML <html> <head><title>第一个页面</title></head><body>键盘敲烂&#xff0c;工资过万</body> </html> <!DOCTYPE>文档类型声明&#xff0c;告诉浏览器使用哪种HTML版本显示网页 <!DOCTYPE html>当前页面采取…

go语言day08 泛型 自定义错误处理 go关键字:协程

泛型&#xff1a; 抛错误异常 实现error接口类型 用java语言解释的话&#xff0c;实现类需要重写error类型的抽象方法Error().这样就可以自定义异常处理。 回到go语言&#xff0c;在Error()方法中用*argError 这样一个指针类来充当error接口的实现类。 在f2()方法中定义返回值…

本地部署秘塔开源搜索引擎

秘塔AI搜索是由秘塔科技于2024年初推出的一款新型搜索引擎&#xff0c;被业界誉为“中国版的Perplexity”。秘塔科技成立于2018年4月&#xff0c;其核心团队包括CEO闵可锐、技术专家唐悦和首席运营官王益为等。秘塔AI搜索以其高效简洁的特点受到关注&#xff0c;其搜索结果直接…

累积分布函数的一些性质证明

性质1&#xff1a; E [ X ] ∫ 0 ∞ ( 1 − F ( x ) ) d x − ∫ − ∞ 0 F ( x ) d x ( 1 ) E[X]\int_0^{\infty}(1-F(x))dx - \int_{-\infty}^0F(x)dx\quad (1) E[X]∫0∞​(1−F(x))dx−∫−∞0​F(x)dx(1) 证明&#xff1a; E [ X ] ∫ − ∞ ∞ x p ( x ) d x E[X] …

ETCD 基本介绍与常见命令的使用

转载请标明出处&#xff1a;https://blog.csdn.net/donkor_/article/details/140171610 文章目录 一、基本介绍1.1 参考1.2 什么是ETCD1.3 ETCD的特点1.4 ETCD的主要功能1.5 ETCD的整体架构1.6 什么时候用ETCD&#xff0c;什么时候用redis 二、安装三、使用3.1 etcdctl3.2 常用…

审核平台前端新老仓库迁移

背景 审核平台接入50业务&#xff0c;提供在线审核及离线质检、新人培训等核心能力&#xff0c;同时提供数据报表、资源追踪、知识库等工具。随着平台的飞速发展&#xff0c;越来越多的新业务正在或即将接入审核平台&#xff0c;日均页面浏览量为百万级别。如今审核平台已是公司…

[Redis]哨兵机制

哨兵机制概念 在传统主从复制机制中&#xff0c;会存在一些问题&#xff1a; 1. 主节点发生故障时&#xff0c;进行主备切换的过程是复杂的&#xff0c;需要人工参与&#xff0c;导致故障恢复时间无法保障。 2. 主节点可以将读压力分散出去&#xff0c;但写压力/存储压力是无法…

直击园区消防管理现状,智慧消防相比传统消防管理的优势是什么

一、工业园区消防管理现状 1、消防信息智能化程度低 信息化手段落后&#xff0c;现场的数据信息无法即时传送至指挥中心&#xff0c;突发事件发生时&#xff0c;无法扁平化指挥到基层现场&#xff0c;应急处置能力不足。 2、防控体系不健全 存在监测盲点&#xff0c;火灾报警…

Mybatis实现RBAC权限模型查询

RBAC权限模型 Role-Based Access Control&#xff0c;中文意思是&#xff1a;基于角色&#xff08;Role&#xff09;的访问控制。这是一种广泛应用于计算机系统和网络安全领域的访问控制模型。 简单来说&#xff0c;就是通过将权限分配给➡角色&#xff0c;再将角色分配给➡用…

ABB机器人坐标系偏移指令

ABB机器人在坐标系中偏移用到的指令有&#xff1a;Offs和RelTool。Offs用在工件坐标系中偏移&#xff0c;而RelTool是在工具坐标系中偏移。 一、Offs用于在一个机械臂位置的工件坐标系中添加一个偏移量。 Offs (Point &#xff0c;XOffset&#xff0c; YOffset &#xff0c;Z…

【UE5.1】Chaos物理系统基础——05 蓝图绑定Chaos破裂或碰撞事件

步骤 1. 新建一个父类为Actor的蓝图&#xff0c;这里命名为“BP_ChaosExplosionEvent” 打开“BP_ChaosExplosionEvent”&#xff0c;添加一个变量&#xff0c;这里命名为“GC”&#xff0c;变量类型为“几何体集actor”&#xff0c;设置为可编辑实例 在事件图表中添加如下节点…

Unity休闲手机游戏开发课程

课程介绍 Unity休闲手机游戏开发课程将教您如何利用Unity游戏引擎创建令人愉快的休闲手机游戏。从基础的游戏开发知识到高级的游戏制作技巧&#xff0c;您将学习到创建各种类型的休闲游戏所需的关键技能和工具。无论您是初学者还是有一定经验的开发者&#xff0c;本课程都能帮助…

基于JavaScript、puppeteer的爬虫

前期准备: npm puppeteer import puppeteer from puppeteer; puppeteer文档 第一步&#xff1a;启动浏览器&#xff0c;跳转到需要爬取的页面 const browser await puppeteer.launch({ headless: false });const page await browser.newPage();await page.goto(url, { w…

ssm高校宿舍用电管理系统-计算机毕业设计源码97859

摘要 随着高校规模的扩大和学生数量的增加&#xff0c;高校宿舍的用电需求也日益庞大。为了提高用电效率、节约能源、确保用电安全和方便管理&#xff0c;开发一个高校宿舍用电管理系统具有重要意义。本系统将采用Java作为后端开发语言&#xff0c;具备跨平台特性&#xff0c;能…