单片机大作业.docx
《单片机大作业.docx》由会员分享,可在线阅读,更多相关《单片机大作业.docx(16页珍藏版)》请在冰点文库上搜索。
单片机大作业
课题名称
简易楼道灯电费计价系统
院、系、部
自动化与电气工程学院
专业
电气工程及其自动化
班级
姓名
学号
指导教师
单片机大作业
1.作业背景
城市居民楼内一般安装有楼道灯,方便夜间居民上下楼,其工作特点是人来灯亮,人走灯灭。
以热释电型楼道灯为例,其基本工作原理是:
热释电传感器能检测人体是否进入感应范围,当人体未进入感应范围,即离楼道灯还有一定距离时,传感器输出低电平;当人体进入感应范围,即靠近楼道灯时,传感器输出高电平。
根据传感器的输出,单片机可决定是否点亮楼道灯。
由于楼道灯属本单元全体居民共用,为便于电费结算,现要求设计一套简易楼道灯电费计价系统,系统能自动计算楼道灯在一个月内的总点亮时间,并据此计算出应缴电费额度。
2.作业要求
系统由电源电路、热释电传感器、单片机、按键以及显示器组成,楼道灯供电为220市电,功率2kW(实际灯泡功率一般不会这么大。
考虑到实验演示时间有限,故假设此灯泡功率为该值)。
其中电源采用5V,热释电传感器的输出采用按键按下与否进行模拟,单片机采用51,显示器采用4位数码管,电价按5.86元/千瓦时(实际电价一般为0.58。
考虑到实验演示时间有限,故假设电价为该值),要求电费计算精度精确到0.01元。
用户可用按键查询本月楼道灯总点亮时间(精度0.01小时),以及本月总电费。
3.硬件部分
(1)仿真电路图
(2)实物电路图:
(3)
元器件列表
STC89C52RC
一个
按钮开关
3个
四位共阳数码管
1个
12M晶振
1个
CS9012三极管
1个
二极管
1个
ZS230-25G灯泡
1个
HK4100F-DC5V-SHG继电器
1个
接线端子
1个
3906PNP三极管
4个
电容、电阻
若干
(4)电路介绍:
1>起振电路:
由一个12M晶振和两个20pF的电容组成,接在单片机STC89C52的18、19脚间,为整个电路提供时钟脉冲,一个机器周期为1us。
2>复位电路:
由一个0.1nF的电容和一个100Ω的电阻,电容两端并联一个按钮开关S6组成复位电路,接在单片机第9脚上,按下开关S6,电路复位。
同时,将31脚接至VCC,采用内部存储器。
3>数码管显示电路:
采用四位7段共阳数码管
位选线接至P2.0-P2.3,段选线接至P0口。
4>外部中断连线:
按钮开关S1控制定时器T0开关状态,按下S1,模拟人来,则控制灯亮;按钮开关S2接至P3.3,控制外部中断INT1,按下S2,数码管显示当月灯亮总时间。
4.软件部分
(1)程序流程图
(2)程序代码:
#include
#defineSEGP0//段选线接至P0
#defineSCANPP2//位选线接至P2
sbitLAMP=P1^2;//灯接至P1.2
sbitS1=P3^4;//开关S1接至P3.4
sbitS2=P3^3;//开关S2接至P3.3,外部中断INT1,显示时间(h)
#definecount50000//声明计数值,0.05s
#defineTH(65536-count)/256//声明计数高8位
#defineTL(65536-count)%256//声明计数低8位
charcount_T0=0;//计数T0中断次数
charcount_T1=0;//计数T1中断次数
voiddebouncer(void);
voiddelay1ms(int);//声明动态显示延时x(ms)函数
voiddispmoney(void);//声明计费显示函数
charcodeTAB[11]={0xc0,0xf9,0xa4,0xb0,0x99,
0x92,0x82,0xf8,0x80,0x90};
chardispm[4]={0,0,0,0};//设置计费显示初值
chardispt[4]={0,0,0,0};//设置计时显示初值
charseconds=0;
charscan=1;
intt=0;//声明灯在一个月内的总点亮时间t变量
intl=0;
charp=0;
charq=0;
main()
{
IE=0x8e;//允许T0、INT1、T1中断
TMOD=0x11;//T0采用Mode1、T1采用Mode1
TH1=TH;
TL1=TL;
TR1=1;//定时器T1启动
LAMP=1;//设置灯初始为熄灭状态
while
(1)
{
if(S1==0)//开关S1若按下,模拟传感器检测到人来
{
debouncer();
if(S1==0)
{
TH0=TH;
TL0=TL;
TR0=1;//定时器T0启动
LAMP=0;//灯点亮
}
}
dispmoney();//显示电费值
}
}
voidT0_30s(void)interrupt1//T0定时器中断,计时30s
{
TH0=TH;
TL0=TL;
if(++count_T0==20)//计数溢出次数,20*0.05=1s
{
count_T0=0;//重新计数
seconds++;
if(seconds==30)//计数30次,30*1=30s
{
seconds=0;//重新计数
LAMP=1;//设置灯灭
t++;//灯点亮时间加1
TR0=0;//停止T0定时器
}
}
}
voidT1_1month(void)interrupt3//T1中断,定时1month
{
TH1=TH;
TL1=TL;
if(++count_T1==20)//1s
{
count_T1=0;
l++;
if(l==3600)//1h
{
l=0;
p++;
if(p==24)//1day
{
p=0;
q++;
if(q==30)//1month
q=0;
t=0;//灯点亮总时间t清零
}
}
}
}
voiddisptime(void)interrupt2//INT1中断,显示灯当月的总点亮时间
{
charj;
inttime;
scan=0x01;
for(j=0;j<4;j++)
{
time=t*30/36;
dispt[3]=TAB[time/1000];
dispt[2]=0x7f&TAB[time%1000/100];
dispt[1]=TAB[time%100/10];
dispt[0]=TAB[time%10];
SEG=0xff;
SCANP=~scan;
SEG=dispt[3-j];
delay1ms
(2);//延时约2ms,4*2=8ms<16ms,可实现动态显示
scan<<=1;
}
}
voiddispmoney(void)//计费显示函数
{
chari;
intmoney;
scan=0x01;
for(i=0;i<4;i++)
{
money=t*293/30;
dispm[3]=TAB[money/1000];
dispm[2]=0x7f&TAB[money%1000/100];
dispm[1]=TAB[money%100/10];
dispm[0]=TAB[money%10];
SEG=0xff;
SCANP=~scan;
SEG=dispm[3-i];
delay1ms
(2);
scan<<=1;
}
}
voiddebouncer(void)//去抖动函数
{
intk;
for(k=0;k<2400;k++);
}
voiddelay1ms(intx)//延时x(ms)函数
{
intm,n;
for(m=0;mfor(n=0;n<120;n++);
}
5.仿真调试:
按钮开关S1模拟人来,灯亮后定时30s,灯灭,数码管刷新电费值一次,单位(元),精确到0.01元;按钮开关S2被按下时,数码管显示当月灯亮总时间,单位(小时),精确到0.01小时。
按下开关S1,定时30s开始
30s定时结束,数码管显示当月电费
按下S2,显示当月灯点亮总时间
6.实验总结
通过本次单片机大作业的完成,从刚开始的硬件电路设计,到软件程序的编写,然后经过软件Proteus的仿真调试,接着进行电路板焊接,到最后调试成功,历时三周左右,让我受益颇多。
其中,也遇到很多的困难,比如元器件型号的选择、购买,程序各部分单元的组合结构一改再改,还有软件应用的困难等,但都通过与同学们的讨论、交流最终得以克服。
本人热爱动手实践,喜欢通过理论的学习后可以将其与实践相结合,通过实践的过程,可以收获的不仅仅的是短暂的成就感,更多的是对理论知识的深刻理解和对实践应用的不断熟练,通过这个过程,使自己的专业素养进一步得到培养和锻炼。
总之,凡事预则立,不预则废。
我相信,向着自己追求的方向不断努力的过程是永远的快乐。