?? sushe_lamp.c
字號:
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit DQ=P3^0; //溫度傳感的DQ腳
sbit lcden=P3^1; //LCD 的E腳
sbit lcdrs=P3^2; //LCD的RS腳
sbit cro_l=P3^3; //光控中斷控制腳
sbit cro_h=P3^4; //人體紅外中斷控制腳
sbit lamp=P3^5;
sbit wr=P3^6;
sbit rd=P3^7;
sbit cro_t=P1^7; //時間控制中斷腳
bit flag_init=0;
uchar code ascII[]={
0x30,0x31,0x32,0x33,
0x34,0x35,0x36,0x37,
0x38,0x39}; //0到9的ASCII碼
uchar code tbweek[][9]={
{0x4d,0x6f,0x6e,0x64,0x61,0x79},
{0x54,0x75,0x65,0x73,0x64,0x61,0x79},
{0x57,0x65,0x64,0x6e,0x65,0x73,0x64,0x61,0x79},
{0x54,0x68,0x75,0x72,0x73,0x64,0x61,0x79},
{0x46,0x72,0x69,0x64,0x61,0x79},
{0x53,0x64,0x74,0x75,0x72,0x64,0x61,0x79},
{0x53,0x75,0x6e,0x64,0x61,0x79}}; //星期一到星期天在液晶中顯示用的代碼
uint tens,units,decile,tmp,un_guang;
uchar time,sec,min,hour,week;
float tmprt;
void time_init();
void lcd_init();
void ADC_init();
void write_com(uchar com);
void write_data(uchar date);
void DS18B20_init();
void Readtemperature();
void Writeonechar(uchar dat);
uchar Readonechar();
void displaytt(uchar sec1,uchar min1,uchar hour1);
void displaytemp();
void displaywe();
void keyscan();
void delay(uint z);
void Delay_uS(uint tt);
void main()
{
lcd_init(); //液晶初始化
time_init(); //定時器初始化
DS18B20_init(); //溫度傳感器初始化
hour=12;
while(1)
{
Readtemperature(); //讀DS18B20檢測到的溫度
displaytt(sec,min,hour); //顯示時間
keyscan(); //按鍵掃描
displaytemp(); //顯示溫度
displaywe(); //顯示星期
ADC_init();
if(un_guang>52) //(假設)夜晚光強少于150lx
cro_l=1;
else //白天光強大于150lx,AD轉換后數少于52,給中斷口一個電平,使進入燈滅函數
cro_l=0;
if(cro_h==1)
lamp=0;
else //人體紅外檢測到有低電平(沒人時),控制燈滅
lamp=1;
if(hour==8) //早上八點讓被睡眠開關置零的P1^7口恢復高電平,傳感器開始正常工作
cro_t=1;
delay(21);
while(time>=16) //用大于等于代替等于才能確保進去
{
time=0;
sec++;
while(sec==60)
{
sec=0;
min++;
while(min==60)
{
min=0;
hour++;
while(hour==24)
{
sec=0;
min=0;
hour=0;
week++;
while(week==7)
week=0;
}
}
}
}
}
}
void lcd_init()
{
lcden=0; //寫狀態,使能為高脈沖
write_com(0x38); //顯示模式設置
write_com(0x01); //顯示清屏
write_com(0x0c); //開顯示,光標不顯示
write_com(0x06); //光標移動設置
write_com(0x80+0x00); //設置數據地址指針
}
void write_com(uchar com) //往LCD寫指令
{
lcdrs=0;
P2=com;
delay(2);
lcden=1;
delay(2);
lcden=0;
}
void write_data(uchar date) //往LCD寫數據
{
lcdrs=1;
P2=date;
delay(2);
lcden=1;
delay(2);
lcden=0;
}
void displaytt(uchar sec1,uchar min1,uchar hour1) //LCD時間顯示
{
uchar s1,s2,m1,m2,h1,h2;
write_com(0x80+0x00);
s2=sec1/10;
s1=sec1%10;
m2=min1/10;
m1=min1%10;
h2=hour1/10;
h1=hour1%10;
s1=ascII[s1];
s2=ascII[s2];
m1=ascII[m1];
m2=ascII[m2];
h1=ascII[h1];
h2=ascII[h2];
write_data(h2); //寫入小時的高位代碼
delay(5);
write_data(h1); //寫入小時的地位代碼
delay(5);
write_data(0x3a); //寫入時分間的分號代碼
delay(5);
write_data(m2);
delay(5);
write_data(m1);
delay(5);
write_data(0x3a);
delay(5);
write_data(s2);
delay(5);
write_data(s1);
delay(5);
}
void displaywe() //顯示星期
{
uchar j,we;
write_com(0x80+0x40); //星期在LCD中的地址
we=tbweek[week][0];
for(j=0;j<=8;j++)
{
we=tbweek[week][j];
write_data(we); //寫入星期的ASCII符號
delay(2);
}
}
void keyscan() //鍵盤掃描
{
uchar temp;
temp=P1;
temp=temp&0x0f;
while(temp!=0x0f)
{
temp=P1;
temp=temp&0x0f;
delay(3);
switch(temp)
{
case 0x07: cro_t=!cro_t; //每按一次改變一次燈的狀態
break;
case 0x0b: min++;
if(min==60)
min=0;
break;
case 0x0d: hour++;
if(hour==24)
hour=0;
break;
case 0x0e: week++;
if(week==7)
week=0;
break;
}
while(temp!=0x0f) //按鍵松開檢測
{
temp=P1;
temp=temp&0x0f;
}
}
}
void time_init() //定時器初始化
{
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=1;
}
void ADC_init() //ADC轉換初始化
{
wr=1;
wr=0;
delay(2);
wr=1;
rd=0;
un_guang=P0; //AD轉換后的電壓值二進制數據賦給變量un_guang
delay(2);
rd=1;
}
void DS18B20_init() //溫度傳感ds18b20初始化
{
flag_init=1; //初始化成功標志位,0為成功
DQ=1; //DQ復位
_nop_();
DQ=0; //拉低DQ
Delay_uS(52); //延時484us(此信號要求480us~960us)
DQ=1; //釋放DQ
Delay_uS(5); //延時61us (在檢測到 I/O 引腳上的上升沿之后DS18B20等待15us~60us并且接著發送存在脈沖60-240us的低電平信號)
flag_init=DQ;
Delay_uS(25); //延時241us(DS18B20發送存在脈沖的低電平信號60~240us)
}
void displaytemp() //溫度顯示
{
uchar te1,te2,te3;
write_com(0x80+0x4a); //溫度在LCD顯示的地址
te3=ascII[tens];
write_data(te3); //顯示十位
delay(5);
te2=ascII[units];
write_data(te2); //顯示各位
delay(5);
write_data(0x2e); //顯示小數點
delay(5);
te1=ascII[decile];
write_data(te1); //顯示小數點后一位
delay(5);
write_data(0xdf); //顯示攝氏度的符號圓圈
delay(5);
write_data(0x43); //顯示攝氏度的符號C
delay(5);
}
uchar Readonechar() //讀一個字節
{
unsigned char i,dat=0;
for(i=8;i;i--)
{
DQ=0;
dat>>=1;
DQ=1;
if(DQ)
dat|=0x80;
Delay_uS(5);//延時61us(所有讀時間片的最短持續期限為60us,各個讀時間片之間必須有最短為1us的恢復時間)
}
return dat;
}
void Writeonechar(unsigned char dat) //寫一個字節
{
unsigned char i;
for(i=8;i;i--)
{
DQ=0;
DQ=dat&0x01;
Delay_uS(5); //延時61us(在I/O線由高電平變為低電平之后DS1820在15us~60us之間對 I/O 線采樣)
DQ=1;
dat>>=1;
}
}
void Readtemperature() //讀溫度
{
tens=0;units=0;decile=0;tmp=0;
tmprt=0;
DS18B20_init();
Writeonechar(0xcc);// 跳過讀序列號的操作
Writeonechar(0x44);// 啟動溫度轉換
DS18B20_init();
Writeonechar(0xcc);//跳過讀序號列號的操作
Writeonechar(0xbe);//讀取溫度寄存器
units=Readonechar();//讀低八位
tens=Readonechar(); //讀高八位
tens<<=8;
tens|=units; //高低位合并
tmprt=tens*0.0625; //計算溫度值
tmp=tmprt*10+0.5; //放大10倍輸出并四舍五入
tens=tmp/100; //十位
units=tmp/10%10; //個位
decile=tmp%10; //小數位
}
void timer0() interrupt 1 //定時器0中斷
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
time++;
}
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void Delay_uS(unsigned int tt) //延時時間為(tt*9+16)us.晶振為12MHz
{
while(tt--)
;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -