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

ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁(也可以相当于一个电压表)

 拓展:DAC是数字-模拟转换器,例如PWM驱动电机等,但适合大功率的,主要DAC是应用于信号发生器,音频解码芯片。

12位逐次逼近型ADC(量化结果是0~4095),1us转换时间(转换开始到产生结果,频率也就是1MHz)

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

18个输入通道,可测量16个外部(GPIO)和2个内部信号源(内部温度和电压)。

规则组和注入组两个转换单元

模拟看门狗自动监测输入电压范围(可以设置值,到达值后直接申请中断)。

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

这是比较经典款的ADC芯片内部结构图。

通道选择开关和地址锁存和译码相当于138译码器,比较器的作用是比较输入的数值,调节SAR的值给DAC,再进行对比,直到输入的值和DAC的一样。CLOCK是时钟,需要一定的频率进行对比,START是开始ADC。EOC是结束ADC开关。结束转换后DAC的值就传到缓冲器进行输出,VREF是对ADC的值进行对应电压转换

 

 

这里是STM32ADC的结构图

 也是通过16个GPIO口进入,模拟通路开关,指定哪个GPIO进入,但这里可以同时选择多个输入,进入规则通道和注入通道,规则通道进到规则寄存器时,寄存器只能读取一个,防止数据丢失可以使用MDA转运。注入通道进入注入寄存器可以存放4个数据。左下角的部分开始触发,也相当于START。其中转换模式分为单次转换非扫描模式(相当于只读取一个通道,转换完成后下次需要再次START开始触发转换)、连续转换非扫描模式(也是只读取一个通道,可以立刻开始转换,直到结束,下次再START)、单次转换扫描模式(读取多个通道就结束,下次就START)、连续转换扫描模式

 

 ADC通道和引脚复用,也可见引脚复用图,其中ADC12公用引脚,可提高采样效率

以下代码是用ADC读取传感器的数值转换为电压的例程

 AD.c

#include "stm32f10x.h"                  // Device header
void AD_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//开启ADC通道1时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//开启GPIOA时钟
	
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);//ADC时钟分频,72/6=14MHZ
	GPIO_InitTypeDef GPIO_InitStructure;
 	GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AIN;//ADC模拟专用模式
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
 	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_239Cycles5);//配置规则组的函数
	
	
	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模式,此时是单
	ADC_InitStructure.ADC_NbrOfChannel=1;          //通道数目,此时数目为1
	ADC_InitStructure.ADC_ScanConvMode=DISABLE;    //扫描或者非扫描,此时非扫描
	ADC_Init(ADC1,&ADC_InitStructure);
	
	ADC_Cmd(ADC1,ENABLE);//开启ADC开关
	
	ADC_ResetCalibration(ADC1);//复位校准,会把标志位置1,
	while(ADC_GetResetCalibrationStatus(ADC1)==SET);//等待返回复位校准的状态,复位校准完成后就会置0
	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的值,置1完成。在扫描模式下,不需要每次等待读取
	return ADC_GetConversionValue(ADC1);//读取ADC获取的转换值,也自动清除获取的值
	
}


AD.h

#ifndef __AD_H
#define __AD_H

void AD_Init(void);
uint16_t AD_GetValue(void);
#endif

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;
		
		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);
	}
}

本文是跟着江科大学习的,是本人的学习笔记,如有侵权请联系本人删除!!

更多推荐