前述:
QQ:3177227373
这个是一个自己做的一个毕设的作品。
主要内容
本设计要实现一个以单片机为核心的人体感应灯光调控系统电路设计。该系统通过人体感应传感器来感知室内是否有人存在,通过光敏电阻感应室内的光线强度;采集来的信息经系统处理、分析后作出判断,决定是否开启灯光;根据室内光线强度的不同可实现对室内的光照强度的调节。同时系统可通过按键模块进行灯的手动操作,并且系统还具显示当前时间等功能。
感应式调灯光系统选用单片机为控制核心器件。系统由硬件和软件两部分组成。
系统硬件结构设计
智能人体感应灯光系统硬件部分主要包括人体感应模块、光照感应模块、显示模块、调光模块、照明模块、单片机控制模块及按键控制模块等七个模块,其原理框图如图1所示。
人体感应模块可通过人体红外线传感器感知是否有人体的存在,光照感应模块可感知当前实际光照强度;当有人且周围光线强度满足要求时,单片机控制模块可控制系统可自行启动照明;当感应到室内光线过亮或长时间没有人时单片机控制模块可控制系统可自行切断照明。同时系统利用显示模块实时显示时间,利用按键控制模块手动开关照明,利用调光模块调节照明亮度。照明模块用来模拟和显示照明效果。
人体感应模块采用HC-SR501人体红外感应模块
按键采用普通轻触按键
光照感应模块采用光敏电阻和AD采集
显示模块采用数码管
照明模块采用mos管驱动一个LED灯
调光模块采用自动调光和按键手动调光
系统软件结构设计
感应式调灯光系统软件部分由系统软件和应用软件组成。系统软件部分主要完成对硬件电路的驱动,对采集数据的收集、处理、分析及传输,依据采集数据进行判断并向执行功能模块发出对应的控制指。其主要由主程序、数据采集、数据处理、按键扫描和显示等几个主要的功能程序构成。
通过各软件功能程序可对信号(包括检测室内有无人员、光强等)采集并进行处理,并且根据室内有无人员和光强的大小来共同控制室内亮、灭情况和亮度调节情况,从而实现对室内灯光的智能控制;当按下按键时,可根据按键的判断功能,并进行相应的人为控制。
实物照片
PCB
部分代码
数码管显示
void SMG_Display()
{
//时间显示
SMG_dat(1,smgduan[TIME[2]/16]); //时十位
SMG_dat(2,smgduan[TIME[2]&0x0f]); //时个位
SMG_dat(3,smgduan[10]); //-
SMG_dat(4,smgduan[TIME[1]/16]); //分十位
SMG_dat(5,smgduan[TIME[1]&0x0f]); //分个位
SMG_dat(6,smgduan[10]); //-
SMG_dat(7,smgduan[TIME[0]/16]); //秒十位
SMG_dat(8,smgduan[TIME[0]&0x0f]); //秒个位
//光强ADC数据百分比显示,调试用
// SMG_dat(7,smgduan[ADC_Dat/10]);//十位
// SMG_dat(8,smgduan[ADC_Dat%10]);//个位
}
//数码管位置及数据显示 w;位置 dat;数据
void SMG_dat(u8 w,u8 value)
{
Choose_W(w);//位选
P0 = value;//段选
delay_us(6);//消隐
}
//74HC138显示位数选择
void Choose_W(u8 w)
{
switch(w) //位选,选择点亮的数码管
{
case(1):
LSA=0;LSB=0;LSC=0; break;//显示第1位
case(2):
LSA=1;LSB=0;LSC=0; break;//显示第2位
case(3):
LSA=0;LSB=1;LSC=0; break;//显示第3位
case(4):
LSA=1;LSB=1;LSC=0; break;//显示第4位
case(5):
LSA=0;LSB=0;LSC=1; break;//显示第5位
case(6):
LSA=1;LSB=0;LSC=1; break;//显示第6位
case(7):
LSA=0;LSB=1;LSC=1; break;//显示第7位
case(8):
LSA=1;LSB=1;LSC=1; break;//显示第8位
}
}
按键处理
//按键扫描
void Key_scan()
{
if((K1==0)&&(Flag_1==0))
{
delay_ms(10);//消抖
if((K1==0)&&(Flag_1==0))
{
LED_PWM++;
}
while(K1 == 0);
}
if((K2==0)&&(Flag_1==0))
{
delay_ms(10);//消抖
if((K2==0)&&(Flag_1==0))
{
LED_PWM--;
}
while(K2 == 0);
}
if(Flag_1==0)
{
if(LED_PWM<0)
{LED_PWM=0;}
if(LED_PWM>10)
{LED_PWM=10;}
}
if((People==1)&&(Flag_1==1))
{
delay_ms(10);
if(People==1)
{People_Flag=1;}
else
{People_Flag=0;}
}
else
{People_Flag=0;}
if(K5==0)
{
delay_ms(10);
if(K5==0)
{Flag_1=~Flag_1;}
while(K5==0);
}
}
光强转化为PWM
//光强转化为PWM
void Light_Conversion_PWM()
{
if(People_Flag==1)
{
ADC_Dat=ReadADC(0)/2.56;
LED_PWM=ADC_Dat/10;
}
if((People_Flag==0)&&(Flag_1==1))
{LED_PWM=10;}
}
AD光强采集
#define AddWr 0x90 //写数据地址
#define AddRd 0x91 //读数据地址
sbit Sda=P2^1; //定义总线连接端口
sbit Scl=P2^0;
//读取AD模数转换的值,有返回值
unsigned char ReadADC(unsigned char Chl)
{
unsigned char Data;
Start(); // 启动IIC总线
Send(AddWr); //写入芯片地址
Ack();
Send(0x40|Chl);//写入选择的通道,Chl的值分别为0、1、2、3,分别代表1-4通道
Ack();
Start();
Send(AddRd); //读入地址
Ack();
Data=Read(); //读数据
Scl=0;
NoAck();
Stop();
return Data; //返回值
}
DS1302底层驱动
#include "DS1302.h"
//---存储顺序是秒分时日月周年,存储格式是用BCD码---//
//2019年 第1周 11月 28日 23点 20分 45秒
u8 TIME[7] = {0x45, 0x20, 0x23, 0x28, 0x11, 0x01, 0x19};
///////////////////////////初始化DS1302 写入时间
void Ds1302Init()
{
u8 n;
u8 Wadd = 0x80;
Ds1302Write(0x8E,0X00); //禁止写保护,就是关闭写保护功能
for (n=0; n<7; n++) //写入7个字节的时钟信号:分秒时日月周年
{
Ds1302Write(Wadd,TIME[n]);
Wadd+=2;
}
Ds1302Write(0x8E,0x80); //打开写保护功能
}
///////////////////////////读取时钟信息
void Ds1302ReadTime()
{
u8 n;
u8 Radd = 0x81;
for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年
{
TIME[n] = Ds1302Read(Radd);
Radd+=2;
}
}
///////////////////////////读取一个地址的数据
u8 Ds1302Read(u8 addr)
{
u8 n,dat,dat1;
RST = 0;
_nop_();
SCLK = 0;//先将SCLK置低电平。
_nop_();
RST = 1;//然后将RST(CE)置高电平。
_nop_();
for(n=0; n<8; n++)//开始传送八位地址命令
{
DSIO = addr & 0x01;//数据从低位开始传送
addr >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;//DS1302下降沿时,放置数据
_nop_();
}
_nop_();
for(n=0; n<8; n++)//读取8位数据
{
dat1 = DSIO;//从最低位开始接收
dat = (dat>>1) | (dat1<<7);
SCLK = 1;
_nop_();
SCLK = 0;//DS1302下降沿时,放置数据
_nop_();
}
RST = 0;
_nop_(); //以下为DS1302复位的稳定时间,必须的。
SCLK = 1;
_nop_();
DSIO = 0;
_nop_();
DSIO = 1;
_nop_();
return dat;
}
///////////////////////////向DS1302命令(地址+数据)
void Ds1302Write(u8 addr, u8 dat)
{
u8 n;
RST = 0;
_nop_();
SCLK = 0;//先将SCLK置低电平。
_nop_();
RST = 1; //然后将RST(CE)置高电平。
_nop_();
for (n=0; n<8; n++)//开始传送八位地址命令
{
DSIO = addr & 0x01;//数据从低位开始传送
addr >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;
_nop_();
}
for (n=0; n<8; n++)//写入8位数据
{
DSIO = dat & 0x01;
dat >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;
_nop_();
}
RST = 0;//传送数据结束
_nop_();
}