蓝桥杯嵌入式(七)ADC配置

STM32的ADC是12位逐次逼近型的模拟数字转换器,它有18个通道,可测量16个外部和2个内部信号源。

在蓝桥杯嵌入式比赛中,ADC基本都是用来采集电位器的电压。在开发板上,LED旁有一个蓝白色的电位器,用来作为可调电压输入。首先,我们来看看原理图上的连接:

蓝桥杯嵌入式(七)ADC配置_第1张图片

 

可以看到,电位器连接在PB0引脚上,查阅stm32f103rbt6的数据手册,PB0可复用为ADC_IN8(ADC1的通道8)

在进行ADC配置前,我们需要从固件库添加一个文件,添加方法在串口配置中:

蓝桥杯嵌入式(七)ADC配置_第2张图片

接下来,我们进行ADC的配置,代码如下:

void Adc_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	ADC_InitTypeDef  ADC_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1|RCC_APB2Periph_GPIOB, ENABLE);
	
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);//设置ADC分频因子6
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//模拟输入
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//ADC独立模式
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;//单通道模式
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//单次转换模式
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//转换由软件而不是外部触发启动
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//ADC数据右对齐
	ADC_InitStructure.ADC_NbrOfChannel = 1;//顺序进行规则转换的ADC通道的数目
	ADC_Init(ADC1, &ADC_InitStructure);
	
	ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_239Cycles5);//ADC通道配置
	
	ADC_Cmd(ADC1, ENABLE);//使能ADC1

	ADC_ResetCalibration(ADC1);//开启复位校准
	while(ADC_GetResetCalibrationStatus(ADC1));//等待复位校准结束

	ADC_StartCalibration(ADC1);//开启AD校准
	while(ADC_GetCalibrationStatus(ADC1));//等待校准结束
}

1.开启PB口和ADC1时钟,设置PB0为模拟输入。

2.设置ADC1分频因子:分频因子要确保ADC1的时钟不要超过14Mhz,我们设置分频因子为6,时钟为72/6=12Mhz

3.初始化ADC1参数:通过函数ADC_Init()实现

4.ADC1通道配置:函数ADC_RegularChannelConfig()用来设置规则序列通道以及采样周期。

5.使能ADC并校准:使能ADC1后,先执行复位校准,再AD校准,这两步是必须的,否则结果不准确。

配置好ADC后,我们还需要编写一个函数来读取ADC的值:

float Adc_Get(void)
{
	float Adc_Value;
	
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能ADC1的软件转换启动功能
	while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==0);//等待转换结束
	Adc_Value=ADC_GetConversionValue(ADC1)*3.30/4096;
	
	return Adc_Value;
}

使用函数ADC_SoftwareStartConvCmd()启动AD转换,接下来要等待转换结束,通过EOC标志位来判断转换是否结束。EOC标志位在ADC状态寄存器中(STM32_CN 170页

转换结束之后,我们就可以读取ADC的值了,通过函数ADC_GetConversionValue()来实现,stm32f103rbt6的ADC精度为12位(0~4096),所以我们需要把它转化为真正的电压值。

主函数代码:

#include "stm32f10x.h"
#include "lcd.h"
#include "io.h"
#include "stdio.h"

u32 TimingDelay = 0;
void Delay_Ms(u32 nTime);

u8 Adc_Flag=0;
float adc;
char str[20];

//Main Body
int main(void)
{
	SysTick_Config(SystemCoreClock/1000);
	Adc_Init();
	STM3210B_LCD_Init();
	LCD_Clear(Blue);
	LCD_SetBackColor(Blue);
	LCD_SetTextColor(White);
	while(1)
	{
		if(Adc_Flag)
		{
			Adc_Flag=0;
			adc=Adc_Get();
			sprintf((char*)str,"ADC_VALUE:%.2fV   ",adc);
			LCD_DisplayStringLine(Line1,str);
		}
	}
}

//
void Delay_Ms(u32 nTime)
{
	TimingDelay = nTime;
	while(TimingDelay != 0);	
}

在嘀嗒定时器中,设置每200ms读取一次ADC的值

extern u8 Adc_Flag; 
void SysTick_Handler(void)
{
	static u16 ms1=0;
	TimingDelay--;
	
	if(++ms1==200)	//ADC采集
	{
		ms1=0;
		Adc_Flag=1;
	}
}

这样ADC的采样程序就完成了。

你可能感兴趣的:(蓝桥杯嵌入式)