⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sushe_lamp.c

📁 带时间显示的室内灯光控制
💻 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 + -