5. ADC模数转换器

1、ADC简介

ADC Analog-Digital Converter )模拟 - 数字转换器
ADC 可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁
12 位逐次逼近型 ADC 1us 转换时间
输入电压范围: 0~3.3V ,转换结果范围: 0~4095
18 个输入通道,可测量 16 个外部和 2 个内部信号源
规则组和注入组两个转换单元
模拟看门狗自动监测输入电压范围
STM32F103C8T6 ADC 资源: ADC1 ADC2 10 个外部输入通道

 2、逐次逼近型ADC

3、 ADC框图

左边ADC输入通道16个GPIO口,IN0~IN15和两个内部通道,一个温度传感器,一个VREFINT(V Reference Internal),内部参考电压。

模式转换器执行的就是逐次比较的工程,然后转换结果放在数据寄存器中。

规则通道虽然能有十六组数据,但是寄存器只能存储最后一组,前面的都会被覆盖。需要结合DMA使用。

RCC为72M时,ADC预分频只能6分频12M或者8分频9M。

4、ADC基本结构

5、 输入通道与引脚复用关系

通道

ADC1

ADC2

ADC3

通道0

PA0

PA0

PA0

通道1

PA1

PA1

PA1

通道2

PA2

PA2

PA2

通道3

PA3

PA3

PA3

通道4

PA4

PA4

PF6

通道5

PA5

PA5

PF7

通道6

PA6

PA6

PF8

通道7

PA7

PA7

PF9

通道8

PB0

PB0

PF10

通道9

PB1

PB1

通道10

PC0

PC0

PC0

通道11

PC1

PC1

PC1

通道12

PC2

PC2

PC2

通道13

PC3

PC3

PC3

通道14

PC4

PC4

通道15

PC5

PC5

通道16

温度传感器

通道17

内部参考电压

6、转换模式

单次非扫描

在序列1定义通道2触发转换,然后模拟电压转换为数字信号,存储在寄存器里,同时,EOC标志置1。然后在想使用,同上。

 连续转换非扫描

 优点,开始转换后一直转换,不需要手动开始转换

单次转换扫描模式

 在初始化的时候,需要给予通道数目,转换后需要多次读取数据防止覆盖结合DMC来使用产生EOC信号,,转换结束,下次手动开启。

连续转换扫描模式

7、触发控制

 

8、 数据对齐

 常用右对齐,左对齐左移得到的数据较大。

9、 转换时间

AD 转换的步骤:采样,保持,量化,编码
STM32 ADC 的总转换时间为:

             TCONV = 采样时间 + 12.5ADC周期

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

             TCONV = 1.5 + 12.5 = 14ADC周期 = 1μs

 10、校准

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

建议在每次上电后执行一次校准

启动校准前, ADC必须处于关电状态超过至少两个ADC时钟周期

11、ADC单通道采集

main
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "AD.h"


uint16_t ADValue;
float Voltage;
int main(void)
{
	OLED_Init();
	AD_Init();
	
	OLED_ShowString(0,0,"ADValue:");
	OLED_ShowString(0,3,"Volatge: .  V");
	
	while (1)
	{
		ADValue=AD_GetValue();
		Voltage=(float)ADValue/4095*3.3;
		OLED_ShowNum(60,0,ADValue,5,16);
		OLED_ShowNum(62,3,Voltage/1000,1,16);
		OLED_ShowNum(75,3,(uint16_t)(Voltage*100)%100,2,16);
		
	}
}

AD.C

#include "stm32f10x.h"                  // Device header


void AD_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//ADC是APB2上的设备
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);//ADCCLK六分频在RCC.H里面找680
	
	GPIO_InitTypeDef GPIO_Initstructure;
	GPIO_Initstructure.GPIO_Mode=GPIO_Mode_AIN;//ADC专属模式,在AIN模式下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);
	//规则组菜单第一个位置写入通道0,采样时间为55.5个ADCCLK的周期
	
	/************用结构体初始化ADC************/
	ADC_InitTypeDef ADC_InitStructure;
	ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;//连续转换模式:
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right ;//数据对齐:右对齐
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//外部触发控制的触发源:内部触发,软件触发
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent ;//工作模式:独立模式
	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_StartCalibration(ADC1);//开始校准
	while (ADC_GetCalibrationStatus(ADC1) == SET);//等待校准完成
}

uint16_t AD_GetValue(void)
{
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);//软件触发转换函数
	while (ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET);//获取EOC标志位状态:规则组转换完成标志位
	//大概等待5.6us,1/12M*(55.5+12.5)=5.6us
	return ADC_GetConversionValue(ADC1);
}

12、多通道

main

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "AD.h"
#include "LED.h"


uint16_t AD0,AD1;

int main(void)
{
	OLED_Init();
	AD_Init();
	LED_Init();
	OLED_ShowString(0,0,"AD0:");
	OLED_ShowString(0,3,"AD1:");
	
	while (1)
	{
		AD0=AD_GetValue(ADC_Channel_0);
		AD1=AD_GetValue(ADC_Channel_1);
		OLED_ShowNum(60,0,AD0,5,16);
		OLED_ShowNum(60,3,AD1,5,16);
		Delay_ms(100);
	}
}

AD

#include "stm32f10x.h"                  // Device header


void AD_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//ADC是APB2上的设备
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);//ADCCLK六分频在RCC.H里面找680
	
	GPIO_InitTypeDef GPIO_Initstructure;
	GPIO_Initstructure.GPIO_Mode=GPIO_Mode_AIN;//ADC专属模式,在AIN模式下GPIO口无效,防止干扰
	GPIO_Initstructure.GPIO_Pin=GPIO_Pin_0 | GPIO_Pin_1;
	GPIO_Initstructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_Initstructure);
	
	/************选择规则组输入通道***********/
	
	
	/************用结构体初始化ADC************/
	ADC_InitTypeDef ADC_InitStructure;
	ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;//连续转换模式:
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right ;//数据对齐:右对齐
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//外部触发控制的触发源:内部触发,软件触发
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent ;//工作模式:独立模式
	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_StartCalibration(ADC1);//开始校准
	while (ADC_GetCalibrationStatus(ADC1) == SET);//等待校准完成
}

uint16_t AD_GetValue(uint8_t ADC_Channel)
{
	ADC_RegularChannelConfig(ADC1,ADC_Channel,1, ADC_SampleTime_55Cycles5);
	//规则组菜单第一个位置写入通道0,采样时间为55.5个ADCCLK的周期
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);//软件触发转换函数
	while (ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET);//获取EOC标志位状态:规则组转换完成标志位
	//大概等待5.6us,1/12M*(55.5+12.5)=5.6us
	return ADC_GetConversionValue(ADC1);
}

实物

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值