STM32之ADC模数转换器单通道。

ADC模数转换器

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

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

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

分辨率含义:0 ~ 2^12,即0 ~ 4095 ,位数越高量化结果越精细,分辨率越高

STM32的ADC输入是0~3.3V,所以ADC是将0~3.3V线性映射成0~4095。

 逐次逼近型ADC图

STM32之ADC模数转换器单通道。_第1张图片

 VREF与VCC相连,输入电压模拟量范围由VREF决定。

可以单通道输入,也可以多通道接不通传感器输入。

输出是八位二进制数,因此是8位ADC。

STM32的ADC完整框图

STM32之ADC模数转换器单通道。_第2张图片

 image-20221211134242951

VREF与VDDA内部电源连接。

 image-20221211143348853

三、 规则组转换模式

1、单次转换,非扫描模式

2、连续转换,非扫描模式

3、单次转换,扫描模式

4、连续转换,扫描模式

单次转换:每次从开始触发(软件触发或者硬件触发)到数据写入规则组数据寄存器后置EOC标志位,转换结束。后面要再采集数据需要重新上述过程。

连续转换:每次从开始触发(软件触发或者硬件触发)到数据写入规则组数据寄存器后置EOC标志位,转换不结束,不需要再次触发,继续采集数据写入数据寄存器。

扫描模式:多通道采集数据,并在序列中指定好通道顺序,开始触发后,数据寄存器逐个写入指定序列中数据(会覆盖,因此采用这个模式需要配合DMA使用)序列中数据读完后置EOC标志位。

非扫描模式:单通道单序列就是非扫描模式,默认。

如图:

STM32之ADC模数转换器单通道。_第3张图片STM32之ADC模数转换器单通道。_第4张图片  STM32之ADC模数转换器单通道。_第5张图片STM32之ADC模数转换器单通道。_第6张图片

触发控制有硬件和软件两种触发:如图

image-20221211144655873

 数据对齐方式:

 因为STM32中ADC是12位的,而ADC的数据寄存器是16位的,因此有两种对齐方式。其中左对齐会损失精度,右对齐不会。左对齐降低精度,只读高八位,舍去后四位。

STM32之ADC模数转换器单通道。_第7张图片

六、转换时间

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

其中采样、保持放一起,量化、编码放一起。

STM32之ADC模数转换器单通道。_第8张图片

七、校准STM32之ADC模数转换器单通道。_第9张图片

代码部分

AD单通道

功能实现:用电位计产生0~3.3V的连续变化的模拟电压,在LCD显示转换后的数据和处理后得到的电压值

STM32之ADC模数转换器单通道。_第10张图片

 流程:

参考上面的框图,具体步骤如下:

第一步开启RCC时钟,包括ADC和GPIO的时钟,ADCCLK的分频器也要配置(给ADC配置时钟信号的用来计算采样的时间。72MHZ/ADCCLK);

第二步配置GPIO,把需要用的GPIO配置成模拟输入的模式;

第三步配置多路开关(黄颜色部分),把左边的通道接入到右边的规则组列表里;

第四步配置ADC转换器,库函数中用结构体来配置,包括单次转换还是连续转换、扫描还是非扫描、通道数量、触发源、数据对齐方式(左对齐or右对齐)。若需要模拟看门狗,会有几个函数配置阈值和检测通道。若想开启中断,就在中断输出控制里用ITConfig函数开启对应的中断输出,然后再在NVIC里,配置一下优先级,就可以触发中断了;

第五步调用ADC_Cmd函数,开启ADC。

注:开启ADC后,根据手册建议,可以对ADC进行校准,减小误差。在ADC工作时,如果想要软件触发转换,那会有函数可以触发;如果想读取转换结果,那也会有函数可以读取结果。
 

#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);  //提供时钟,72/6=12MHZ
	
	//GPIO配置
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_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);
	///选择规则组的输入通道.第三个参数为
	//要配置的ADC通道在转换序列中的排位。取值为1~16,表示该通道在转换序列中的第几个进行转换。
	//例如,若取值为2,则表示该通道在转换序列中排在第2位。
	
	//ADC模块配置
	ADC_InitTypeDef ADC_InitStructure;
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作在单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_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标志位
	return ADC_GetConversionValue(ADC1);//转换完成会自动清除标志位
}

 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, "Volatge:0.00V");
	
	while (1)
	{
		ADValue = AD_GetValue();
		Voltage = (float)ADValue / 4095 * 3.3;  //12位ADC
		
		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);
	}
}

你可能感兴趣的:(STM32,stm32,单片机,嵌入式硬件)