ADC数模转换器

一、ADC(Analog-Digital Converter)模拟-数字转换器

1、ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路数字电路的桥梁

2、12位逐次逼近型ADC,1us转换时间

3、输入电压范围:0~3.3V,转换结果范围:0~4095

4、18个输入通道,可测量16个外部2个内部信号源

5、规则组注入组两个转换单元

6、模拟看门狗自动监测输入电压范围

7、STM32F103C8T6 ADC资源:ADC1、ADC2,10个外部输入通道

8、逐次逼近型ADC

9、ADC框图

10、ADC基本结构

11、转换模式

        (1)单次转换,非扫描模式

        (2)连续转换,非扫描模式

        (3)单次转换,扫描模式

        (4)连续转换,扫描模式

12、数据对齐

13、转换时间

(1)AD转换的步骤:采样,保持,量化,编码

(2)STM32 ADC的总转换时间为:     

                TCONV = 采样时间 + 12.5个ADC周期

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

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

14、校准

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

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

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

15、硬件电路

二、AD单通道

1、按照以下接线方式连接,并将STLINK插到电脑上

2、AD转换函数驱动模块

(1)ADCCLK的配置函数(在RCC中)

(2)ADC相关库函数功能

(3)AD.c

#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);						//配置ADCCLK 72MHz/6=12MHz
	
	GPIO_InitTypeDef GPIO_InitStructure;					//配置GPIO
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;//模拟输入,在AIN模式下,GPIO口是无效的,断开GPIO,防止GPIO口的输入输出对模拟电压造成干扰,AIN模式就是ADC的专属模式
	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 转换周期:固定为12.5  一共68个周期	//选择规则组的输入通道
	
	ADC_InitTypeDef ADC_InitStructure;											//结构体初始化ADC
	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_Cmd(ADC1,ENABLE);														//开启AC电源
	
	ADC_ResetCalibration(ADC1);							//复位校准				//ADC校准
	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);	//等待时间:1/12MHz*(55.5+12.5)=5.6us
	return ADC_GetConversionValue(ADC1);//读取后自动清除标志位
}

(4)AD.h

#ifndef __AD_H
#define __AD_H

void AD_Init(void);
uint16_t AD_GetValue(void);

#endif

3、编写main.c代码

#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(1,1,"ADValue:");
	OLED_ShowString(2,1,"Voltage:0.00V");

	while(1)
	{
		ADValue = AD_GetValue();
		Voltage = (float)ADValue/4095*3.3;	//AD值转换成电压
		
		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);
	}
}

4、实现效果

AD单通道

5、单通道连续转换、非扫描模式

修改AD.c

三、AD多通道

1、按照以下接线方式连接,并将STLINK插到电脑上

2、AD转换函数驱动模块

(1)AD.c

#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);						//配置ADCCLK 72MHz/6=12MHz
	
	GPIO_InitTypeDef GPIO_InitStructure;					//配置GPIO
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;//模拟输入,在AIN模式下,GPIO口是无效的,断开GPIO,防止GPIO口的输入输出对模拟电压造成干扰,AIN模式就是ADC的专属模式
	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
	ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;//连续转换模式
//	ADC_InitStructure.ADC_ContinuousConvMode=ENABLE;//连续转换模式
	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_Cmd(ADC1,ENABLE);														//开启AC电源
	
	ADC_ResetCalibration(ADC1);							//复位校准				//ADC校准
	while(ADC_GetResetCalibrationStatus(ADC1) == SET);	//返回复位校准的状态
	ADC_StartCalibration(ADC1);							//开始校准
	while(ADC_GetCalibrationStatus(ADC1) == SET);		//获取校准状态	

//	ADC_SoftwareStartConvCmd(ADC1,ENABLE);		//软件触发

}

uint16_t AD_GetValue(uint8_t ADC_Channel)
{
	ADC_RegularChannelConfig(ADC1,ADC_Channel,1,ADC_SampleTime_55Cycles5);	//采用周期:55.5 转换周期:固定为12.5  一共68个周期	//选择规则组的输入通道

	ADC_SoftwareStartConvCmd(ADC1,ENABLE);
	while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET);	//等待时间:1/12MHz*(55.5+12.5)=5.6us
	return ADC_GetConversionValue(ADC1);//读取后自动清除标志位
}

(2)AD.h

#ifndef __AD_H
#define __AD_H

void AD_Init(void);
uint16_t AD_GetValue(uint8_t ADC_Channel);

#endif

3、编写main.c代码

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

uint16_t AD0,AD1,AD2,AD3;

int main(void)
{
	OLED_Init();
	AD_Init();
	
	OLED_ShowString(1,1,"AD0:");
	OLED_ShowString(2,1,"AD1:");
	OLED_ShowString(3,1,"AD2:");
	OLED_ShowString(4,1,"AD3:");

	while(1)
	{
		AD0 = AD_GetValue(ADC_Channel_0);
		AD1 = AD_GetValue(ADC_Channel_1);
		AD2 = AD_GetValue(ADC_Channel_2);
		AD3 = AD_GetValue(ADC_Channel_3);
		
		OLED_ShowNum(1,5,AD0,4);
		OLED_ShowNum(2,5,AD1,4);
		OLED_ShowNum(3,5,AD2,4);
		OLED_ShowNum(4,5,AD3,4);
		
		Delay_ms(100);
	}
}

4、实现效果

AD多通道

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值