基于stm32的模拟楼道光控开关的实验

实验目的:本文基于stm32开发板做一个模拟光控开关的实验,实验最后的实现的功能是,在光照强度大于临界值LED灯就变暗,如果光照强度小于临界值LED灯就变亮。

一、硬件设计

1.本实验所用到的硬件资源

1:一块stm32开发板
2:一个光敏电阻
3:手电筒

2.原理图

在这里插入图片描述

LS1表示光敏电阻,PF8具有ADC3_IN6的功能。如果自己的开发板没有PF8引脚的可以选择一个具有ADC功能的引脚来替换,对实验结果不会有影响。

3.工作原理

光敏电阻特性:光照强度越强,电阻就越小,光照强度越弱,电阻就越大。
通过ADC采集光敏电阻的电压:如果采集到的电压越大,就说明此时的电阻就越大,从而说明光照强度越弱。

我们就可以通过判断ADC转换的值来判断此时外界的光照强度。在判断之后就可以做出相应的命令,例如LED的亮灭,蜂鸣器发声与不发声,等等其他的功能。

二、软件设计

1.主函数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);//中断优先级分组,给串口使用的
	delay_init();//延时初始化
	LED_Init();//led(PB5)初始化
	uart_init(115200);//串口初始化
	ADC3_CH6_Init();//ADC3_CH6初始化
	while(1)
	{
		adcx=Lsens_Get_Val();
		printf("光照强度为=%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,超过的话可能不准。
	
	ADC_DeInit(ADC3);
	
	ADC_InitTypeDef ADC_InitStruct;
	ADC_InitStruct.ADC_ContinuousConvMode=DISABLE;//指定是否是连续转换还是单个转换。也就是连续采集还是单次采集。我这里不管配置什么都是一直在采集
	ADC_InitStruct.ADC_DataAlign=ADC_DataAlign_Left;//数据向右对齐
	ADC_InitStruct.ADC_Mode=ADC_Mode_Independent;//单通道的独立模式
	ADC_InitStruct.ADC_NbrOfChannel=1;//顺序进行规则转换的ADC通道的数目
	ADC_InitStruct.ADC_ScanConvMode=DISABLE;//模数转换工作在单通道模式
	ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	//转换由软件而不是外部触发启动
	ADC_Init( ADC3, & ADC_InitStruct);//ADC模式初始化
	
	ADC_Cmd( ADC3, ENABLE);//ADC使能
	
	ADC_ResetCalibration(ADC3);//复位校准使能
	while(ADC_GetResetCalibrationStatus(ADC3));//等待复位校准完成
	
	ADC_StartCalibration(ADC3);//开启AD校准
	while(ADC_GetCalibrationStatus(ADC3));//等待AD校准完成
}


u16 Get_AdcValue(u8 ch)
{
	ADC_RegularChannelConfig(ADC3, ch, 1, ADC_SampleTime_239Cycles5);
	//ADC1,通道1,

	ADC_SoftwareStartConvCmd(ADC3, ENABLE);//ADC1的软件转换启动使能
	while(ADC_GetFlagStatus( ADC3, ADC_FLAG_EOC)==RESET);//等待转换结束
	
	return ADC_GetConversionValue(ADC3);//返回转换值
}

//读取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对应的ADC转换数据为4096。所以读到的数据不会超过4096
	
	
	//	光照最强的时候,电阻最小,电压也最小,ADC转换出来的数据也最小
	//	光照最弱的时候,电阻最大,电压也最大,ADC转换出来的数据也最大
	//我希望把光照等级分成10份,光照最强的时候为10,最弱的时候为0。在正常状态数据为(0-4),打开手电筒数据为(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 


验证

当我关闭手电筒的时候,串口打印出来的数据小于5,此时LED变亮。
当我用手电筒照着光敏电阻时,串口打印出来的数据大于等于5,此时LED变暗。
说明此时模拟楼道光控开关试验成功。

  • 6
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我不是小白菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值