细说MCU的ADC模块单通道单次采样的实现方法

news2024/12/24 2:25:29

目录

一、工程依赖的硬件

二、设计目的

三、建立工程

1、配置GPIO

2、配置中断

3、配置串口

4、配置ADC

5、选择时钟源和Debug

6、配置系统时钟和ADC时钟

四、设置采样频率 

五、代码修改 

1、重定义外部中断回调函数

2、启动ADC

3、配置printf函数 

六、运行并查看结果 


        STM32G4系列MCU的模/数转换器(Analog to Digital Converter,ADC)功能比较强不同的型号所含ADC模块数量不同,最多有5个ADC(ADC1~5);但也并非完全独立,其ADC1和ADC2是一对,ADC3和ADC4是一对,ADC5可独立控制。每个ADC都包含一个12位逐次比较型模/数转换器。此外,每个ADC还有最多至19个通道,不同的通道具有单次、连续和扫描或断续等采样模式。

一、工程依赖的硬件

        文章依赖的硬件及工程配置参考本文作者的其他文章:细说ARM MCU的串口接收数据的实现过程-CSDN博客 https://wenchm.blog.csdn.net/article/details/139541112

二、设计目的

        在本例子中,使用ADC1的一个通道以单次采样的模式采集外部输入直流电压信号。使用NUCLEO-G474RE开发板上的按键B1来启动ADC采样。每按下一次B1键,进行一次A/D转换。在代码实现中,将通过查询方式判断是否转换完成;一旦转换成,主程序会从ADC的数据寄存器中读取转换结果,并将结果通过串口送出。此外,当输入信号的幅值大于一定值时,将会点亮板上发光二极管LD2。这个例子用到了ADC、串口入/输出等多个模块。此外,A/D转换虽采用查询模式,但对按键状态的识别,将采用中断方式。

        ADC的输入电压范围是0~3.3 V,所以要确保外部施加的信号不超过此电压范围,否则会导致硬件损坏。

        本例中,采用ADC1的第一个通道,对应STM32G474RE的引脚为PA0,在NUCLEG474RE板上通过CN7端子的第28引脚引出。此外,按键B1连接的引脚为PC13,LD2的控制引脚为PA5。

三、建立工程

1、配置GPIO

        配置PA5为输出(GPIO_Output),默认输出电平Low,推挽输出,上拉,速度High,标识为LED;PA5引脚输出高电平时LD2点亮,默认的低电平时熄灭;

        配置PC13为中断模式(GPIO_EXTI13),上升沿触发,下拉,用户标识为KEY。

2、配置中断

        在NVIC中断表中,将EXTI line[15:10]interrupts使能,并将其抢占式优先级设为2(由于仅用到一个中断,级数选择可任意)。

3、配置串口

        选择 Connectivity中的 USART2,其模式( Mode)选择异步( Asynchronous),其他参数设置均保持默认(波特率为115200 bit/ s),不开启中断。将 USART2的两个引脚 PA2和 PA3均设置为上拉。

4、配置ADC

        选择Analog中的ADC1,在其模式(Mode)区,通道1(IN1)选择IN1 Single-ended(单端);其它参数设置可暂时均保持默认值。时钟预分频参数(Clock Prescaler)选择Asynchronous clock mode dividedby 1(其他选项亦可)。

5、选择时钟源和Debug

        使用片外时钟晶体作为HSE的时钟源。在SYS中将Debug设置为Serial Wire。

6、配置系统时钟和ADC时钟

        在STM32G474RE的说明文档中,给出了其ADC时钟频率的范围。

        ADC的最大频率为60 MHz,而系统最高频率为170 MHz,如果系统频率配置较高,生成ADC时钟频率时就需要分频处理。

        在本例中,没有使用低功耗模式,并且是让ADC进行单次采样的,所以最高时钟频以达到60 MHz。为了可靠起见,本例中配置ADC的时钟频率为34 MHz。

符  号

参  数

条  件

最小值

最大值

fADC/MHz

ADC
时钟频率

Rangel单路ADC操作

0.14

60

Range2

——

26

Range1所有ADCs操作,单端模式VDDA≥2.7 V

0.14

52

Range1所有ADCs操作,单端模式VDDA≥1.62 V

0.14

42

Rangel单路ADC操作,差分模式VDDA≥1.62 V

0.14

56

四、设置采样频率 

 

五、代码修改 

        打开main.c,修改代码。 

1、重定义外部中断回调函数

        由于希望在产生按键中断时,启动ADC采样,所以,需要重定义外部中断EXTI的回调函数。这个回调函数可以写在main.c文件后面的一个注释对中。这里直接给出它的定义:

/* USER CODE BEGIN 4 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	HAL_ADC_Start(&hadc1);
	HAL_ADC_PollForConversion(&hadc1,10);
	ADC1ConvertedValue = HAL_ADC_GetValue(&hadc1);
	if(ADC1ConvertedValue > 2048)
		HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_SET);
	else
		HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_RESET);
	printf("ADCResult =%d \r\n",ADC1ConvertedValue);
}

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_Start(ADC_HandleTypeDef *hadc)。此函数只有一个参数,就是ADC结构体变量。由于在硬件配置中用了ADC1,所以自动生成的代码中已经给出了它的结构体变量,即hadcl。

        调用的第二个库函数是:

HAL_ADC_PollForConversion(ADC_HandleTypeDef *hadc,uint32_t Timeout);

        这个函数是以查询方式等待A/D转换过程的结束。该函数的第二个参数是Timeout,单位为ms。随后,就可以调用库函数HAL_ADC_GetValue(ADC_HandleTypeDef *hadc)来读取A/D转换的结果了。这里用了一个变量ADC1ConvertedValue来存放A/D转换的结果。需要在main.c中定义该变量,可以将其放到main函数前的注释对中:

/* USER CODE BEGIN PV */
uint16_t ADC1ConvertedValue = 0;
/* USER CODE END PV */

        接下来,在回调函数HAL_GPIO_EXTI_Callback()中根据A/D采样值的大小控制发光二极管的亮灭。

3、配置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 */

六、运行并查看结果 

        编译工程并下载到硬件中,将程序运行起来。 

 

 

        打开串口助手程序,设置好串口端口和波特率等参数,单击“打开串口。

        分别用跳线将PA0连接到GND和VDD(3.3 V)上,并操作NUCLEO-G474RE板上B1键。可以看到,连接到GND时每次送的是0,连接到VDD时会每次送来一个接近4095的数,如图截图。

        STM32G474RE上的ADC是12位的,输入电压3.3 V时,理论上对应最大转换值为4095。在将PA0连接到VDD上时,为什么 ADC的转换结果不是4095呢?这是因为板上的VDD并不是稳定的3.3 V,而是有偏差的。对于12位ADC,如果满量程输入电压为3.3 V,则转换结果的每一位对应的电压为3.3/4096 V,约为0.0008 V,即0.8 mV。从截图中的结果看,偏差了几十mV(不同的板子,偏差可能会有所不同)。

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

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

相关文章

Java开发-面试题-0006-DELETE、VACUUM和TRUNCATE的区别

Java开发-面试题-0006-DELETE、VACUUM和TRUNCATE的区别 更多内容欢迎关注我(持续更新中,欢迎Star✨) Github:CodeZeng1998/Java-Developer-Work-Note 技术公众号:CodeZeng1998(纯纯技术文) …

[论文阅读笔记31] Object-Centric Multiple Object Tracking (ICCV2023)

最近Object centric learning比较火, 其借助了心理学的概念, 旨在将注意力集中在图像或视频中的独立对象(objects)上,而不是整个图像。这个方法与传统的基于像素或区域的方法有所不同,它试图通过识别和分离图像中的各个对象来进行…

推出一系列GaN功率放大器: QPA2211、QPA2211D、QPA2212、QPA2212D、QPA2212T,支持卫星通信和5G基础设施。

推出用于支持支持卫星通信和5G基础设施的GaN功率放大器: QPA2211 QPA2211D QPA2212 QPA2212D QPA2212T QPA2211 10W GaN功率放大器是一款Ka波段功率放大器,采用0.15m碳化硅基氮化镓工艺 (QGaN15) 制造而成。该放大器的工作频率范围为27.5GHz至31GHz&…

Linux_内核缓冲区

目录 1、用户缓冲区概念 2、用户缓冲区刷新策略 3、用户缓冲区的好处 4、内核缓冲区 5、验证内核缓冲区 6、用户缓冲区存放的位置 7、全缓冲 结语 前言: Linux下的内核缓冲区存在于系统中,该缓冲区和用户层面的缓冲区不过同一个概念&#x…

【并发程序设计】总篇集 Linux下 C语言 实现并发程序

11_Concurrent_Programing 文章目录 11_Concurrent_Programing1.进程概念进程内容进程类型进程状态 2.进程常用命令进程信息命令top 命令进程信息表 进程优先级命令nice 命令renice 命令 后台进程命令 3.子进程创建子进程fork 函数 结束进程exit 函数_exit 函数 回收子进程wait…

MySQL性能问题诊断方法和常用工具

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG数据库运维(如安装迁移,性能优化、故障应急处理等) 公众号:老苏畅谈运维 欢迎关注本人公众号,更多精彩与您分享。MySQL运…

如何监控巨量千川的违规行为

在这个瞬息万变的数字营销时代,每一分数据都蕴含着无限价值,尤其在电商领域,精准洞察与高效决策力已成为致胜关键。然而,面对巨量千川这一电商一体化智能营销平台的广阔天地,如何在海量信息中准确捕捉投放违规信息&…

如何避免vue的url中使用hash符号?

目录 1. 安装 Vue Router 2. 配置 Vue Router 使用 history 模式 3. 更新 main.js 4. 配置服务器以支持 history 模式(此处需要仔细测试) a. Nginx 配置 b. Apache 配置 5. 部署并测试 总结 在 Vue.js 项目中,避免 URL 中出现 # 符号的…

用 Rust 实现一个替代 WebSocket 的协议

很久之前我就对websocket颇有微词,它的确满足了很多情境下的需求,但是仍然有不少问题。对我来说,最大的一个问题是websocket的数据是明文传输的,这使得websocket的数据很容易遭到劫持和攻击。同时,WebSocket继承自HTTP…

yocto系列讲解[实战篇]94 - 添加libhybris库和测试示例

By: fulinux E-mail: fulinux@sina.com Blog: https://blog.csdn.net/fulinus 喜欢的盆友欢迎点赞和订阅! 你的喜欢就是我写作的动力! 目录 1. 概述2. 添加libhybris的recipe3.libhybris编译4.libhybris测试5.自制Android C++动态库6.自制Android C++动态库编译7.创建testhyb…

spring源码环境的搭建

为什么要编译spring源码 为了高效调试Spring源码、验证个人猜想,并从开发者的视角深化理解,编译自定义的Spring源码版本显得尤为重要。这样可以避免因缺乏预编译版本而带来的不便,并允许直接在源码上进行注释或修改,以记录学习心…

【Java毕业设计】基于JavaWeb的服务出租系统

本科毕业设计论文 题目:房屋交易平台设计与实现 系 别: XX系(全称) 专 业: 软件工程 班 级: 软件工程15201 学生姓名: 学生学号: 指导教师: 导师1 导师2 文章目录 摘…

基于AT89C52单片机的超声波测距设计—数码管显示

点击链接获取Keil源码与Project Backups仿真图: https://download.csdn.net/download/qq_64505944/89456475?spm=1001.2014.3001.5503 C 源码+仿真图+毕业设计+实物制作步骤+10 在这里插入图片描述 题 目: 基于52的超声波测距汽车防撞系统 学生姓名 [姓名] 学 号 [学号…

毕业季带给我的五个启示

每到毕业季,校园里总是充满了复杂的情绪。有人欢笑,有人落泪。同样的四年大学生活,为何结局如此不同?本文将从多个角度探讨如何实现综合改变,解释在交友、机会和心态上的关键因素,揭示“慢就是快”的真理。…

工作实践:11种API性能优化方法

一、索引优化 接口性能优化时,大家第一个想到的通常是:优化索引。 确实,优化索引的成本是最小的。 你可以通过查看线上日志或监控报告,发现某个接口使用的某条SQL语句耗时较长。 此时,你可能会有以下疑问&#xff…

别再滥用std::async了,strace命令暴露了一个乱开线程问题

用strace查看进程的系统调用后,发现一个std::async滥用问题 问题现象 进程的系统调用clone次数持续增加 使用工具strace发现进程clone系统调用过多且一直在增加 strace -c -p PID问题分析 clone在做什么:创建进程(线程) 查看…

Redis入门篇

目录 传送门一、前言二、NoSQL1、ont only sql,特点:2、NoSQL的四大分类: 三、Redis概念四、五大数据类型: 传送门 SpringMVC的源码解析(精品) Spring6的源码解析(精品) SpringBoot3框架&#…

大数据学习-环境准备

VMware 部分 网络设置 下载好 CentOS 7 的镜像文件 修改 VMware 的网络 把子网 ip 修改为 192.168.88.0,然后点击 NAT 设置,修改网关 IP 为 192.168.88.2 之后就确定即可 虚拟机安装 选择镜像文件,使用 VMware 的典型安装方法即可&#…

Prompt 提示词工程:翻译提示

近期在对计算机学习时,许多内容需要看原始的英文论文,对于我这种学渣来说特别不友好,🤷🏻‍♀️无奈只能一边看翻译,一边学习。 之前有搜到过专门的翻译工具,无奈都是按照字数算费用的&#xf…

【Java毕业设计】基于JavaWeb的礼服租赁系统

文章目录 摘 要Abstract目录1 绪论1.1 课题背景和意义1.2 国内外研究现状1.2.1 国外研究现状 1.3 课题主要内容 2 开发相关技术介绍2.1 Spring Boot框架2.2 Vue框架2.3 MySQL数据库2.4 Redis数据库 3 系统分析3.1 需求分析3.1.1 用户需求分析3.1.2 功能需求分析 3.2 可行性分析…