329 基于单片机智能照明灯控制系统设计【毕设课设】

本文设计了一种具有时控和光控相结合的太阳能路灯控制器,利用单片机STC12C2051和时钟芯片DS1302控制路灯照明时间,利用低功耗的数据存储器AT24C02存储路灯点亮和熄灭时间,利用光敏电阻实现光电控制。傍晚光线暗时控制器自动接通路灯电源,深夜行人少时根据设置的时间熄灭路灯,早上再自动接通电源点亮路灯、天亮后自动关断。文中详细分析了控制器的电路组成和工作原理,简述了控制器的调试过程。

太阳能路灯由太阳能电池、蓄电池、高亮度LED, 控制器等部件组成,减少噪声污染:太阳能路灯运动部件很少,基本没有噪声。太阳辐射能是取之不尽、用之不竭的,是人类能够自由利用的能源。在世界能源短缺、环境污染日益严重的今天,充分开发利用太阳能是世界各国政府可持续发展的能源战略决策。与传统的照明工具相比,超高亮白光LED照明源体积小、重量轻、方向性好并可耐各种恶劣条件,在功耗、寿命以及环保等方面有不可比拟的优越性,再加上太阳能灯具的节能性和安装简便,所以凡有工频交流电灯具的地方,LED灯具的触角就会到达。21世纪将是以固体发光材料为核心的,即以LED为代表的新型光源、绿色照明的世纪。今后。随着各国政府的高度重视和加大投入,LED必将成为本世纪极具竞争力的新型绿色环保光源而掀起一次照明领域新的革命。

系统设计

 太阳能LED路灯在白天通过太阳能电池组件采集太阳光的能量,并将其转化为电能存储起来,即向蓄电池充电,在晚上光线较暗时由蓄电池经路灯控制处理器控制,点亮LED灯用于路灯照明。

根据各部分电路的功能不同,整体电路可以分为以下几个部分,太阳能电池板组件、过充过放电控制电路、STC12C2051单片机、蓄电池、时控光控电路、照明负载和时间显示电路。
由太阳能电池板通过7805稳压电路为单片机供电,并通过为蓄电池充电,当蓄电池电压较低时其容量损耗得很快,使用寿命也会缩减,为延长蓄电池的寿命,要防止蓄电池出现过充或过放,因此本电路加的有过充过放控制电路。

系统太阳能供电,24V蓄电池电压经过7805稳压后产生5V电压,作为控制器的主电源。电容C2、C3作为高频旁路电容,将高频信号旁路到地。同样电容C1、C4为滤波电容。

过充控制,就是在蓄电池处于过充状态时断开充电电路,过放控制电路就是在蓄电池处于过放状态时断开放电电路。过充、过放控制都是为了保护蓄电池,延长蓄电池的使用寿命。

系统的软件设计主要包括程序初始化、时间设定子程序、1302的读写程序、24C02的读写程序、时间比较子程序、按键子程序、显示刷新子程序等共同组成。程序开始要进行初始化,调用24c02内部存储的开关路灯时间点,程序每各一段时间调一次1302中的时间[17]。通过程序将设定的时间同系统当前时间进行比较,设定的比较间隔为1秒一次,当时间相同时,则通过程序输出控制信号,对驱动电路进行驱动。

如果想调整开关路灯时间点和1302中的当前时间可以通过设置的按键手动进行时间的调节图中开关S1、S2、S3分别为显示1302时间键,功能键和加一键。

完整版 电路图和程序代码 下载地址

https://pan.baidu.com/s/1tJRmtZtN_piWpCinulxb_w?pwd=8888

部分代码展示

#include<reg51.h>
 #include<intrins.h>
  #include<string.h>
 #define uchar unsigned char
 #define uint unsigned int
 #define delayNOP() {_nop_();_nop_();_nop_();_nop_();}
 sbit SDA=P1^0;  // DS1302数据线
 sbit CLK=P1^1;  //	 DS1302时钟线
 sbit RST=P1^2;  // DS1302复位线
 //DS18B20数据端口定义
sbit DQ=P2^4;    //DS18B20数据端口
 sbit LCD_RS=P2^5;   // LCD寄存器选择
 sbit LCD_RW=P2^6;   // 	LCD读写/写控制
 sbit LCD_EN=P2^7;   //  LCD启用
 sbit K1=P3^2;   //  选择
 sbit K2=P3^3;   // 确定 
 sbit K3=P3^5;   // 加
 sbit K4=P3^6;  // 减

 
sbit key_1=P3^0;	//自动手动切换
sbit key_2=P3^1;	//关灯,按一下,关一个
sbit key_3=P3^4;	//开灯,按一下,开一个
uchar code zz[]={0x08,0x0c,0x04,0x06,0x02,0x03,0x01,0x09};
uchar code fz[]={0x09,0x01,0x03,0x02,0x06,0x04,0x0c,0x08};  
sbit R_LED=P2^0;   //红灯
sbit Y_LED=P2^1;   //黄灯
sbit G_LED=P2^2;   //绿灯
sbit B_LED=P2^3;   //蓝灯

sbit guangmin=P1^3;	  //光敏电阻传感器
sbit ren1=P1^4;		  //红外热释电传感器1
sbit ren2=P1^5;		  //红外热释电传感器2
sbit ren3=P1^6;		  //红外热释电传感器3
sbit ren4=P1^7;		  //红外热释电传感器4



//温度字符
 uchar code Temperature_Char[8]={0x0c,0x12,0x12,0x0c,0x00,0x00,0x00,0x00};
//温度小数对照表
 uchar code df_Table[]={0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,9};
 uchar CurrentT=0; //当前读取温度的整数部分
 uchar Temp_Value[]={0x00,0x00};	 //从DS18B20读取的温度值
 uchar Display_Digit[]={0,0,0,0};//待显示的各温度数位
bit DS18B20_IS_OK=1;//传感器正常标志

 uchar tCount=0;
 //一年中每个月的天数,2月的天数由年份决定
 uchar MonthsDays[]={0,31,0,31,30,31,30,31,31,30,31,30,31};
 //周日,每周一到周六(0,1-6)【读取DS1302时分别是1-7】
 uchar *WEEK[]={"SUN","MON","TUS","WEN","THU","FRI","SAT"};

//LCD显示缓冲
uchar LCD_DSY_BUFFER1[]={"00-00-00        "};
uchar LCD_DSY_BUFFER2[]={"00-00-00      "};
uchar DateTime[7];  //所读取的日期时间
uchar Adjust_flag=0; //当前调节的时间对像:秒,分,时,日,月,年(1,2,3,4,5,6)
uchar Change_Flag[]=" YMDHM";//(分,时,日,月,年)(不调节秒与周)

//延时
void DelayMS(uchar x)
{uchar i;
while(x--)
for(i=0;i<120;i++);
}

//向DS1302写入一个字节
void Write_A_Byte_TO_DS1302(uchar x)
{uchar i;
for(i=0;i<8;i++)
{SDA=x&1;  CLK=1;  CLK=0; x>>=1;
}
}

//从DS11302读取一个字节
uchar Get_A_Byte_FROM_DS1302()
{uchar i,b,t;
for(i=0;i<8;i++)
{b>>=1; t=SDA; b|=t<<7;  CLK=1;CLK=0;
}
//BCD码转换
return b/16*10+b%16;
}
//从DS1302指定位置读数据
uchar Read_Data(uchar addr)
{uchar dat;
RST=0; CLK=0; RST=1;
Write_A_Byte_TO_DS1302(addr);
dat=Get_A_Byte_FROM_DS1302();
CLK=1;RST=0;
return dat;
}

//向DS1302某地址写入数据
void Write_DS1302(uchar addr,uchar dat)
{CLK=0;RST=1;
Write_A_Byte_TO_DS1302(addr);
Write_A_Byte_TO_DS1302(dat);
CLK=0;RST=0;
}

//设置时间
void SET_DS1302()
{ uchar i;
Write_DS1302(0x8e,0x00); //写控制字,取消写保护
//分时日月年依次写入
for(i=0;i<7;i++)
{
//分的起始地址10000010(0x82),后面连续依次是时,日,月,周,年,写入 地址每次增2
Write_DS1302(0X80+2*i,(DateTime[i]/10<<4)|(DateTime[i]%10));
}
Write_DS1302(0x8e,0x80);//加保护
}

//读取当前的时间
void GetTime()
{
  uchar i;
  for(i=0;i<7;i++)
   {
     DateTime[i]=Read_Data(0x81+2*i);
   }
}


//LCD忙等待
 bit LCD_Busy_Check()
 {bit result;
 LCD_RS=0;
 LCD_RW=1;
 LCD_EN=1;
 delayNOP();
 result=(bit)(P0&0x80);
 LCD_EN=0;
 return result;
 }

 //写指令
void Write_LCD_Command(uchar cmd)
{while(LCD_Busy_Check());
LCD_RS=0;LCD_RW=0;LCD_EN=0;	_nop_(); 	_nop_();
P0=cmd;
delayNOP();
LCD_EN=1;
delayNOP();
LCD_EN=0;
}
 //写数据
void Write_LCD_Data(uchar dat)
{while(LCD_Busy_Check());
LCD_RS=1;LCD_RW=0;LCD_EN=0;
P0=dat;
delayNOP();
LCD_EN=1;
delayNOP();
LCD_EN=0;
}

//初始化
void Init_LCD()
{Write_LCD_Command(0x01);DelayMS(5);
Write_LCD_Command(0x38);DelayMS(5);
Write_LCD_Command(0x0c);DelayMS(5);
Write_LCD_Command(0x06);DelayMS(5);
}
//设置显示位置
 void Set_LCD_POS(uchar pos)
 {	Write_LCD_Command(pos|0x80);
  }

//在LCD上显示字符串
void Display_LCD_String(uchar p,uchar *s)
{uchar i;
Set_LCD_POS(p);
for(i=0;i<16;i++)
{Write_LCD_Data(s[i]);
DelayMS(1);
}
}

//日期与时间值转换为数字字符
void Format_DateTime(uchar d,uchar *a)
{a[0]=d/10+'0';
a[1]=d%10+'0';
}

//判断是否为闰年
uchar isLeapYear(uint y)
{return (y%4==0&&y%100!=0)||(y%400==0);
}

//求自2000.1.1开始的任何一天是星期几
void RefreshWeekDay()
{uint i,d,w=5; //已知1999.12.31是星期五
for(i=2000;i<2000+DateTime[6];i++)
{ d=isLeapYear(i)?366:365;
w=(w+d)%7;
}
d=0;
for(i=1;i<DateTime[4];i++)
d+=MonthsDays[i];
d+=DateTime[3];
//保存星期,0~6表示星期日,星期一,二.....六,为了与DS1302的星期格式匹配,返回值需要加1
DateTime[5]=(w+d)%7+1;
}

 //延时函数2
 void Delay(uint x)
 {while(--x);
 }
 /***************初始化18B20温度函数******************/
uchar Init_DS18B20()
{
   uchar status;
   DQ=1;
   Delay(8);
   DQ=0;
   Delay(90);
   DQ=1;
   Delay(8);
   status=DQ;
   Delay(100);
   DQ=1;
   return status;
}
 
//读一字节
uchar ReadOneByte()
{uchar i,dat=0;
DQ=1;_nop_();
for(i=0;i<8;i++)
{DQ=0;dat>>=1;DQ=1;_nop_();_nop_();
if(DQ)dat|=0x80;
Delay(30);
DQ=1;
}
return dat;
}

//写一字节
void WriteOneByte(uchar dat)
{uchar i;
for(i=0;i<8;i++)
{ DQ=0;DQ=dat&0x01;Delay(5);DQ=1;dat>>=1;
}
}

//读取温度值
void Read_Temperature()
{
//延时值与负数标识
uchar t=150,ng=0;
//高5位全为1(0xf8)则为负数,为负数时取反加1,并设置负数标识

if(Init_DS18B20()==1)  //DS18B20故障
DS18B20_IS_OK=0;
else
{WriteOneByte(0xcc);   //跳过序列号
WriteOneByte(0x44);//启动温度转换
 Init_DS18B20();
 WriteOneByte(0xcc);   //跳过序列号
WriteOneByte(0xBE);//读取温度寄存器
Temp_Value[0]=ReadOneByte();  //温度低8位
Temp_Value[1]=ReadOneByte();  //温度高8位
DS18B20_IS_OK=1;
if((Temp_Value[1]&0xf8)==0xf8)
{
Temp_Value[1]=~Temp_Value[1];
Temp_Value[0]=~Temp_Value[0]+1;
if(Temp_Value[0]==0x00)
Temp_Value[1]++;
//负数标志置1
ng=1;
}
//查表得到温度的小数部分
Display_Digit[0]=df_Table[Temp_Value[0]&0x0f];
//获取温度整数部分(高字节中的低三位与低字节中的高4位,无符号)
CurrentT=((Temp_Value[0]&0xf0)>>4)|((Temp_Value[1]&0X07)<<4);
//将整数部分分解为3位待显示数字
Display_Digit[3]=CurrentT/100;
Display_Digit[2]=CurrentT%100/10;
Display_Digit[1]=CurrentT%10;

  • 12
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值