一、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模数转换实验的更多相关文章

  1. STM32学习笔记(七) ADC模数转换测电平(普通和DMA模式)

    嵌入式系统在微控制领域(温度,湿度,压力检测,四轴飞行器)中占据着重要地位,这些功能的实现是由微处理器cpu(如stm32)和传感器以及控制器共同完成的,而连接他们,使它们能够互相正常交流的正是本小节 ...

  2. Keil MDK STM32系列(六) 基于抽象外设库HAL的ADC模数转换

    Keil MDK STM32系列 Keil MDK STM32系列(一) 基于标准外设库SPL的STM32F103开发 Keil MDK STM32系列(二) 基于标准外设库SPL的STM32F401 ...

  3. 【StatLearn】统计学习中knn算法实验(2)

    接着统计学习中knn算法实验(1)的内容 Problem: Explore the data before classification using summary statistics or vis ...

  4. (stm32f103学习总结)—stm32 PMW输出实验

    一.PWM简介 PWM是 Pulse Width Modulation 的缩写,中文意思就是脉冲宽度调 制,简称脉宽调制.它是利用微处理器的数字输出来对模拟电路进行控 制的一种非常有效的技术,其控制简 ...

  5. (stm32f103学习总结)—RTC独立定时器—实时时钟实验

    一.STM32F1 RTC介绍 1.1 RTC简介 STM32 的实时时钟( RTC)是一个独立的定时器. STM32 的 RTC 模 块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的 ...

  6. (stm32f103学习总结)—待机唤醒实验

    一.STM32待机模式介绍 1.1 STM32低功耗模式介绍 很多单片机具有低功耗模式,比如MSP430.STM8L等,我们的STM32 也不例外.默认情况下,系统复位或上电复位后,微控制器进入运行模 ...

  7. Arduino学习笔记⑤ 模拟IO实验

    1.前言     还记得前几个我们都是在讲解数字IO,而其实我们生活中大多数信号都是模拟信号,如声音以及温度变化.在Arduino中,常用0~5v的电压来表示模拟信号. 1.1 模拟输入功能      ...

  8. zju(7)ADC操作实验

    1.实验目的 1.学习和掌握S3C2410下ADC接口的操作方法以及应用程序的编写: 二.实验内容 1.编写EduKit-IV实验箱Linux操作系统下按键ADC的应用程序,并显示ADC的值. 三.主 ...

  9. stm32学习总结)—SPI-FLASH 实验 _

    SPI总线 SPI 简介 SPI 的全称是"Serial Peripheral Interface",意为串行外围接口,是Motorola 首先在其 MC68HCXX 系列处理器上 ...

随机推荐

  1. Hadoop2.7.2源码编译过程

    目录 准备工作 jar包安装 源码编译 准备工作 CentOS可以联网,验证:ping www.baidu.com 是畅通的 jar 包准备(hadoop 源码.JDK8.maven.ant .pro ...

  2. win7下安装Hadoop

    1 下载准备 下载hadoop,官网用一个快一点的镜像,使用迅雷加速下载,二进制格式,解压目录:E:\hadoop\hadoop-2.9.2 下载winutils,这个是别人编译好的hadoop的wi ...

  3. linux(Centos7)安装mysql

    查看系统环境 [root@localhost html]# cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core) CentOS 7 ...

  4. js实现密码输入框对开启键盘大写锁定的提示(IE浏览器下有自动识别提示则不执行(用IE自带效果即可))

    代码如下: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <tit ...

  5. Java 将XML转为PDF

    可扩展标记语言(XML)文件是一种标准的文本文件,它使用特定的标记来描述文档的结构以及其他特性.通过将XML转换为PDF,能够便于文件传输及共享.本文,将介绍通过Java代码来实现该格式转换的方法. ...

  6. 矩池云 | 新冠肺炎防控:肺炎CT检测

    连日来,新型冠状病毒感染的肺炎疫情,牵动的不仅仅是全武汉.全湖北,更是全国人民的心,大家纷纷以自己独特的方式为武汉加油!我们相信坚持下去,终会春暖花开. 今天让我们以简单实用的神经网络模型,来检测肺炎 ...

  7. netty搭建rpc框架

    介绍 netty想必大家都不陌生,我就不废话介绍了...(主要是懒,网上资料很多的) 本文主要使用netty搭建rpc远程调用框架,实现了个注册中心微服务,整合了springboot例子... 开发内 ...

  8. java面试:java基础、Io、容器

    1.java基础 1.JDK 和JRE有什么区别 ​ JDK:java开发工具包,java开发运行环境.包含了JRE. ​ JRE:java运行环境,包含java虚拟机,java基础类库. 2.jav ...

  9. 分布式 PostgreSQL 集群(Citus)官方示例 - 实时仪表盘

    Citus 提供对大型数据集的实时查询.我们在 Citus 常见的一项工作负载涉及为事件数据的实时仪表板提供支持. 例如,您可以是帮助其他企业监控其 HTTP 流量的云服务提供商.每次您的一个客户端收 ...

  10. Airtest安装与简介

    一:简介 什么是Airtest 网易的airtest其实是个测试套件,由Airtest框架.poco框架.airtestIDE 组成. Airtest框架 基于图像识别的自动化测试框架,是网易自己团队 ...