1)数据下载:点击数据下载
2)正点原子Linux感兴趣的学生可以加入小组讨论:935446741
3)关注正点原子微信官方账号,获取最新信息更新

本章将向您介绍探索者 STM32F4 本章仍需使用开发板自带的光敏传感器
到 ADC 采集,通过 ADC 收集电压,获得光敏传感器的电阻变化,从而获得环境光的变化
化,并在 TFTLCD 上图显示。本章将分为以下几部分:
25.1 介绍光敏传感器
25.2 硬件设计
25.3 软件设计
25.4 下载验证
25.1 介绍光敏传感器
光敏传感器是最常见的传感器之一,主要有:光电管、光电倍增管、光电倍增管
敏感电阻、光敏三极管、太阳能电池、红外传感器、紫外传感器、光纤光电传感器
彩传感器、CCD 和 CMOS 图像传感器等。光传感器是目前产量最大、应用最广泛的传感器之一
一是在自动控制和非电量电测技术中发挥着非常重要的作用。
光敏传感器是一种利用光敏元件将光信号转换为电信号的传感器在可见光波中的敏感波长
长度附近,包括红外波长和紫外波长。光传感器不仅限于光的探测,还可以作为探测
测量元件形成其他传感器,只要将这些非电量转换为光信号,就可以检测到许多非电量
可。
探索者 STM32F4 作为光敏传感器,开发板载有光敏二极管(光敏电阻)
光的变化非常敏感。光敏二极管又称光电二极管。光敏二极管和半导体二极管在结构上是类别
其管芯具有光敏特性 PN 结具有单向导电性,因此工作时需要增加反向电压。
无光照时,饱和反向泄漏电流很小,即暗电流,此时光敏二极管截止。当光线充足时,
随着射光强度的变化,反向泄漏电流大大增加,形成光电流。当光线照射时 PN 结时,
可以使 PN 结中产生电子空穴对,增加了少数载流子的密度。这些载流子在反向电压下漂浮
移动,增加反向电流。因此,可以利用光的强度来改变电路中的电流。
利用这种电流变化,我们串联一个电阻,将其转换为电压变化 ADC 读
取电压值,判断外光的强度。
本章,我们用 ADC3 的通道 5(PF7)读取光敏二极管电压的变化,以获得环境
光的变化和光的强度显示在 TFTLCD 上面。关于 ADC 前两章已经介绍了
经过详细介绍,这里就不细说了。
25.2 硬件设计
本实验使用的硬件资源包括:
1) 指示灯 DS0
2) TFTLCD 模块
3) ADC
4) 光敏传感器
前三个之前都有介绍,光敏传感器和 STM32F4 的连接如图 25.2.1 所示:
图中,LS1 光敏二极管(实物在开发板摄像头接口右侧),R58 提供反向电压,
当环境光变化时,LS1 通过这种方式,两端的电压也会发生变化 ADC3_IN5 通道,读取
LIGHT_SENSOR(PF7)上述电压可获得环境光的强度。光线越强,电压越低,光线越低
线越暗,电压越高。
25.3 软件设计
打开本章可以看到实验工程。 HAL 在图书馆文件中,我们一个实验是一样的,添加
了 adc 库函数相关文件 stm32f4xx_hal_adc.c 支持相应的头文件。同时,我们在
HARDWARE 分组下新建了 adc3.c 和 lsens.c 源文件和包含相应的头文件。
我们主要使用这个实验 ADC3 测量关敏二极管的电压变化,所以我们的大部分知识都在前面
ADC 实验部分已经解释过了,这里我们稍微过去了。 lsens.c,代码如下:
////
void Lsens_Init(void)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOF_CLK_ENABLE();
//开启 GPIOF 时钟
GPIO_Initure.Pin=GPIO_PIN_7;
//PF7
GPIO_Initure.Mode=GPIO_MODE_ANALOG; //模拟
GPIO_Initure.Pull=GPIO_NOPULL;
//不带上下拉
HAL_GPIO_Init(GPIOF,&GPIO_Initure);
Adc3_Init();//初始化 ADC3
}
//读取 Light Sens 的值
//0~100:0,最暗;100,最亮
u8 Lsens_Get_Val(void)
{
u32 temp_val=0;
u8 t;
for(t=0;t<LSENS_READ_TIMES;t )
{
temp_val =Get_Adc3(ADC_CHANNEL_5);
//读取 ADC 值,通道 5
delay_ms(5);
}
temp_val/=LSENS_READ_TIMES;//得到平均值
if(temp_val>4000)temp_val=4000;
return (u8)(100-(temp_val/40));
}
这里就 2 其中:Lsens_Init 用于初始化光敏传感器实际上是初始化 PF7 为模
拟输入,然后通过 Adc3_Init 函数初始化 ADC3 的通道 ADC_Channel_5。Lsens_Get_Val 函
该函数用于获得当前的光强度 Get_Adc3 得到通道 ADC_Channel_5 转换电压值,
简单量化后,处理成 0~100 的光强值。0 对应最暗,100 对应最亮。
接下来我们来看看 adc3.c 源文件代码:
ADC_HandleTypeDef ADC3_Handler;//ADC 句柄
//初始化 ADC
//ch: ADC_channels
//通道值 0~16 值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16
void Adc3_Init(void)
{
ADC3_Handler.Instance=ADC3;
ADC3_Handler.Init.ClockPrescaler=ADC_CLOCK_SYNC_PCLK_DIV4;
//4 分频,ADCCLK=PCLK2/4=84/4=21MHZ
ADC3_Handler.Init.Resolution=ADC_RESOLUTION_12B;
//12 位模式
ADC3_Handler.Init.DataAlign=ADC_DATAALIGN_RIGHT; //右对齐
ADC3_Handler.Init.ScanConvMode=DISABLE;
//非扫描模式
ADC3_Handler.Init.EOCSelection=DISABLE;
//关闭 EOC 中断
ADC3_Handler.Init.ContinuousConvMode=DISABLE;
//关闭连续转换
ADC3_Handler.Init.NbrOfConversion=1;
//1 在规则序列中转换个 也就是说,只转换规则序列 1
ADC3_Handler.Init.DiscontinuousConvMode=DISABLE; //禁止不连续采样模式
ADC3_Handler.Init.NbrOfDiscConversion=0; ///不连续采样通道 0
ADC3_Handler.Init.ExternalTrigConv=ADC_SOFTWARE_START; ///软件触发
ADC3_Handler.Init.ExternalTrigConvEdge=
ADC_EXTERNALTRIGCONVEDGE_NONE;//使用软件触发
ADC3_Handler.Init.DMAContinuousRequests=DISABLE; //关闭 DMA 请求
p> HAL_ADC_Init(&ADC3_Handler); //初始化}
//ADC 底层驱动,引脚配置,时钟使能
//此函数会被 HAL_ADC_Init()调用
//hadc:ADC 句柄
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
__HAL_RCC_ADC3_CLK_ENABLE(); //使能 ADC3 时钟
}
//获得 ADC 值
//ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16
//返回值:转换结果
u16 Get_Adc3(u32 ch)
{
ADC_ChannelConfTypeDef ADC1_ChanConf;
ADC1_ChanConf.Channel=ch; //通道
ADC1_ChanConf.Rank=1; //1 个序列
ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_480CYCLES; //采样时间
ADC1_ChanConf.Offset=0;
HAL_ADC_ConfigChannel(&ADC3_Handler,&ADC1_ChanConf); //通道配置
HAL_ADC_Start(&ADC3_Handler); //开启 ADC
HAL_ADC_PollForConversion(&ADC3_Handler,10); //轮询转换
return (u16)HAL_ADC_GetValue(&ADC3_Handler);
//返回最近一次 ADC1 规则组的转换结果
}
这里,Adc3_Init 函数几乎和 ADC_Init 函数一模一样,这里我们设置了 ADC3_CH5 的
相关参数,但是没有设置对应 IO为模拟输入,因为这个在Lsens_Init函数已经实现。Get_Adc3
用于获取 ADC3 某个通道的转换结果。
因为我们前面对 ADC 有了详细的讲解,所以本章实验源码部分讲解就比较简单。接下
来我们看看主函数:
int main(void)
{
u8 adcx;
HAL_Init(); //初始化 HAL 库
Stm32_Clock_Init(336,8,2,7); //设置时钟,168Mhz
delay_init(168); //初始化延时函数
uart_init(115200); //初始化 USART
usmart_dev.init(84);
//初始化 USMART
LED_Init();
//初始化 LED
KEY_Init();
//初始化 KEY
LCD_Init();
//初始化 LCD
Lsens_Init();
//初始化光敏传感器
POINT_COLOR=RED;
LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");
LCD_ShowString(30,70,200,16,16,"LSENS TEST");
LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
LCD_ShowString(30,110,200,16,16,"2014/5/7");
POINT_COLOR=BLUE;//设置字体为蓝色
LCD_ShowString(30,130,200,16,16,"LSENS_VAL:");
while(1)
{
adcx=Lsens_Get_Val();
LCD_ShowxNum(30+10*8,130,adcx,3,16,0);//显示 ADC 的值
LED0=!LED0;
delay_ms(250);
}
}
此部分代码也比较简单,初始化各个外设之后,进入死循环,通过 Lsens_Get_Val 获取
光敏传感器得到的光强值(0~100),并显示在 TFTLCD 上面。
代码设计部分就为大家讲解到这里,下面我们开始下载验证。
25.4 下载验证
在代码编译成功之后,我们通过下载代码到 ALIENTEK 探索者 STM32F4 开发板上,
可以看到 LCD 显示如图 25.4.1 所示:
伴随 DS0 的不停闪烁,提示程序在运行。此时,我们可以通过给 LS1 不同的光照强度,
来观察 LSENS_VAL 值的变化,光照越强,该值越大,光照越弱,该值越小。