整個系統以STC89C52單片機為核心器件,配合電阻電容晶振等器件,構成單片機的最小系統。其它個模塊圍繞著單片機最小系統展開。其中包括,照明設備采用USB小燈進行模擬,在USB小燈內部,是6顆白色的LED燈;光照強度采集模塊,是使用光敏電阻+ADC0832,當外界有光照時,燈具會停止工作;人體感應采用紅外熱釋傳感器,該傳感器靈敏度高,操作控制簡單;時間控制模塊采用PWM脈沖寬度調制,控制燈光亮度最大工作時間為60s;最后是供電采用常用的USB 5V進行供電。
電路原理圖如下:
原理圖
最小系統模塊
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char // 以后unsigned char就可以用uchar代替
#define uint unsigned int // 以后unsigned int 就可以用uint 代替
sbit LED = P1^0; // 模式指示燈,亮是自動模式,滅是手動模式
sbit Key1 = P3^2; // 按鍵1,模式切換按鍵
sbit Key2 = P3^3; // 按鍵2,亮度減少按鍵
sbit Key3 = P3^4; // 按鍵3,亮度增加按鍵
sbit Lamp = P1^4; // 臺燈控制引腳
sbit ADC_CLK = P2^0; // ADC0832的CLK引腳
sbit ADC_DAT = P2^1; // ADC0832的DI/DO引腳
sbit ADC_CS = P2^3; // ADC0832的CS引腳
sbit Module = P2^2; // 人體紅外檢測模塊
sbit fog=P2^4;
uchar gCount=0; // 全局計數變量
uchar gIndex; // 亮度變量,0是最暗,9是最亮,一共10檔
uint gTime=0; // 計時變量,用于計時多久沒檢測到有人
bit alarm_fog_flag=0; //煙霧報警標志
/*********************************************************/
// 毫秒級的延時函數,time是要延時的毫秒數
/*********************************************************/
void DelayMs(uint time)
{
uint i,j;
for(i=0;i<time;i++)
for(j=0;j<112;j++);
}
/*********************************************************/
// ADC0832的時鐘脈沖
/*********************************************************/
void WavePlus()
{
_nop_();
ADC_CLK = 1;
_nop_();
ADC_CLK = 0;
}
/*********************************************************/
// 獲取指定通道的A/D轉換結果
/*********************************************************/
uchar Get_ADC0832()
{
uchar i;
uchar dat1=0;
uchar dat2=0;
ADC_CLK = 0; // 電平初始化
ADC_DAT = 1;
_nop_();
ADC_CS = 0;
WavePlus(); // 起始信號
ADC_DAT = 1;
WavePlus(); // 通道選擇的第一位
ADC_DAT = 0;
WavePlus(); // 通道選擇的第二位
ADC_DAT = 1;
for(i=0;i<8;i++) // 第一次讀取
{
dat1<<=1;
WavePlus();
if(ADC_DAT)
dat1=dat1|0x01;
else
dat1=dat1|0x00;
}
for(i=0;i<8;i++) // 第二次讀取
{
dat2>>= 1;
if(ADC_DAT)
dat2=dat2|0x80;
else
dat2=dat2|0x00;
WavePlus();
}
_nop_(); // 結束此次傳輸
ADC_DAT = 1;
ADC_CLK = 1;
ADC_CS = 1;
if(dat1==dat2) // 返回采集結果
return dat1;
else
return 0;
}
/*********************************************************/
// 定時器初始化
/*********************************************************/
void TimerInit()
{
TMOD = 0x01; // 使用定時器0,工作方式1
TH0 = 252; // 給定時器0的TH0裝初值
TL0 = 24; // 給定時器0的TL0裝初值
ET0 = 1; // 定時器0中斷使能
EA = 1; // 打開總中斷
TR0 = 1; // 啟動定時器0
}
void AutoControl(uchar num)
{
if(num<59) // 最亮
gIndex=1;
else if(num>241) // 最暗
gIndex=0;
}
/*********************************************************/
// 主函數
/*********************************************************/
void main()
{
uchar ret;
TimerInit(); // 定時器初始化
LED=0; // 指示燈點亮(自動模式指示燈)
ret=Get_ADC0832(); // 獲取AD采集結果(環境光照強度)
AutoControl(ret); // 上電先進行一次自動亮度控制
AutoControl(ret+7);
while(1)
{
/* 亮度控制 */
if(LED==0) // 如果LED是亮的
{
AutoControl(); // 則進行自動控制
}
if(gTime<600)
{
ret=Get_ADC0832(); // 獲取AD采集結果(環境光照強度)
AutoControl(ret); // 進行自動控制
DelayMs(200);
}
}
/*檢測是否有人*/
if(Module==1)
{
gTime=0; // 檢測到有人,則把60秒計時清零
}
if(gTime>60000) // 如果gTime的值超過了60000
{
gTime=60000; // 則把gTime的值重新賦值為60000,避免過大溢出
gIndex=0 ; // 如果1分鐘檢測不到有人,則把臺燈熄滅
}
}
/*********************************************************/
// 定時器0服務程序,1毫秒
/*********************************************************/
void Timer0(void) interrupt 1
{
TH0 = 252; // 給定時器0的TH0裝初值
TL0 = 24; // 給定時器0的TL0裝初值
gTime++; // 每1毫秒,gTime變量加1
gCount++; // 每1毫秒,gCount變量加1
if(gCount==10) // 如果gCount加到10了
{
gCount=0; // 則將gCount清零,進入新一輪的計數
if(gIndex!=0) // 如果說臺燈不是最暗的(熄滅)
{
Lamp=0; // 則把臺燈點亮
}
}
if(gCount==gIndex) // 如果gCount計數到和gIndex一樣了
{
if(gIndex!=1) // 如果說臺燈不是最亮的
{
Lamp=1; // 則把臺燈熄滅
}
}
}
全部資料51hei下載地址:
程序(Keil版).rar
(29.2 KB, 下載次數: 93)
2019-1-29 12:55 上傳
點擊文件名下載附件
源代碼
|