前述:
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_();
}