STM32学习笔记Day3

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

今日学习内容是STM32的ADC外设模块,STM32的ADC为12位,AD的最大值位4095,对应的最大电压位3.3v,可对0-3.3v之间的任意电压量化,所以ADC相当于一个电压表。而对于GPIO而言只能读取引脚的高低电平两个值。了解ADC的基本结构,学会初始化ADC,今天主要有两个实验,使用ADC实现测量单通道ADC测量电压和多通道测量ADC电压。


提示:以下是本篇文章正文内容,下面案例可供参考

一、ADC简介

1、概述

ADC(模拟-数字转换器),ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁。STM32的ADC采用的是12位逐次逼近型ADC,所谓逐次逼近就是采用计算机当中的二分法比较输入的模拟电压与逐次逼近寄存器SAR当中的存储值。
在这里插入图片描述
(1)12位逐次逼近型ADC,1us转换时间。这里涉及到ADC的两个关键参数。第一个是分辨率,一般用多少位表示,表示可量化的精细度。第二个是转换时间也即转换频率,AD转换需要一定的时间,1us表示AD转换开始到产生结果的时间,对应的频率为1MHz.
(2)规则组和注入组,规则组最多允许 16 个输入通道进行转换,而注入组最多允许 4 个输入通道进行转换。规则组:按照一定的顺序,相当于正常运行的程序。注入组:打破原来的规则组的转换,只有等到注入组被转换完成之后,规则组才能够继续转换。但是这里需要注意的是规则组AD数据寄存器的值会被后来的值覆盖,所以需要及时获取AD数据寄存器当中的值,可以结合DMA实现跟注入组一样的效果。规则组用于常规使用,注入组用于突发事件。
(3)STM32F103C8T6 ADC资源:ADC1、ADC2,10个外部输入通道。
ADC 的输入时钟是由 PCLK2 经过分频产生的,分频系数是由 RCC_CFGR 寄存器的ADCPRE[1:0]位设置的,可选择 2/4/8/16 分频。需要注意的是,ADC 的输入时钟频率最大值是14MHz,如果超过这个值将会导致 ADC 的转换结果准确度下降。

2、图示详解

1、外挂式逐次逼近型ADC

在这里插入图片描述
上图便是外挂逐次逼近型ADC的基本结构。
1、左边IN0-IN7是8路输入通道,通过通道选择开关选中一路输入到下一步进行转换,地址锁存和姨妈就是想选中哪个通道(8路)就把通道号放在ADDA-ADDC三个引脚上,ALE给一个锁存信号对应上面的通路开关就可自动调试好。
2、逐次逼近方法:信号到一个电压比较器,可以判断两个输入信号电压的大小关系,输出一个高低电平指示谁大谁小;两个输入端一个为待测电压,另一个是DAC的电压输出端,电压调节的过程由图中的逐次逼近SAR完成,为了快速常使用二分法查找,8位的ADC从高位到地位需要依次判断8次,12位的需要12次。
3、AD转换结束后,DAC的输入数据(SAR向下的双箭头)就是位置待测电压的编码,通过朝右的双箭头输出到三态锁存缓冲器,8位8根线,12位12根线。

2、ADC中断

ADC 中断可分为三种:规则组转换结束中断、注入组转换结束中断、设置了模拟看门狗状态位中断。
模拟看门狗中断:模拟看门狗中断发生条件:首先通过ADC_LTR和ADC_HTR寄存器设置低阈值和高阈值,然后开启了模拟看门狗中断后,当被 ADC 转换的模拟电压低于低阈值或者高于高阈值时,就
会产生中断。
DMA请求:规则组和注入组的转换结束后,除了可以产生中断外,还可以产生 DMA 请求,我们利用
DMA 及时把转换好的数据传输到指定的内存里,防止数据被覆盖。注意只有ADC1和ADC3可以产生DMA请求。

3、单次转换模式与连续转换模式

(1)单次转换模式
通过将ADC_CR2寄存器的CONT位置0选择单词转换模式。在该模式下ADC只触发一次转换,可以通过ADC_CR2寄存器的ADON位启动(只适用于规则组),也可以通过外部触发启动。
规则组的转换结果存放在16位的ADC_DR寄存器中、注入组的转换结果存放在ADC_DRJ寄存器当中。
(2)连续转换模式
通过将 ADC_CR2 寄存器的 CONT 位置 1 选择连续转换模式。该模式下,ADC 完成上一个通道的转换后会马上自动地启动下一个通道的转换,由 ADC_CR2 寄存器的 ADON 位启动,也可以通过外部触发启动。
(3)扫描模式
可以通过 ADC_CR1 寄存器的 SCAN 位配置是否使用扫描模式。如果选择扫描模式,ADC会扫描所有被 ADC_SQRx 寄存器或 ADC_JSQR 选中的所有通道,并对规则组或者注入组的每个通道执行单次转换,然后停止转换。但如果还设置了 CONT 位,即选择连续转换模式,那么转换不会在选择组的最后一个通道上停止,而是再次从选择组的第一个通道继续转换。

4、数据对齐

在转换后得到的结果是12位,但是数据寄存器是16位,所以存在数据对齐的问题,高位补0。一般选择数据右对齐的方式,这样可以读取16位寄存器直接就是转换结果。

5、校准

ADC有一个内置自校准模式,校准可以大幅减小因内部电容器组的变化而造成的准精度误差。校准期间,在每个电容器上都会计算出一个误差修正码,这个码用于消除之后的转换中每个电容器上的误差,应用ADC_StartCalibration ()和ADC_GetCalibrationStatus ()这两个函数来实现ADC的校准功能。

二、实操案例

1.AD单通道

代码如下(示例):
单通道ADC采集配置步骤
(1)开启ADCX和ADC通道对应的IO时钟,并配置IO为模拟功能
(2)初始化ADCx,配置其工作参数
(3)配置ADC通道并启动AD转换器
(4)读取ADC值

//AD.c
#include "stm32f10x.h"                  // Device header
//根据ADC基本结构图,打通它即可:
//1、开启RCC时钟,包括ADC和GPIO的时钟;ADCCLK的分频器也需要配置下
//2、配置GPIO,把需要用的GPIO配置为模拟输入模式
//3、配置多路开关,把左边的通道接入到右边的规则组列表里(“点菜”)
//4、配置ADC转换器,利用库函数里的结构体,可配置包括AD转换器和AD数据寄存器在内的一大块的电路
   //(包括ADC是单次还是连续、扫描还是非扫描、几个通道、触发源是什么、数据对齐是左or右对齐)
//其他的,如果需要模拟看门狗,会有几个函数用来配置阈值和监测通道。
//如果想开启中断,可在中断输出函数控制里用ITConfig函数开启对应的中断输出,然后在NVIC里配置下优先级就可触发中断。
//实例代码中暂未用到模拟看门狗和中断。
//5、开关控制,ADC_Cmd()函数开启ADC。
//6、根据手册建议,开启后还可对其进行下校准,可减小误差。
void AD_Init(void){
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);//6分频
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN ;//选择模拟输入模式即AIN
	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);//一个口非扫描模式,点一个菜。“1”表示序列1的位置,加上Channel1表示在序列1处写入通道1,第四个参数与采样时间有关根据需要。
	//ADC_RegularChannelConfig(ADC1,ADC_Channel_3,2,ADC_SampleTime_55Cycles5);//多个序列可在后面加,此处就一个输入口PA0
	
	ADC_InitTypeDef ADC_InitStructure;
	ADC_InitStructure.ADC_Mode= ADC_Mode_Independent;//独立模式,ADC1和ADC2各转换各的。其他为双ADC模式较复杂
	ADC_InitStructure.ADC_DataAlign= ADC_DataAlign_Right;//数据对齐:右对齐
	ADC_InitStructure.ADC_ExternalTrigConv= ADC_ExternalTrigConv_None;//触发源:软件触发
	ADC_InitStructure.ADC_ContinuousConvMode= DISABLE;//转换模式:单次转换
	ADC_InitStructure.ADC_ScanConvMode= DISABLE;//转换模式:非扫描
	ADC_InitStructure.ADC_NbrOfChannel= 1;//通道数目:
	ADC_Init(ADC1,&ADC_InitStructure);
	
	ADC_Cmd(ADC1,ENABLE);
	
	ADC_ResetCalibration(ADC1);//校准
	while (ADC_GetCalibrationStatus(ADC1) == SET);//检查校准
	ADC_StartCalibration(ADC1);//开始指定 ADC 的校准程序
	while (ADC_GetCalibrationStatus(ADC1) == SET);//获取指定 ADC 的校准程序
}

uint16_t AD_GetValue(void){
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);//软件触发,ADC开始转换
	while (ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET);//ADC转换需要一定时间
	return ADC_GetConversionValue(ADC1);//获取转换值
}

2、AD多通道

在上面的单次转换、非扫描模式基础上,在每次触发转换之前,手动更改下列表第一个位置的通道,比如第一次转换先写入通道哦,之后触发、等待、读值;第二次转换把通道0改为通道1。

#include "stm32f10x.h"                  // Device header

void AD_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
		
	ADC_InitTypeDef ADC_InitStructure;
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;
	ADC_InitStructure.ADC_NbrOfChannel = 1;
	ADC_Init(ADC1, &ADC_InitStructure);
	
	ADC_Cmd(ADC1, ENABLE);
	
	ADC_ResetCalibration(ADC1);
	while (ADC_GetResetCalibrationStatus(ADC1) == SET);
	ADC_StartCalibration(ADC1);
	while (ADC_GetCalibrationStatus(ADC1) == SET);
}

uint16_t AD_GetValue(uint8_t ADC_Channel)
{
	ADC_RegularChannelConfig(ADC1, ADC_Channel, 1, ADC_SampleTime_55Cycles5);
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);
	while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
	return ADC_GetConversionValue(ADC1);
}



# 总结

STM32F103 系列芯片拥有 3 个 ADC(C8T6 只有 2 个),这些 ADC 可以独立使用,其中ADC1 和 ADC2 还可以组成双重模式(提高采样率)。STM32 的 ADC 是 12 位逐次逼近型的模拟数字转换器。它有 18 个通道,可测量 16 个外部和 2 个内部信号源,其中 ADC3 根据 CPU 引脚的不同其通道数也不同,一般有 8 个外部通道。ADC 中的各个通道的 A/D 转换可以单次、连续、扫描或间断模式执行。ADC 的结果可以以左对齐或者右对齐存储在 16 位数据寄存器中,一定对ADC的基本结构有个清除的了解跟认识。

![在这里插入图片描述](https://img-blog.csdnimg.cn/fe2dcff5ad374bb890d3e4a57e6ff06b.png)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值