(stm32f103学习总结)—ADC模数转换实验
一、STM32F1 ADC介绍
TM32F103 系列一般都有 3 个 ADC,这些 ADC 可以独立使用,也可 以使用双重(提高采样率)。STM32F1 的 ADC 是 12 位逐次 逼近型的模拟数字转换器。它具有多达 18个复用通道,可测量来自16 个外部源、2 个内部源信号。 这些通道的 A/D 转换可 以单次、连续、扫描或间断模式执行。ADC 的结果可以左对齐或右对齐 方式存储在 16 位数据寄存器中。ADC具有模拟看门狗特性,允许应用程 序检测输入电压是否超出用户定义的阀值上限或者下限。
1.2 STM32F1 ADC结构框图
STM32F1 ADC拥有这么多功能,是由ADC内部结构所决定。要更好的理 解STM32F1的ADC,就需要了解它内部的结构。如下图所示:(大家 也可以查看《STM32F10x中文参考手册》-11模数转换器(ADC)章-ADC功 能说明)。
(1)标号1:电压输入引脚
ADC输入电压范围为: VREF- ≤ VIN ≤ VREF+。由 VREF-、 VREF+ 、 VDDA 、 VSSA这四个外部引脚决定。通常我们把 VSSA和 VREF-接地 ,把 VREF+和 VDDA 接 3.3V,因此ADC的输入电压范围为:0~3.3V。我 们使用的开发板ADC输入电压范围为0~3.3V。
(2)标号2:输入通道
STM32 的 ADC的输入通道多达 18 个,其中外部的 16 个通道就是框 图中的 ADCx_IN0、ADCx_IN1...ADCx_IN5(x=1/2/3,表示ADC数),通 过这16个外部通道可以采集模拟信号。这 16 个通道对应着不同的 IO 口, 具体是哪一个 IO 口可以从数据手册查询到,也可以从下图查 看,同样我们在开发板芯片原理图内也给大家标注了。其中 ADC1 还有2 个内部通道:ADC1 的通道16连接到了芯片内部的温度传感器,通道17连 接到了内部参考电压 VREFINT。ADC2 和ADC3的通道 16、 17全部连接到 了内部的 VSS。
(3)标号3:通道转换顺序
外部的 16 个通道在转换的时候可分为2组通道:规则通道组和注入 通道组,其中规则通道组最多有16路,注入通道组最多有 4 路。 规则通道组:从名字来理解,规则通道就是一种规规矩矩的通道,类 似于正常执行的程序,通常我们使用的都是这个通道。 注入通道组:从名字来理解,注入即为插入,是一种不安分的通道, 类似于中断。当程序正常往下执行时,中断可以打断程序的执行。同样 如果在规则通道转换过程中,有注入通道插入,那么就要先转换完注入 通道,等注入通道转换完成后再回到规则通道的转换流程。 每个组包含一个转换序列,该序列可按任意顺序在任意通道上完成。 例如,可按以下顺序对序列进行转换: ADC_IN3、ADC_IN8、 ADC_IN2、 ADC_IN2、 ADC_IN0、 ADC_IN2、 ADC_IN2、 ADC_IN15。
(4)标号4:触发源(外部触发和软件触发)
选择好输入通道,设置好转换顺序,接下来就可以开始转换。要开启 ADC转换,可以直接设置ADC 控制寄存器ADC_CR2 的 ADON位为1,即使能 ADC。当然ADC还支持外部事件触发转换,触发源有很多,具体选择哪一 种触发源,由 ADC 控制寄存器2:ADC_CR2 的 EXTSEL[2:0]和 JEXTSEL[2:0]位来控制。EXTSEL[2:0]用于选择规则通道的触发源, JEXTSEL[2:0]用于选择注入通道的触发源。选定好触发源之后,触发源 是否要激活,则由 ADC 控制寄存器ADC_CR2 的 EXTTRIG 和 JEXTTRIG 这两位来激活。 如果使能了外部触发事件,我们还可以通过设置 ADC 控制寄存器 2:ADC_CR2 的EXTEN[1:0]和 JEXTEN[1:0]来控制触发极性,可以有 4 种 状态,分别是:禁止触发检测、上升沿检测、下降沿检测以及上升沿和 下降沿均检测。
(5)标号5:ADC时钟
ADC 输入时钟 ADC_CLK 由 APB2经过分频产生,最大值是14MHz,分 频因子由 RCC 时钟配置寄存器 RCC_CFGR 的位 15:14 ADCPRE[1:0]设置 ,可以是 2/4/6/8 分频,注意这里没有 1 分频。我们知道APB2总线时 钟为72M,而ADC最大工作频率为14M,所以一般设置分频因子为6,这样 ADC的输入时钟为12MHz。
ADC要完成对输入电压的采样需要若干个ADC_CLK周期,采样的周期数 可通过ADC 采样时间寄存器 ADC_SMPR1 和 ADC_SMPR2 中的 SMP[2:0]位 设置, ADC_SMPR2控制的是通道 0~9, ADC_SMPR1 控制的是通道 10~17 。每个通道可以分别用不同的时间采样。其中采样周期最小是1.5个,即 如果我们要达到最快的采样,那么应该设置采样周期为1.5个周期,这里 说的周期就是 1/ADC_CLK。
ADC 的总转换时间跟ADC 的输入时钟和采样时间有关,其公式如下:
(转换时间) Tconv = 采样时间 + 12.5个周期
其中Tconv为ADC总转换时间,当ADC_CLK=14Mhz的时候,并设置1.5个周 期的采样时间,则Tcovn=1.5+12.5=14个周期=1us。
(6)标号6:数据寄存器
ADC 转换后的数据根据转换组的不同,规则组的数据放在ADC_DR 寄 存器内,注入组的数据放在 JDRx内。 因为STM32F1的ADC是12位转换精度,而数据寄存器是16位,所以ADC 在存放数据的时候就有左对齐和右对齐区分。如果是左对齐,AD转换完 成数据存放在 ADC_DR 寄存器的[4:15]位内;如果是右对齐,则存放在 ADC_DR 寄存器的[0:11]位内。具体选择何种存放方式,需通过ADC_CR2 的 11 位 ALIGN 设置。
(7)标号7:中断
当发生如下事件且使能相应中断标志位时,ADC能产生中断。
1.转换结束(规则转换)与注入转换结束
2.模拟看门狗事件
3.DMA请求
二、STM32F1 ADC配置步骤
(1)使能端口时钟和ADC时钟,设置引脚模式为模拟输入
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AN; //模拟输入模式
(2)设置ADC的分频因子
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
(3)初始化ADC参数,包括ADC工作模式、规则序列等
ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);
(4)使能ADC并校准
ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);
ADC_Cmd(ADC1, ENABLE);//开启AD转换器
执行复位校准的方法是: ADC_ResetCalibration(ADC1);
执行 ADC 校准的方法是: ADC_StartCalibration(ADC1); //开始指定 ADC1 的校准状态
while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束
while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束
(5)读取ADC转换值 设置规则序列通道以及采样周期的库函数是:
ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel,uint8_t Rank, uint8_t ADC_SampleTime);
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5 )
设置好规则序列通道及采样周期,接下来就要开启转换,由于我们采 用的是软件触发,库函数
ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
要开启 ADC转换.
三、编写ADC控制程序
本章所要实现的功能是:通过ADC1通道1采样外部电压值,将采样的 AD值和转换后的电压值通过串口打印出来,同时D1指示灯闪烁,提示系 统正常运行。
程序框架如下: (1)初始化ADC1_IN1相关参数,开启ADC1 (2)编写获取ADC1_IN1的AD转换值函数 (3)编写主函数
- 1 #ifndef _adc_H
- 2 #define _adc_H
- 3
- 4 #include "system.h"
- 5
- 6 void ADCx_Init(void);
- 7 u16 Get_ADC_Value(u8 ch,u8 times);
- 8
- 9
- 10 #endif
- 1 #include "adc.h"
- 2 #include "SysTick.h"
- 3
- 4 /*******************************************************************************
- 5 * 函 数 名 : ADCx_Init
- 6 * 函数功能 : ADC初始化
- 7 * 输 入 : 无
- 8 * 输 出 : 无
- 9 *******************************************************************************/
- 10 void ADCx_Init(void)
- 11 {
- 12 GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量
- 13 ADC_InitTypeDef ADC_InitStructure;
- 14
- 15 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);
- 16
- 17 RCC_ADCCLKConfig(RCC_PCLK2_Div6);//设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
- 18
- 19 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;//ADC
- 20 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN; //模拟输入
- 21 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
- 22 GPIO_Init(GPIOA,&GPIO_InitStructure);
- 23
- 24 ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
- 25 ADC_InitStructure.ADC_ScanConvMode = DISABLE;//非扫描模式
- 26 ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//关闭连续转换
- 27 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//禁止触发检测,使用软件触发
- 28 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐
- 29 ADC_InitStructure.ADC_NbrOfChannel = 1;//1个转换在规则序列中 也就是只转换规则序列1
- 30 ADC_Init(ADC1, &ADC_InitStructure);//ADC初始化
- 31
- 32 ADC_Cmd(ADC1, ENABLE);//开启AD转换器
- 33
- 34 ADC_ResetCalibration(ADC1);//重置指定的ADC的校准寄存器
- 35 while(ADC_GetResetCalibrationStatus(ADC1));//获取ADC重置校准寄存器的状态
- 36
- 37 ADC_StartCalibration(ADC1);//开始指定ADC的校准状态
- 38 while(ADC_GetCalibrationStatus(ADC1));//获取指定ADC的校准程序
- 39
- 40 ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能或者失能指定的ADC的软件转换启动功能
- 41 }
- 42
- 43 /*******************************************************************************
- 44 * 函 数 名 : Get_ADC_Value
- 45 * 函数功能 : 获取通道ch的转换值,取times次,然后平均
- 46 * 输 入 : ch:通道编号
- 47 times:获取次数
- 48 * 输 出 : 通道ch的times次转换结果平均值
- 49 *******************************************************************************/
- 50 u16 Get_ADC_Value(u8 ch,u8 times)
- 51 {
- 52 u32 temp_val=0;
- 53 u8 t;
- 54 //设置指定ADC的规则组通道,一个序列,采样时间
- 55 ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5); //ADC1,ADC通道,239.5个周期,提高采样时间可以提高精确度
- 56
- 57 for(t=0;t<times;t++)
- 58 {
- 59 ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能指定的ADC1的软件转换启动功能
- 60 while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
- 61 temp_val+=ADC_GetConversionValue(ADC1);
- 62 delay_ms(5);
- 63 }
- 64 return temp_val/times;
- 65 }
- 1 #include "system.h"
- 2 #include "SysTick.h"
- 3 #include "led.h"
- 4 #include "usart.h"
- 5 #include "adc.h"
- 6
- 7
- 8 /*******************************************************************************
- 9 * 函 数 名 : main
- 10 * 函数功能 : 主函数
- 11 * 输 入 : 无
- 12 * 输 出 : 无
- 13 *******************************************************************************/
- 14 int main()
- 15 {
- 16 u8 i=0;
- 17 u16 value=0;
- 18 float vol;
- 19
- 20 SysTick_Init(72);
- 21 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组 分2组
- 22 LED_Init();
- 23 USART1_Init(9600);
- 24 ADCx_Init();
- 25
- 26 while(1)
- 27 {
- 28 i++;
- 29 if(i%20==0)
- 30 {
- 31 led1=!led1;
- 32 }
- 33
- 34 if(i%50==0)
- 35 {
- 36 value=Get_ADC_Value(ADC_Channel_1,20);
- 37 printf("检测AD值为:%d\r\n",value);
- 38 vol=(float)value*(3.3/4096);
- 39 printf("检测电压值为:%.2fV\r\n",vol);
- 40 }
- 41 delay_ms(10);
- 42 }
- 43 }
(stm32f103学习总结)—ADC模数转换实验的更多相关文章
- STM32学习笔记(七) ADC模数转换测电平(普通和DMA模式)
嵌入式系统在微控制领域(温度,湿度,压力检测,四轴飞行器)中占据着重要地位,这些功能的实现是由微处理器cpu(如stm32)和传感器以及控制器共同完成的,而连接他们,使它们能够互相正常交流的正是本小节 ...
- Keil MDK STM32系列(六) 基于抽象外设库HAL的ADC模数转换
Keil MDK STM32系列 Keil MDK STM32系列(一) 基于标准外设库SPL的STM32F103开发 Keil MDK STM32系列(二) 基于标准外设库SPL的STM32F401 ...
- 【StatLearn】统计学习中knn算法实验(2)
接着统计学习中knn算法实验(1)的内容 Problem: Explore the data before classification using summary statistics or vis ...
- (stm32f103学习总结)—stm32 PMW输出实验
一.PWM简介 PWM是 Pulse Width Modulation 的缩写,中文意思就是脉冲宽度调 制,简称脉宽调制.它是利用微处理器的数字输出来对模拟电路进行控 制的一种非常有效的技术,其控制简 ...
- (stm32f103学习总结)—RTC独立定时器—实时时钟实验
一.STM32F1 RTC介绍 1.1 RTC简介 STM32 的实时时钟( RTC)是一个独立的定时器. STM32 的 RTC 模 块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的 ...
- (stm32f103学习总结)—待机唤醒实验
一.STM32待机模式介绍 1.1 STM32低功耗模式介绍 很多单片机具有低功耗模式,比如MSP430.STM8L等,我们的STM32 也不例外.默认情况下,系统复位或上电复位后,微控制器进入运行模 ...
- Arduino学习笔记⑤ 模拟IO实验
1.前言 还记得前几个我们都是在讲解数字IO,而其实我们生活中大多数信号都是模拟信号,如声音以及温度变化.在Arduino中,常用0~5v的电压来表示模拟信号. 1.1 模拟输入功能 ...
- zju(7)ADC操作实验
1.实验目的 1.学习和掌握S3C2410下ADC接口的操作方法以及应用程序的编写: 二.实验内容 1.编写EduKit-IV实验箱Linux操作系统下按键ADC的应用程序,并显示ADC的值. 三.主 ...
- stm32学习总结)—SPI-FLASH 实验 _
SPI总线 SPI 简介 SPI 的全称是"Serial Peripheral Interface",意为串行外围接口,是Motorola 首先在其 MC68HCXX 系列处理器上 ...
随机推荐
- JavaWeb后端
JavaWeb后端 我们学习JavaWeb的最终目的是为了搭建一个网站,并且让用户能访问我们的网站并在我们的网站上做一些事情. 计算机网络基础 在计算机网络(谢希仁 第七版 第264页)中,是这样描述 ...
- 路径修改后cmd命令行窗口仍然没有变化的原因
修改环境变量后,要重启cmd再输入才有用
- linux echo用法和实例
echo命令用于在shell中打印shell变量的值,或者直接输出指定的字符串.linux的echo命令,在shell编程中极为常用, 在终端下打印变量value的时候也是常常用到的,因此有必要了解下 ...
- 解决github网站打不开的方法
发现github最近经常抽风,之前发现打不开时就挂个梯子,最近梯子也都被封了,尝试了下改host发现效果挺好,方法如下(Mac电脑): 1.通过站长工具找出DNS地址:进入站长工具网站的域名解析网址: ...
- 如何取消 UIView 动画?
原文链接 最近项目中有一个需求是需要手动点击相机对焦,这里由于相机对焦部分需要一个类似于系统对焦框一样的缩放动画,同时动画时长为0.3秒,因此这里就有一个很普遍的需求,如果用户在0.3秒内继续点击对焦 ...
- AT1219题解
题意 设 \(a\) 的价值为 \(a \times cnt_a\)(\(cnt_a\) 为 \(a\) 在区间中出现的次数),求区间种某种元素,使得这种元素的价值最大. 因为设计出现元素的次数,所以 ...
- VS2022不能使用<bits/stdc++.h>的解决方案
•<bits/stdc++.h>介绍 #include<bits/stdc++.h> 包含了目前 C++ 所包含的所有头文件,又称万能头文件,简直是开挂一般的存在. 你编程 ...
- 比较 Java 静态工厂方法与构造函数
1 什么是静态工厂方法 Java 静态工厂方法是在方法前加上 public static,让这个方法变为公开.静态的方法.该方法返回该类的一个实例,就好像一个工厂生产出一个产品.所以称之为静态工厂方法 ...
- 测试杂谈——一条SQL引发的思考
此篇只是个人记录,相信各位大神早已轻车熟路,不喜勿喷:有错之处,欢迎指正. 有一天收到新人的咨询,是关于sql的问题. 问题1:为什么sql查询的数据与界面展示的不准确: 问题2:为什么sql查询时间 ...
- CodeGym-17~20
读文章 0.如果是基本数据类型的话,在数组中就存储特定的值:如果是对象的话,在数组中就是存储对象的引用. 1.数组本身就是对象 再读文章 0.Arrays.sort(array); Arrays.to ...