STM32_ADC

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 headervoid 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);//如果是连续转换模式,仅需要在最开始触发一次就行了,所以只要把下面软件触发转换的函数放在初始化函数最后面就行,在初始化完成后触发一次就行了//第五步,开关控制,开启ADCADC_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)
{//初始化OLEDOLED_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.mzph.cn/web/13682.shtml

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

相关文章

P6【力扣144,94,145】【数据结构】【二叉树遍历】C++版

【144】二叉树的前序遍历 1、递归法&#xff1a; class Solution { public:void preorder(TreeNode* root, vector<int> &res){if(root nullptr){return;}res.push_back(root->val);preorder(root->left, res);preorder(root->right, res);}vector<in…

没有密码如何卸载卡巴斯基?

如果忘记卡巴斯基6.0的保护密码&#xff0c; &#xff08;1&#xff09;进入安全模式下 &#xff08;2&#xff09;打开6.0的安装目录 Kaspersky Anti-Virus 6.0: C://Program Files//Kaspersky Lab//Kaspersky Anti-Virus 6.0 &#xff08;3&#xff09;将目录中的avp.exe改…

CVE-2020-7982 OpenWrt 远程命令执行漏洞学习(更新中)

OpenWrt是一款应用于嵌入式设备如路由器等的Linux操作系统。类似于kali等linux系统中的apt-get等&#xff0c;该系统中下载应用使用的是opgk工具&#xff0c;其通过非加密的HTTP连接来下载应用。但是其下载的应用使用了SHA256sum哈希值来进行检验&#xff0c;所以将下载到的数据…

开发过程中使用MySQL和Oracle的差异

前言 小型项目中使用MySQL的占比还是相对较高的&#xff0c;但是也不排除随着项目的扩大&#xff0c;产品的丰富&#xff0c;或者甲方的财大气粗&#xff0c;有可能会有MySQL换成Oracle。那么这两者对于开发者而言&#xff0c;有什么差异化的地方呢。 官方文档 MySQL5.7 htt…

weblogic简介

WebLogic是美国Oracle公司出品的一个Application Server&#xff0c;它是一个基于JAVA EE架构的中间件。WebLogic主要用于开发、集成、部署和管理大型分布式Web应用、网络应用和数据库应用的Java应用服务器。它将Java的动态功能和Java Enterprise标准的安全性引入大型网络应用的…

什么是安全左移如何实现安全左移

文章目录 一、传统软件开发面临的安全挑战二、什么是安全左移四、安全左移与安全开发生命周期&#xff08;SDL&#xff09;三、安全左移对开发的挑战五、从DevOps到DevSecOps六、SDL与DevSecOps 一、传统软件开发面临的安全挑战 传统软件开发面临的安全挑战主要包括以下几个方…

yarn常用命令

Yarn 是一个快速、可靠且安全的依赖管理工具&#xff0c;用于替代 npm。以下是一些常用的 Yarn 命令&#xff0c;用于不同的包管理和项目依赖安装场景&#xff1a; 初始化一个新的项目 yarn init这个命令会引导你创建一个 package.json 文件。 安装依赖 yarn add [package]…

抄表:现代生活中的数据采集关键

1.界定与发源 抄表&#xff0c;简单的说&#xff0c;指从各种各样计量机器设备(如智能水表、电度表、天然气表等)载入做好记录使用量的全过程。这一概念自工业化时代至今就出现了&#xff0c;最初由人工进行&#xff0c;伴随着科技创新&#xff0c;如今已经演化出自动化和远程…

Java中的时间戳【详解】

一.何为Java时间戳 在Java中&#xff0c;时间戳通常指的是自1970年1月1日午夜&#xff08;UTC&#xff09;以来的毫秒数。 这个概念在Java中主要通过java.util.Date类和java.sql.Timestamp类来表示 而在Java 8及以后的版本中&#xff0c;引入了新的日期时间API&#xff0c;即…

给大家分享一套非常棒的python机器学习课程

给大家分享一套非常棒的python机器学习课程——《AI小天才&#xff1a;让小学生轻松掌握机器学习》&#xff0c;2024年5月完结新课&#xff0c;提供配套的代码笔记软件包下载&#xff01;学完本课程&#xff0c;可以轻松掌握机器学习的全面应用&#xff0c;复杂特征工程&#x…

【C++刷题】优选算法——递归第三辑

floodfill篇 图像渲染 unordered_multimap<int, int> direction {{0, 1},{0, -1},{1, 0},{-1, 0} }; void dfs(vector<vector<int>>& image, int sr, int sc, int color, int val) {image[sr][sc] color;for(auto& e : direction){int x sr e.…

关于微服务的一点感悟和过往经验的思考

一、为什么有微服务 解决单体应用的局限性 随着业务发展&#xff0c;业务逻辑复杂、关联方多&#xff0c;导致业务系统的代码臃肿、难于做迭代或者维护&#xff0c;导致很多的问题&#xff0c;如&#xff1a;bug多、难于维护修复、每次需要评估改动服务接口影响的范围&#xf…

碰撞器触发事件(OnTriggerEnter/OnTriggerStay/OnTriggerExit)

碰撞器触发事件&#xff08;OnTriggerEnter/OnTriggerStay/OnTriggerExit&#xff09;简介 在Unity中&#xff0c;触发器事件是当一个游戏对象进入、停留或离开另一个游戏对象的触发器碰撞器时发生的事件。这些事件分别是: OnTriggerEnter: 当其他Collider首次进入触发器时调用…

服务端Web资源缓存

1.前言 虽然客户端缓存效果很好&#xff0c;但它有一个核心问题&#xff1a;要在本地提供资源&#xff0c;必须先将其存储在缓存中。因此&#xff0c;每个客户端都需要其缓存的资源。如果请求的资源需要大量计算&#xff0c;则无法扩展。服务器端缓存背后的理念是计算一次资源…

【CAN】libsocketcan库详解

1、简介 libsocketcan是用户空间通过SocketCAN操作CAN的接口。 源码:https://github.com/linux-can/libsocketcan 2、API详解 2.1 can_do_restart 1)说明:重启CAN接口 2)原型: int can_do_restart(const char *name);3)参数: name:CAN接口名,比如:can0、can1,…

继续分析开发人员容易被骗的原因和防范措施

继续分析开发人员容易被骗的原因和防范措施&#xff0c;可以深入探讨一些具体的技术细节和实际操作建议&#xff0c;以更全面地理解和应对这一问题。 技术细节&#xff1a; 未加密的敏感数据传输&#xff1a; 原因&#xff1a;开发人员可能忽视了数据传输过程中的安全性&#…

第10章 软件架构的演化和维护

软件架构周期&#xff1a;初始设计、实际使用、修改完善(这就是演化)、退化弃用。 演化和维护的目的&#xff1a;为了使软件能够适应环境的变化而进行的纠错性修改和完善性修改等&#xff0c;而且这个过程是一个不断迭代的过程。 架构演化的重要性、演化过程、演化分类、演化…

Vary HTTP 标头

1.前言 服务器端 Web 资源缓存的想法是在客户端和上游之间设置一个组件来缓存先前计算的结果&#xff0c;以避免后者过载。根据您的基础架构和要求&#xff0c;此组件可以是反向代理或 API 网关。HTTP 提供Cache-Control标头来自定义缓存的不同方面&#xff0c;例如&#xff0…

Java——通过方法交换实参值

想写一个方法来交换main函数中的两个变量值&#xff0c;代码如下&#xff1a; public class Test {public static void swap(int x,int y) {int tmp x;x y;y tmp;}public static void main(String[] args) {int a 10;int b 20;System.out.println("交换前&#xff1…

Autodesk Maya 2025软件安装教程(附软件下载地址)

软件简介&#xff1a; 软件【下载地址】获取方式见文末。注&#xff1a;推荐使用&#xff0c;更贴合此安装方法&#xff01; Autodesk Maya 2025是一款领先的三维动画设计软件&#xff0c;界面直观且功能丰富。它集成了全球领先的3D设计技术&#xff0c;提供了多种创意功能&a…