目录
1. 什么是光敏传感器、光敏电阻
2. 硬件分析
3. 实验程序
3.1 main.c
3.2 ADC3.c
3.3 ADC3.h
3.4 Lightsensor.c
3.5 Lightsensor.h
1. 什么是光敏传感器、光敏电阻
光敏传感器也称为光电传感器。是利用光电器件把光信号转换成电信号的一种传感器。它的敏感波长在可见光波长附近,包括红外线波长和紫外线波长。光传感器不只局限于对光的探测,它还可以作为探测元件组成其他传感器,对许多非电量进行检测,只要将这些非电量转换为光信号的变化即可。
光敏传感器是最常见的传感器之一,它的种类繁多,主要有:光电管、光电倍增管、光敏电阻、光敏三极管、太阳能电池、红外线传感器、紫外线传感器、CCD和CMOS图像传感器等。光传感器是目前产量最多、应用最广的传感器之一,它在自动控制和非电量电测技术中占有非常重要的地位。
光敏电阻是一种由半导体材料制成的没有极性的纯电阻,光敏电阻是一种对光敏感的光电器件。
光敏电阻的主要参数:
- 暗电阻和暗电流:通常把光敏电阻未受到光照射时的电阻称作暗电阻,在没有光照射时流过的电流称作暗电流。
- 亮电阻和亮电流:亮对应于暗,通常将光敏电阻在受到光照射时的电阻称作亮电阻,在有光照射时通过的电流称作亮电流。
光敏电阻的主要特性:
- 伏安特性:在一定的光照强度下,光敏电阻两端所加的电压与电流成正比,阻值只和照射的入光强度有关,与加在两端的电流或者电压无关。
- 光谱特性:我们只要光存在不同的波长,则不同波长的光对光敏电阻的灵敏度是不一样的。
- 温度特性:光敏电阻受温度的影响较大,当温度升高时,暗电阻和灵敏度都随之下降。
工作原理:
光敏电阻串联在电流中,在光敏电阻的两端,通常加上合适的电压,在没有光照的条件下,光敏电阻的阻值接近于无穷大,相当于断路,当在一定的光照强度下, 光敏电阻的阻值减少,电流对应增大,足够的光照强度使得光敏电阻所在的支路相当于短路。
实际应用:
通过STM32F4的ADC去测量电压值
- 首先需要确定ADC的位数,也可以说是分辨率,最大数值是多少。比如说一个16位的ADC,最大值就是0xFFFF,对应于=65536;
- 确定最大值时对应的参考电压值,STM32F4的开发板对应的最大值为3.3V。
- 计算电压值,需要把ADC的数值除刚才的确定的最大数值(也就是)再乘以参考电压值,
比如说是ADC*(3.3/65536)
2. 硬件分析
STM32F4板载了一个光敏二极管(光敏电阻),作为开发板的光敏传感器,它对光的变化非常敏感。光敏二极管也叫作光电二极管。光敏二极管和半导体二极管类似,其管芯是一个具有光敏特性的PN结,PN结具有单向导电性,因此工作时需要加反向电压。无光照条件时,有很小的饱和反向漏电流,也就是上面提到的暗电流,此时光敏二极管截止。当受到光照时,饱和反向漏电流大大增加,形成光电流,此时这个值随着入射光的光照强度变化而变化。当光线照射PN结时,可以在PN结中产生电子---空穴对,使得少数的载流子的密度增加。这些载流子在反向电压下产生漂移,使得反向电流增加。因此可以利用光照强度来改变电路中的电流。
利用PN结中电流的变化,串联一个电阻,就可以转换成电压的变化,通过ADC读取电压值。
图中,LSI 就是光敏二极管,R58为其提供反向电压,当环境光线变化时,LSI 两端的电压也会随之变化,通过ADC3_IN5通道,读取LIGHT_SENSOR上面的电压;光线越强,电压越低,光线越暗,电压越高。
3. 实验程序
本实验利用ADC3的通道5(PF7)来读取光敏二极管的电压变化。
光敏二极管位于开发板的左下角,如上图PCB图所示;可以用强光照射该处,观察光敏电阻的变化;
3.1 main.c
#include "stm32f4xx.h"
#include "delay.h"
#include "usart.h"
#include "LED.h"
#include "lcd.h"
#include "usmart.h"
#include "ADC3.h"
#include "Lightsensor.h"
//LCD状态设置函数
void led_set(u8 sta)//只要工程目录下有usmart调试函数,主函数就必须调用这两个函数
{
LED1=sta;
}
//函数参数调用测试函数
void test_fun(void(*ledset)(u8),u8 sta)
{
led_set(sta);
}
int main(void)
{
u8 adcx;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
delay_init(168);
uart_init(115200);
LED_Init();
LCD_Init();
LightSensor_Init();
POINT_COLOR=RED;
LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");
LCD_ShowString(30,70,200,16,16,"Lightsensor Test");
LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
LCD_ShowString(30,110,200,16,16,"2023/20/23");
POINT_COLOR=BLUE;
LCD_ShowString(30,130,200,16,16,"Lightsensor:");
while(1)
{
adcx=LightSensor_Get_Val();
LCD_ShowxNum(30+12*8,130,adcx,3,16,0);
LED0=!LED0;
delay_ms(250);
}
}
3.2 ADC3.c
#include "stm32f4xx.h"
#include "ADC3.h"
void Adc3_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3,ENABLE); //使能ADC3时钟
RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3,ENABLE); //ADC3复位
RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3,DISABLE); //复位结束
//初始化CCR寄存器
ADC_CommonInitTypeDef ADC_CommonInitStructure;
ADC_CommonInitStructure.ADC_DMAAccessMode=ADC_DMAAccessMode_Disabled; //DMA不使能,DMA通常用于多通道的转移
ADC_CommonInitStructure.ADC_Mode=ADC_Mode_Independent; //独立模式
ADC_CommonInitStructure.ADC_Prescaler=ADC_Prescaler_Div4; //预分频4分频
ADC_CommonInitStructure.ADC_TwoSamplingDelay=ADC_TwoSamplingDelay_5Cycles; //两个采样阶段之间延迟5个时钟
ADC_CommonInit(&ADC_CommonInitStructure);
//初始化ADC
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_ContinuousConvMode=DISABLE; //关闭连续转换
ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right; //右对齐
ADC_InitStructure.ADC_ExternalTrigConvEdge=ADC_ExternalTrigConvEdge_None;//禁止触发检测,使用软件触发
ADC_InitStructure.ADC_NbrOfConversion=1; //1个转换在规则序列中
ADC_InitStructure.ADC_Resolution=ADC_Resolution_12b; //12位模式分辨率
ADC_InitStructure.ADC_ScanConvMode=DISABLE; //非扫描模式
ADC_Init(ADC3,&ADC_InitStructure);
ADC_Cmd(ADC3,ENABLE); //开启AD转换器
}
//获得ADC的值
//ch:通道值0~16 ADC_Channel_0~ADC_Channel_16
//返回值:转换的结果
u16 Get_Adc3(u8 ch)
{
ADC_RegularChannelConfig(ADC3,ch,1,ADC_SampleTime_480Cycles); //设置ADC规则组通道,1个序列 采样时间
ADC_SoftwareStartConv(ADC3);//使能指定的ADC3的软件转换启动功能
while(!ADC_GetFlagStatus(ADC3,ADC_FLAG_EOC));//等待状态寄存器转换标志位结束
return ADC_GetConversionValue(ADC3); //返回转换的结果
}
3.3 ADC3.h
#ifndef _ADC3__H_
#define _ADC3__H_
u16 Get_Adc3(u8 ch);
void Adc3_Init(void);
#endif
3.4 Lightsensor.c
#include "stm32f4xx.h"
#include "Lightsensor.h"
#include "ADC3.h"
#include "delay.h"
void LightSensor_Init(void) //初始化光敏传感器
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE); //初始化GPIOF时钟
//初始化GPIOF PF7通道
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AN; //模式为模拟输入
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL; //不带上下拉
GPIO_Init(GPIOF,&GPIO_InitStructure);
Adc3_Init(); //初始化ADC3
}
//读取光敏电阻Light Sensor的值
//0~100 0最暗,100最亮
u8 LightSensor_Get_Val(void)
{
u32 temp_val=0;
u8 t;
for(t=0;t<LSENS_READ_TIMES;t++)
{
temp_val=Get_Adc3(ADC_Channel_5)+temp_val;// 取多次读取的总和加在一起
delay_ms(5);
}
temp_val=temp_val/LSENS_READ_TIMES; //得到平均值
if(temp_val>4000)
temp_val=4000;
return (u8)(100-(temp_val/40));
}
3.5 Lightsensor.h
#ifndef _LIGHTSENSOR__H_
#define _LIGHTSENSOR__H_
#define LSENS_READ_TIMES 10
u8 LightSensor_Get_Val(void);
void LightSensor_Init(void);
#endif