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

前言

  
光敏电阻和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
代码没有问题。

posted @   京多安  阅读(1572)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示