STM32F4的ADC采集光敏传感器电压实验

发布时间 2023-11-30 23:09:07作者: 京多安

前言

  
光敏电阻和ADC采集电压引脚如下:
image
光照越强,LS1导通程度越高,ADC采集电压越接近于0,光照越弱,采集电压则接近3.3V。

一.ADC简介

1.实验原理

  本次实验选用12位ADC采集电压,12位采用逐次逼近的思想,将采集到的电压与内部DAC输出的模拟电压进行比较,多次比较由DAC得出ADC输入电压值的数字量,所以称为逐次逼近。

2.ADC内部结构

image
STM32系列一共有18个输入通道,16个外部GPIO输入源和2个内部源
各通道对应如下
image

规则组最多16个输入但仅有一个数据寄存器,所以处理多个通道时要及时用DMA将数据转移
ADC转换需要触发控制:软件/硬件触发,硬件触发包括定时器和外部中断
RCC提供采样时钟频率,ADC123均位于APB2总线(查阅参考手册总线架构)
转换完成会产生标志位,可根据标志位选择产生中断读取还是直接读取,读取完数据之后标志位会自动清零(参考手册ADC标志寄存器)
开关控制即ADC_cmd()函数,用于给ADC上电,注意如果要软件触发ADC,把触发函数放在ADC上电函数之后。
对于规则组,有单次/连续转换,非/扫描模式,两两组合四种工作模式
image

image

image

image

二.代码实现

此次连接光敏元件的ADC引脚是PF7,采用的是ADC3的通道5
初始化函数如下,采用连续、非扫描模式:

void AD_Init(void)
{
	//初始化GPIO
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3,ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_7;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_Init(GPIOF,&GPIO_InitStructure);
	
	//ADC通用初始化结构体,
	//ADC_CommonInitTypeDef 结构体内容决定三个 ADC 共用的工作环境
	//比如模式选择、 ADC时钟等等。
	ADC_CommonInitTypeDef ADC_CommonInitStructure; 
	ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;//ADC工作模式选择,有独立模式、双重模式以及三重模式
	ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;//ADC时钟分频系数选择,ADC时钟是有 PCLK2 分频而来,分频系数决定ADC 时钟频率,可选的分频系数为 2、4、6 和 8。ADC最大时钟配置为 36MHz。
	ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;//DMA 模式设置,只有在双重或者三重模式才需要设置,可以设置三种模式
	ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;//2 个采样阶段之前的延迟,仅适用于双重或三重交错模式
	ADC_CommonInit(&ADC_CommonInitStructure);
	
	//ADC结构体参数设置
	ADC_InitTypeDef ADC_InitStructure;
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //连续转换
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//数据右对齐
	//ADC_InitStructure.ADC_ExternalTrigConv = ;//使用软件触发,外部触发不用配置,注释掉即可
	ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//禁止外部边沿触发
	ADC_InitStructure.ADC_NbrOfConversion = 1;//转换通道 1 个
	ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;// ADC 分辨率
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;// 禁止扫描模式,多通道采集才需要
	ADC_Init(ADC3,&ADC_InitStructure);
	
	ADC_RegularChannelConfig(ADC3,ADC_Channel_5, 1, ADC_SampleTime_480Cycles );//设置指定ADC 的规则组通道,一个序列,采样时间
	ADC_Cmd(ADC3,ENABLE);	//给ADC上电
	
	ADC_SoftwareStartConv(ADC3);//使能指定的ADC3 的软件触发,连续转换触发一次即可,注意要在ADC上电之后
}

再写一个读取函数

uint16_t AD_GetValue(void)
{	
	return ADC_GetConversionValue(ADC3); //返回ADC采集的值,数据寄存器数据被读取,EOC会自动清零
}	

主函数如下:

uint16_t ADValue;
int main(void)
{
	uart_init(115200);
	delay_init(84);
	AD_Init();
  while(1){
	  ADValue = AD_GetValue();
	  delay_ms(1000);
	  printf("Num = %d\r\n",ADValue);
	  delay_ms(1000);
	}
}

三.实验结果
挡住光敏元件光源,数值明显变大,采集电压增大
image
手电筒照射,数值明显变小,采集电压减小
image
代码没有问题。