STM32F4的ADC采集光敏传感器电压实验
前言
光敏电阻和ADC采集电压引脚如下:
光照越强,LS1导通程度越高,ADC采集电压越接近于0,光照越弱,采集电压则接近3.3V。
一.ADC简介
1.实验原理
本次实验选用12位ADC采集电压,12位采用逐次逼近的思想,将采集到的电压与内部DAC输出的模拟电压进行比较,多次比较由DAC得出ADC输入电压值的数字量,所以称为逐次逼近。
2.ADC内部结构
STM32系列一共有18个输入通道,16个外部GPIO输入源和2个内部源
各通道对应如下
规则组最多16个输入但仅有一个数据寄存器,所以处理多个通道时要及时用DMA将数据转移
ADC转换需要触发控制:软件/硬件触发,硬件触发包括定时器和外部中断
RCC提供采样时钟频率,ADC123均位于APB2总线(查阅参考手册总线架构)
转换完成会产生标志位,可根据标志位选择产生中断读取还是直接读取,读取完数据之后标志位会自动清零(参考手册ADC标志寄存器)
开关控制即ADC_cmd()函数,用于给ADC上电,注意如果要软件触发ADC,把触发函数放在ADC上电函数之后。
对于规则组,有单次/连续转换,非/扫描模式,两两组合四种工作模式
二.代码实现
此次连接光敏元件的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); } }
三.实验结果
挡住光敏元件光源,数值明显变大,采集电压增大
手电筒照射,数值明显变小,采集电压减小
代码没有问题。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~