STM32_ADC

news2024/11/17 14:51:37

1、ADC简介

        ADC,即Analog-Digital Converter,模拟-数字转换器。

        ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁。

        12位逐次逼近型ADC,1us转换时间。

        输入电压范围:0~3.3V,转换结果范围:0~4095(2的12次方)。

        18个输入通道,可测量16个外部和2个内部信号源。

        规则组和注入组两个转换单元。

        模拟看门狗自动监测输入电压范围。

        STM32F103C8T6 ADC资源:ADC1、ADC2,10个外部输入通道。

2、ADC框图

        基于stm32f103x

        逐次逼近型ADC

        EOC:End of Convert 转换结束信号

        START:开始转换,给一个输入脉冲,开始转换

        CLOCK:ADC时钟,因为ADC内部是一步一步进行判断的,需要时钟来推动这个过程

        Vref+、Vref-:DAC的参考电压,这个范围也决定了ADC的输入范围,所以它也是ADC的参考电压

        简化框图

        ADC时序图:

                如下图所示,ADC在开始精确转换前需要一个稳定时间tSTAB。在开始ADC转换和14个时钟周期后,EOC标志被设置,16位ADC数据寄存器包含转换的结果。

3、通道选择

        有16个多路通道。可以把转换组织成两组:规则组和注入组。在任意多个通道上以任意顺序进行的一系列转换构成成组转换。例如,可以如下顺序完成转换:通道3、通道8、通道2、通道2、通道0、通道2、通道2、通道15。

3.1 规则组

        规则组由多达16个转换组成。规则通道和它们的转换顺序在ADC_SQRx寄存器中选择。规则组中转换的总数应写入ADC_SQR1寄存器的L[3:0]位中。

        规则组虽然有16个通道,但是只有1个数据寄存器,一次最多只能转换1个通道,如果一次转换16个通道,那么前15个会被覆盖掉,只保留第16个。如果要使用规则组一次转换多个通道,最好搭配DMA使用,转换一个就转移一个。

3.2 注入组

        注入组由多达4个转换组成。注入通道和它们的转换顺序在ADC_JSQR寄存器中选择。注入组里的转换总数目应写入ADC_JSQR寄存器的L[1:0]位中。

        注入组一次最多可以转换4个通道,有4个数据寄存器。

4、转换/扫描模式

4.1 单次转换

        单次转换模式下,ADC只执行一次转换。该模式既可通过设置ADC_CR2寄存器的ADON位(只适用于规则通道)启动,也可通过外部触发启动(适用于规则通道或注入通道),这时CONT位为0。一旦选择通道的转换完成:

        如果一个规则通道被转换:

                转换数据被储存在16位ADC_DR寄存器中

                EOC(转换结束)标志被设置

                如果设置了EOCIE,则产生中断。

        如果一个注入通道被转换:

                转换数据被储存在16位的ADC_DRJ1寄存器中

                JEOC(注入转换结束)标志被设置

                如果设置了JEOCIE位,则产生中断。

        然后ADC停止。

4.2 连续转换

        在连续转换模式中,当前面ADC转换一结束马上就启动另一次转换。此模式可通过外部触发启动或通过设置ADC_CR2寄存器上的ADON位启动,此时CONT位是1。每个转换后:

        如果一个规则通道被转换:

                转换数据被储存在16位的ADC_DR寄存器中

                EOC(转换结束)标志被设置

                如果设置了EOCIE,则产生中断。

        如果一个注入通道被转换:

                转换数据被储存在16位的ADC_DRJ1寄存器中

                JEOC(注入转换结束)标志被设置

                如果设置了JEOCIE位,则产生中断。

4.3 扫描模式

        此模式用来扫描一组模拟通道。

        扫描模式可通过设置ADC_CR1寄存器的SCAN位来选择。一旦这个位被设置,ADC扫描所有被ADC_SQRX寄存器(对规则通道)或ADC_JSQR(对注入通道)选中的所有通道。在每个组的每个通道上执行单次转换。在每个转换结束时,同一组的下一个通道被自动转换。如果设置了CONT位,转换不会在选择组的最后一个通道上停止,而是再次从选择组的第一个通道继续转换。如果设置了DMA位,在每次EOC后,DMA控制器把规则组通道的转换数据传输到SRAM中。而注入通道转换的数据总是存储在ADC_JDRx寄存器中。

        扫描模式一般与转换模式结合使用。

5、触发控制

        转换可以由外部事件触发(例如定时器捕获,EXTI线)。如果设置了EXTTRIG控制位,则外部事件就能够触发转换。EXTSEL[2:0]和JEXTSEL2:0]控制位允许应用程序选择8个可能的事件中的某一个,可以触发规则和注入组的采样。

        注意:当外部触发信号被选为ADC规则或注入转换时,只有它的上升沿可以启动转换。

6、数据对齐

         本芯片的ADC是12位的,它的转换结果就是一个12位的数据,但是这个数据寄存器是16位的,所以就存在一个数据对齐的问题。

        ADC_CR2寄存器中的ALIGN位选择转换后数据储存的对齐方式。数据可以左对齐或右对齐,如图29和图30所示。

        注入组通道转换的数据值已经减去了在ADC_JOFRx寄存器中定义的偏移量,因此结果可以是一个负值。SEXT位是扩展的符号值。

        对于规则组通道,不需减去偏移值,因此只有12个位有效。

        一般选择使用的都是数据右对齐。

7、转换时间

        AD转换的步骤:采样、保持、量化、编码

        ADC使用若干个ADC_CLK周期对输入电压采样,采样周期数目可以通过ADC_SMPR1和ADC_SMPR2寄存器中的SMP[2:0]位更改。每个通道可以分别用不同的时间采样。

        总转换时间如下计算:

                Tconv=采样时间+12.5个周期

        采样时间是采样保持花费的时间,采样时间越大,越能避免一些毛刺信号的干扰,不过转换时间也会相应延长;12.5个周期是量化编码花费的时间,因为是12位的ADC,所以需要花费12个周期,多出来0.5个周期可能是要做一些其它东西花费的时间。ADC周期就是从RCC分频过来的ADCCLK,这里这个ADCCLK最大为14KHz。

        例如:当ADCCLK=14MHz,采样时间为1.5个ADC周期

                Tconv=1.5+12.5=14个ADC采样周期=14*1/14MHz=1us

8、校准

        ADC有一个内置自校准模式。校准可大幅减小因内部电容器组的变化而造成的准精度误差。在校准期间,在每个电容器上都会计算出一个误差修正码(数字值),这个码用于消除在随后的转换中每个电容器上产生的误差。

        通过设置ADC_CR2寄存器的CAL位启动校准。一旦校准结束,CAL位被硬件复位,可以开始正常转换。建议在上电时执行一次ADC校准。校准阶段结束后,校准码储存在ADC_DR中。

        注意:        

                (1)建议在每次上电后执行一次校准。

                (2)启动校准前,ADC必须处于关电状态(ADON='O')超过至少两个ADC时钟周期。

        校准时序图:

9、ADC编程示例

//AD_Init.c
#include "stm32f10x.h"                  // Device header

void AD_Init(void)
{
	//第一步,开启RCC的时钟,包括ADC和GPIO的时钟,ADCCLK的分频器也需要配置一下
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);	//ADCCLK = 72MHz / 6 = 12MHz
	
	//第二步,配置GPIO,将需要用的GPIO配制成模拟输入的模式
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;	//模拟输入,在AIN模式下,gpio口是无效的,断开gpio,防止gpio的输入输出对模拟电压造成干扰
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	//第三步,配置多路开关,把左边的通道接入到右边的规则组列表里
	ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);	//关于采样时间的参数,需要更快的转换就用小参数,需要稳定的转换就用大参数,这里就是55.5个ADCCLK的周期
	
	//第四步,配置ADC转换器
	ADC_InitTypeDef ADC_InitStructure;
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;	//ADC工作模式,独立模式
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;	//数据对齐方式,右对齐
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;	//连续转换模式,可以选择是连续转换还是单次转换
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	//外部触发转换选择,就是触发控制的触发源,这里不使用外部触发,用内部软件触发
	ADC_InitStructure.ADC_NbrOfChannel = 1;	//通道数目,指定在扫描模式下总共会用到几个通道
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;	//扫描转换模式,可以选择是扫描模式还是非扫描模式
	ADC_Init(ADC1, &ADC_InitStructure);
	//如果是连续转换模式,仅需要在最开始触发一次就行了,所以只要把下面软件触发转换的函数放在初始化函数最后面就行,在初始化完成后触发一次就行了
	
	//第五步,开关控制,开启ADC
	ADC_Cmd(ADC1, ENABLE);
	
	//对ADC进行校准,可以减少误差
	ADC_ResetCalibration(ADC1);	//复位校准
	while (ADC_GetResetCalibrationStatus(ADC1) == SET);	//ADC_GetResetCalibrationStatus返回复位校准的状态,如果状态变为0了,说明复位校准完成,可以跳出等待了
	ADC_StartCalibration(ADC1);	//开始校准,之后内部电路会自动开始校准
	while (ADC_GetCalibrationStatus(ADC1) == SET);	//等待校准是否完成
	
	
	
}

uint16_t AD_GetValue(void)
{
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);	//使用ADC_SoftwareStartConvCmd软件触发转换函数,触发之后,adc就开始转换了
	while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);	//获取adc状态标志位,ADC_FLAG_EOC规则组转换完成标志位
	return ADC_GetConversionValue(ADC1);	//获取AD转换的结果,获取转换值的函数是直接读取ADC的DR数据寄存器,因为读取DR寄存器会自动清楚EOC标志位,就不用手动再来清除标志位了
}
//main.c
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "AD.h"

uint16_t ADValue;
float Voltage;

int main(void)
{
	//初始化OLED
	OLED_Init();
	AD_Init();
	
	
//	OLED_ShowChar(1, 1, 'A');
	OLED_ShowString(1, 1, "ADValue:");
	OLED_ShowString(2, 1, "Voltage:0.00V");
//	OLED_ShowNum(2, 1, 12345, 5);
//	OLED_ShowSignedNum(2, 7, -66, 2);
//	OLED_ShowHexNum(3, 1, 0xAA55, 4);
//	OLED_ShowBinNum(4, 1, 0xAA55, 16);
	
//	OLED_Clear();
	
	while (1)
	{
		ADValue = AD_GetValue();
		Voltage = (float)ADValue / 4095 * 3.3;
		OLED_ShowNum(1, 9, ADValue, 4);
		OLED_ShowNum(2, 9, Voltage, 1);
		OLED_ShowNum(2, 11, (uint16_t)(Voltage * 100) % 100, 2);
		
		Delay_ms(100);
	}
}

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

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

相关文章

MySQL数据库单表查询中查询条件的写法

1.使用比较运算符作为查询条件 ; !; >; >; <; <; 如上图所示&#xff0c;可以使用命令select 字段&#xff0c;字段 from 表名 where Gender “M”; 即挑选出Gender “M” 的教师&#xff0c; 如上图所示&#xff0c;可以使用命令select 字段&#xff0c;…

fastadmin 树状菜单展开,合并;简要文件管理系统界面设计与实现

一&#xff0c;菜单合并效果图 源文件参考&#xff1a;fastadmin 子级菜单展开合并、分类父级归纳 - FastAdmin问答社区 php服务端&#xff1a; public function _initialize() {parent::_initialize();$this->model new \app\admin\model\auth\Filetype;$this->admin…

chatGPT预训练模型范例之GPT3系列模型的解密

目录 前言 一、GPT的背景 二、GPT的架构 那么如何实现零样本&#xff08;zero-shot&#xff09;学习呢? 这里我们还是主要来看一下 GPT-3 中所谓的 few-/one-/zero- shot 方式分别是什么意思&#xff1f; 三、GPT的应用 四、GPT3的局限性 前言 近年来&#xff0c;预训练…

分割训练日志的可视化

这一部分主要是将mmdetection训练得到的json文件可视化&#xff0c;代码主要源于github&#xff0c;具体哪一个忘记了&#xff08;readme里面没有原址…&#xff09;是专门做的mmdetection 结果可视化的&#xff0c;非常强&#xff01;&#xff01;。使用时如果出现keyerror的话…

MT3041 多项式变换求值

注意点&#xff1a; 1.使用单调栈 2.用ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);避免超时 3.此题除了ans最好不要用long long&#xff0c;如果a[]和b[]都是long long 类型&#xff0c;可能会超内存 4.ans (ans % p p) % p;防止负数 5.使用秦九韶算法计算指数…

MySQL用户管理操作

用户权限管理操作 DCL语句 一.用户管理操作 MySQL软件内部完整的用户格式&#xff1a; 用户名客户端地址 admin1.1.1.1这个用户只能从1.1.1.1的客服端来连接服务器 admin1.1.1.2这个用户只能从1.1.1.2的客服端来连接服务器 rootlocal host这个用户只能从服务器本地进行连…

ptrade从零开始学习量化交易第11期【ptrade策略引擎简介之on_order_response - 委托主推(可选)】

策略引擎简介 更加详细的调用方法&#xff0c;后续会慢慢整理。 也可找寻博主历史文章&#xff0c;搜索关键词使用方案&#xff0c;比如本文涉及函数on_order_response &#xff01; 感谢关注&#xff0c;咨询开通量化回测与获取实盘权限&#xff0c;欢迎和博主联系&#xf…

经验分享:C++ error:‘syscall’ was not declared in this scope

明明已经加了头文件 #include <sys/syscall.h>#define gettid() syscall(__NR_gettid)但是依旧不能使用 syscall() 函数&#xff0c; 检查源码后&#xff1a; sys/syscall.h 内部表示&#xff0c;他封装了 打开对应的 syscall.h 文件内部依旧没有 syscall()函数的声明…

Vue02-黑马程序员学习笔记

一、今日学习目标 1.指令补充 指令修饰符v-bind对样式增强的操作v-model应用于其他表单元素 2.computed计算属性 基础语法计算属性vs方法计算属性的完整写法成绩案例 3.watch侦听器 基础写法完整写法 4.综合案例 &#xff08;演示&#xff09; 渲染 / 删除 / 修改数量 …

炫酷gdb

在VS里面调试很方便对吧&#xff1f;&#xff08;F5直接调试&#xff0c;F10逐过程调试--不进函数&#xff0c;F11逐语句调试--进函数&#xff0c;F9创建断点&#xff09;&#xff0c;那在Linux中怎么调试呢&#xff1f; 我们需要用到一个工具&#xff1a;gdb 我们知道VS中程…

qt中使用tableWidget不显示表头和内容的可能原因

需求是想要把sqlite数据库中的内容通过tableWidget显示出来&#xff0c;但是在使用过程中发现了一些问题 使用ui->tableWidget->setHorizontalHeaderLabels设置表头的时候&#xff0c;发现怎么样都不显示表头&#xff0c;参考这篇文章&#xff0c;应该使用ui->tableW…

Sping6 笔记(一)【优秀的轻量级框架】

Spring6 介绍&#xff1a; 发布时间&#xff1a;2022年11月Spring 框架是一款优秀的轻量级开源框架&#xff0c;为了解决企业应用开发的复杂性而出现Spring 框架的用途&#xff1a;服务器端的开发特点&#xff1a;简单性、可测试性、松耦合性 学习 Spring6 的前置知识&#x…

react组件中的共享数据

在前面的示例中&#xff0c;每个 MyButton 都有自己独立的 count&#xff0c;当每个按钮被点击时&#xff0c;只有被点击按钮的 count 才会发生改变&#xff1a; 然而&#xff0c;你经常需要组件 共享数据并一起更新。 为了使得 MyButton 组件显示相同的 count 并一起更新&…

Socket同步通讯

目录 引言 1. 建立连接 2. 数据传输 3. 同步机制 4. 处理延迟 5. 安全性 6、一对一Socket同步通讯 客户端 代码分析 服务端 代码分析 7、服务端操作 1、首先我们先运行客户端代码 2、服务端点击Connect连接客户端 3、服务端输入信息传输到客户端 4、断开连接 引…

芯片设计公司外协ERP数字化运营:科技与管理的融合

随着信息技术的快速发展&#xff0c;ERP(企业资源计划)系统已经成为现代企业管理不可或缺的一部分。在芯片设计行业&#xff0c;由于产品的复杂性、技术的高要求以及市场的快速变化&#xff0c;外协ERP数字化运营显得尤为重要。 芯片设计公司的外协ERP数字化运营&#xff0c;主…

javaSwing员工工资管理系统(文档+视频+源码)

摘要 由Java swing mysql数据库实现的员工工资管理系统&#xff0c;该项目功能相对完善&#xff0c;有管理员和普通用户两个角色&#xff0c;分别实现了一些列功能&#xff0c;数据库采用的是mysql 系统实现 我们先以员工的身份查询一下&#xff1a; 接下来我们以管理员身份…

Qt | QCalendarWidget 类(日历)

01、QCalendarWidget 类 1、QCalendarWidget 类是 QWidget 的直接子类,该类用于日历,见下图 02、QCalendarWidget 属性 ①、dateEditAcceptDelay:int 访问函数:int dateEditAcceptDelay()const; void setDateEditAcceptDelay(int) 获取和设置日期编辑器的延迟时间(以毫秒…

事务的ACID是什么及扁平化事务、链式事务

一、什么是事务 1.事务&#xff08;Transaction)是区别于数据库文件系统的重要特性之一。事务会把数据库从一种一致状态转换为另一种一致状态。在数据库提交工作时&#xff0c;可以确保要么所有修改都已经保存&#xff0c;要么所有修改都不保存。 2.InnoDB存储引擎中的事物完…

深度学习之基于YoloV5车牌识别系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景与目标 随着智能交通系统的快速发展&#xff0c;车牌识别技术在交通管理、安防监控等领域扮演着越来越…

javaSwing购物系统项目(文档+视频+源码)

摘要 由Java swing实现的一款简单的购物程序&#xff0c;数据库采用的是mysql&#xff0c;该项目非常简单&#xff0c;实现了管理员对商品类型和商品的管理及用户注册登录后浏览商品、加入购物车、购买商品等功能&#xff0c;旨在学习Java 图形界面开发 系统实现 我们先来管理…