光控感應(yīng)器
文章目錄
一、硬件設(shè)計
1.本實(shí)驗(yàn)所用到的硬件資源
2.原理圖
3.工作原理
二、軟件設(shè)計
1.主函數(shù)mian.c
2.ADC.c
3.ADC.h
驗(yàn)證
一、硬件設(shè)計
1.本實(shí)驗(yàn)所用到的硬件資源
1:一塊stm32開發(fā)板
2:一個光敏電阻
3:手電筒
2.原理圖
LS1表示光敏電阻,PF8具有ADC3_IN6的功能。如果自己的開發(fā)板沒有PF8引腳的可以選擇一個具有ADC功能的引腳來替換,對實(shí)驗(yàn)結(jié)果不會有影響。
3.工作原理
光敏電阻特性:光照強(qiáng)度越強(qiáng),電阻就越小,光照強(qiáng)度越弱,電阻就越大。
通過ADC采集光敏電阻的電壓:如果采集到的電壓越大,就說明此時的電阻就越大,從而說明光照強(qiáng)度越弱。
我們就可以通過判斷ADC轉(zhuǎn)換的值來判斷此時外界的光照強(qiáng)度。在判斷之后就可以做出相應(yīng)的命令,例如LED的亮滅,蜂鳴器發(fā)聲與不發(fā)聲,等等其他的功能。
二、軟件設(shè)計
1.主函數(shù)mian.c
代碼如下(示例):
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "adc.h"
#include "led.h"
int main(void)
{
u8 adcx;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中斷優(yōu)先級分組,給串口使用的
delay_init();//延時初始化
LED_Init();//led(PB5)初始化
uart_init(115200);//串口初始化
ADC3_CH6_Init();//ADC3_CH6初始化
while(1)
{
adcx=Lsens_Get_Val();
printf("光照強(qiáng)度為=%d\r\n",adcx);
delay_ms(500);
if(adcx<5)
{
GPIO_ResetBits(GPIOB,GPIO_Pin_5); //PB.5 輸出低
}
else
{
GPIO_SetBits(GPIOB,GPIO_Pin_5); //PB.5 輸出高
}
}
}
2.ADC.c
代碼如下(示例):
#include "sys.h"
#include "adc.h"
#include "delay.h"
#include "stdio.h"
void ADC3_CH6_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF | RCC_APB2Periph_ADC3, ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AIN;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_8;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init( GPIOF, &GPIO_InitStruct);//管腳初始化
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//把時鐘分頻為12MHz,ADC的時鐘不能超過14M,超過的話可能不準(zhǔn)。
ADC_DeInit(ADC3);
ADC_InitTypeDef ADC_InitStruct;
ADC_InitStruct.ADC_ContinuousConvMode=DISABLE;//指定是否是連續(xù)轉(zhuǎn)換還是單個轉(zhuǎn)換。也就是連續(xù)采集還是單次采集。我這里不管配置什么都是一直在采集
ADC_InitStruct.ADC_DataAlign=ADC_DataAlign_Left;//數(shù)據(jù)向右對齊
ADC_InitStruct.ADC_Mode=ADC_Mode_Independent;//單通道的獨(dú)立模式
ADC_InitStruct.ADC_NbrOfChannel=1;//順序進(jìn)行規(guī)則轉(zhuǎn)換的ADC通道的數(shù)目
ADC_InitStruct.ADC_ScanConvMode=DISABLE;//模數(shù)轉(zhuǎn)換工作在單通道模式
ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //轉(zhuǎn)換由軟件而不是外部觸發(fā)啟動
ADC_Init( ADC3, & ADC_InitStruct);//ADC模式初始化
ADC_Cmd( ADC3, ENABLE);//ADC使能
ADC_ResetCalibration(ADC3);//復(fù)位校準(zhǔn)使能
while(ADC_GetResetCalibrationStatus(ADC3));//等待復(fù)位校準(zhǔn)完成
ADC_StartCalibration(ADC3);//開啟AD校準(zhǔn)
while(ADC_GetCalibrationStatus(ADC3));//等待AD校準(zhǔn)完成
}
u16 Get_AdcValue(u8 ch)
{
ADC_RegularChannelConfig(ADC3, ch, 1, ADC_SampleTime_239Cycles5);
//ADC1,通道1,
ADC_SoftwareStartConvCmd(ADC3, ENABLE);//ADC1的軟件轉(zhuǎn)換啟動使能
while(ADC_GetFlagStatus( ADC3, ADC_FLAG_EOC)==RESET);//等待轉(zhuǎn)換結(jié)束
return ADC_GetConversionValue(ADC3);//返回轉(zhuǎn)換值
}
//讀取Light Sens的值
u8 Lsens_Get_Val(void)
{
u32 temp_val=0;
u8 result;
u8 t;
for(t=0;t<10;t++)
{
temp_val+=Get_AdcValue(ADC_Channel_6); //讀取ADC值
delay_ms(5);
}
temp_val/=10;//得到平均值
if(temp_val>3000)temp_val=3000;//電壓最大值為3.3v,3.3v對應(yīng)的ADC轉(zhuǎn)換數(shù)據(jù)為4096。所以讀到的數(shù)據(jù)不會超過4096
// 光照最強(qiáng)的時候,電阻最小,電壓也最小,ADC轉(zhuǎn)換出來的數(shù)據(jù)也最小
// 光照最弱的時候,電阻最大,電壓也最大,ADC轉(zhuǎn)換出來的數(shù)據(jù)也最大
//我希望把光照等級分成10份,光照最強(qiáng)的時候?yàn)?0,最弱的時候?yàn)?。在正常狀態(tài)數(shù)據(jù)為(0-4),打開手電筒數(shù)據(jù)為(5-10)。
result=10-(temp_val/300);
return result;
}
3.ADC.h
代碼如下(示例):
#ifndef __ADC_H
#define __ADC_H
#include "sys.h"
void ADC3_CH6_Init(void);
u16 Get_AdcValue(u8 ch);
u16 Get_Adc_Average(u8 ch,u8 times);
u8 Lsens_Get_Val(void);
#endif
驗(yàn)證
當(dāng)我關(guān)閉手電筒的時候,串口打印出來的數(shù)據(jù)小于5,此時LED變亮。
當(dāng)我用手電筒照著光敏電阻時,串口打印出來的數(shù)據(jù)大于等于5,此時LED變暗。
說明此時模擬樓道光控開關(guān)試驗(yàn)成功。