基于AT89C51单片机的计算器及时钟设计.docx
《基于AT89C51单片机的计算器及时钟设计.docx》由会员分享,可在线阅读,更多相关《基于AT89C51单片机的计算器及时钟设计.docx(24页珍藏版)》请在冰豆网上搜索。
基于AT89C51单片机的计算器及时钟设计
一、设计任务和性能指标
1.1设计任务………………………………………………………………….………………….………….……………………1
1.2设计指标…………………………………………….………………………………….…………………………………….1
二、设计方案..................................................................................................................1
三、硬件设计…………………………………………………………………………………………………………….2
3.1单片机最小系统……………………………………………………………………...................................2
3.2键盘接口电路……………………………………………………………………2
3.3LCD显示电路………………………………………..……………….…………3
3.4按键监视电路…………………………………………………………..………4
四、系统软件设计………………………………………………………………………………………………..4
仿真演示……………………………………………………………..………………14
五、心得体会...............................................................................................................1
一、设计和性能指标
1.1设计任务
编写程序并将程序下载到51单片机的开发板上实现加、减、剩和除法运算和时钟显示并用1602液晶显示器显示出来。
1.2性能指标
1.能实现八位的整数加、减、剩和除法运算。
2.有清零功能。
3.可以实现连续的整数加、减、剩、除运算。
4.可以通过按键实现计算器与时钟之间的切换。
5.时钟可以通过设置键设置时间。
6.在用计算器的同时时钟也在同时运行,使时间不会错误。
7.按键按下可以发出按键声。
二、设计方案
按照系统设计的功能的要求,初步确定设计系统由主控模块、监测模块、显示模块、键扫描接口电路共四个模块组成。
主控芯片使用51系列AT89C52单片机,采用高性能的静态80C51设计,由先进工艺制造,并带有非易失性Flash程序存储器。
它是一种高性能、低功耗的8位COMS微处理芯片,市场应用最多。
键盘电路采用4*4矩阵键盘电路和4个独立按键。
显示模块采用1602液晶显示器。
整个单片机的接口电路:
P1用于液晶的数据传输和位置传输。
P20,P21,P22,分别用于对1602的控制。
P1用于矩阵按键和独立按键。
P30,P31用于单片机的数据下载。
除以上端口和电源等端口以外其它端口处于空闲状态。
三、系统硬件设计
3.1单片机最小系统
单片机最小系统就是支持主芯片正常工作的最小电路部分,包括主控芯片、复位电路和晶振电路。
主控芯片选取AT89C51芯片,因其具有良好的性能及稳定性,价格便宜应用方便。
晶振选取11.0592MHz,晶振旁电容选取22uF。
3.2键盘接口电路
计算器所需按键有:
数字键:
’1’,’2’,’3’,’4’,’5’,’6’,’7’,’8’,’9’,’0’功能键:
’+’,’-‘,’*’,’/’,’=’,’C(清零)’共十六个
扩展键:
时间的设置键三个和切换键一个共四个。
采用4*4矩阵键盘,和四个独立按键键盘的行和列之间都有公共端相连,四行和四列的8个公共端分别接P0.0~P0.7,这样扫描P0口就可以完成对矩阵键盘的扫描,通过对16个按键进行编码,从而得到键盘的口地址,对比P0口的扫描结果和各按键的地址,我们就可以得到是哪个键按下,从而完成键盘的功能。
3.3LCD显示电路
P1用于液晶的数据传输和位置传输,P20,P21,P22,分别用于对1602的控制。
计算器的液晶显示位置为,0x85~0xff;
3.4按键监视电路
按键监视电路就是在按键时,发出声音提醒,以确保输入数字有效。
这里就采用蜂鸣器作为示音设备。
用p2.5口输出低电平实现蜂鸣。
四、系统软件设计
#include
sbitled=P2^5;
sbitRS=P2^0;
sbitRW=P2^1;
sbitEN=P2^2;
unsignedcharx[8],v3;//计算机变量
inta,b,c,d,e,f,h,i,j,k,n;
unsignedlonginta1,g,m,l;
intv,v1;
charz1=0x30;//时钟变量
intw,w1,q1,q2,q3;
unsignedchars[13];
unsignedcharweikong[]={0xcc,0xcb,0xc9,0xc8,0xc6,0xc5,0x8f,0x89,0x88,0x86,0x86,0x83,0x82};
unsignedcharanjian[]={0xee,0xde,0xbe,0x7e,0xed,0xdd,0xbd,0x7d,0xeb,0xdb,0xbb,0x7b,0xe7,0xd7,0xb7,0x77};//按键扫描数组
voidyanshi(intd)//延时程序
{
inti,j;
for(i=1;ifor(j=1;j<10;j++);
}
voidshuji(unsignedchar*v3)
{
while(*v3!
='\0')
{
RS=1;
EN=1;
P1=*v3;
*v3++;
yanshi(10);
EN=0;
}
}
voidweizhi(unsignedchari)//液晶显示位置
{
RS=0;
EN=1;
P1=i;
yanshi(10);
EN=0;
}
voidshuju(unsignedcharj)//液晶显示数据
{
RS=1;
EN=1;
P1=j;
yanshi(10);
EN=0;
}
voidmain()//主程序
{
abc:
TMOD=0x01;//定义定时器及中断
TH0=0x3c;
TL0=0xb0;
TR0=1;
ET0=1;EA=1;PT0=1;
RW=0;
weizhi(0x01);//液晶清屏
weizhi(0x06);
weizhi(0x0c);
weizhi(0x38);
while
(1)
{
weizhi(0xcc);//液晶的时钟显示数据
shuju(z1+s[0]);
weizhi(0xcb);
shuju(z1+s[1]);
weizhi(0xca);
shuju(0x3a);
weizhi(0xc9);
shuju(z1+s[2]);
weizhi(0xc8);
shuju(z1+s[3]);
weizhi(0xc7);
shuju(0x3a);
weizhi(0xc6);
shuju(z1+s[4]);
weizhi(0xc5);
shuju(z1+s[5]);
weizhi(0x80);
shuju(0x32);
weizhi(0x81);
shuju(0x30);
weizhi(0x82);
shuju(z1+s[12]);
weizhi(0x83);
shuju(z1+s[11]);
weizhi(0x84);
shuju('-');
weizhi(0x85);
shuju(z1+s[10]);
weizhi(0x86);
shuju(z1+s[9]);
weizhi(0x87);
shuju('-');
weizhi(0x88);
shuju(z1+s[8]);
weizhi(0x89);
shuju(z1+s[7]);
weizhi(0x8a);
if(s[6]==0)
shuji("Monday");
if(s[6]==1)
shuji("Tuesday");
if(s[6]==2)
shuji("Wednesday");
if(s[6]==3)
shuji("Thursday");
if(s[6]==4)
shuji("Friday");
if(s[6]==5)
shuji("Saturday");
if(s[6]==6)
shuji("Sunday");
if(P0==0xfd)//时钟设置按键扫描,
{q1++;
while
(1)//死循环,放开按键时跳出,以免多次循环赋值
{
P0=0xff;
yanshi(150);
if(P0==0xff)
break;
}
}
if(P0==0xfb)
{q2++;
while
(1)//死循环,放开按键时跳出,以免多次循环赋值
{
P0=0xff;
yanshi(150);
if(P0==0xff)
break;
}
}
if(P0==0xf7)
{q3++;
while
(1)//死循环,放开按键时跳出,以免多次循环赋值
{
P0=0xff;
yanshi(150);
if(P0==0xff)
break;
}
}
if(q1==1)//判别是否按下设置键
{
for(v=0;v<12;v++)//按下设置键后再判别光标在什么位置
if(v==q2)
{
weizhi(weikong[v]);
shuju(0xfe);
if(q3==1)//时间设置
{
s[v]++;
q3=0;
}
}
}
if(q1==2)
q1=0;
if(q2==14)
q2=0;
P0=0xff;
yanshi(250);
if(P0==0xfe)//判断是否按下切换按键
{
x[0]=0xce;
while
(1)//死循环,在按键放开时跳出
{
P0=0x0f;
if(P0==0x0f)
break;
}
weizhi(0x01);//清屏,进入计算器模式
weizhi(0x06);
weizhi(0x0c);
weizhi(0x38);
while
(1)
{
P0=0xff;
yanshi(300);
if(P0==0xfe)//判断是否按下切换按键
{
while
(1)//死循环,在按键放开时跳回时钟模式
{
P0=0x0f;
if(P0==0x0f)
gotoabc;
}
}
weizhi(0x8f);//计算器显示部分
shuju(0xfe-x[0]);
weizhi(0x8e);
shuju(0xfe-x[1]);
weizhi(0x8d);
shuju(0xfe-x[2]);
weizhi(0x8c);
shuju(0xfe-x[3]);
weizhi(0x8b);
shuju(0xfe-x[4]);
weizhi(0x8a);
shuju(0xfe-x[5]);
weizhi(0x89);
shuju(0xfe-x[6]);
weizhi(0x88);
shuju(0xfe-x[7]);
P0=0x0f;
if(P0!
=0x0f)//按键扫描
yanshi(20);
if(P0!
=0x0f)
{
a=P0;
P0=0xf0;
yanshi(10);
b=a|P0;
for(c=0;c<16;c++)
{
if(c<10)//判断按下0~9数字建并给显示变量赋值
{
if(b==anjian[c])
{
k=j;//赋值部分
j=i;
i=h;
h=f;
f=e;
e=d;
d=n;
n=c;
x[0]=0xce-n;
x[1]=0xce-d;
x[2]=0xce-e;
x[3]=0xce-f;
x[4]=0xce-h;
x[5]=0xce-i;
x[6]=0xce-j;
x[7]=0xce-k;
}
}
if(c>11)//判断加减剩除
{
if(b==anjian[c])
{
a1=c-11;
if(a1==1)
{
weizhi(0x85);
shuju('+');
}
if(a1==2)
{
weizhi(0x85);
shuju('-');
}
if(a1==3)
{
weizhi(0x85);
shuju('*');
}
if(a1==4)
{
weizhi(0x85);
shuju('/');
}
g=n+d*10+e*100+f*1000+h*10000+i*100000+j*1000000+k*10000000;//将加数或除数或减数或剩数的值保存
x[0]=0;
x[1]=0;
x[2]=0;
x[3]=0;
x[4]=0;
x[5]=0;
x[6]=0;
x[7]=0;
d=0;
e=0;
f=0;
h=0;
i=0;
j=0;
k=0;
n=0;
}
}
if(c==11&&b==anjian[11])//判断按下‘=’键
{
m=n+d*10+e*100+f*1000+h*10000+i*100000+j*1000000+k*10000000;//将被除数或被减数或被加数或被剩数的值保存
if(a1==1)//判断是做的加或减或剩或除并做相应的计算
l=g+m;
if(a1==2)
l=g-m;
if(a1==3)
l=g*m;
if(a1==4)
l=g/m;
x[0]=0xce-l%10;//将计算出来的值一一的显示出来
x[1]=0xce-l%100/10;
x[2]=0xce-l%1000/100;
x[3]=0xce-l%10000/1000;
x[4]=0xce-l%100000/10000;
x[5]=0xce-l%1000000/100000;
x[6]=0xce-l%10000000/1000000;
x[7]=0xce-l%100000000/10000000;
d=l%10;
d=l%100/10;
e=l%1000/100;
f=l%10000/1000;
h=l%100000/10000;
i=l%1000000/100000;
j=l%10000000/1000000;
k=l%100000000/10000000;
weizhi(0x85);//将显示的符号清屏
shuju(0xfe);
}
if(c==10&&b==anjian[c])//判断按下清零键并清零
{
x[0]=0xce;
x[1]=0;
x[2]=0;
x[3]=0;
x[4]=0;
x[5]=0;
x[6]=0;
x[7]=0;
d=0;
e=0;
f=0;
h=0;
i=0;
j=0;
k=0;
n=0;
l=0;
g=0;
m=0;
weizhi(0x85);
shuju(0xfe);
}
}
v1=0;
for(v=7;v>0;v--)//将最高位后前的零清屏
{
if(x[v]==0xce)
v1++;
if(x[v]!
=0xce)
break;
}
for(v=7,v1;v1>0;v--,v1--)
x[v]=0;
while
(1)//死循环,按键放开时跳出,以免多次做数学计算;
{
led=0;//led为按键声音控制,给与低电瓶,按键按下时峰吟
P0=0x0f;
if(P0==0x0f)
break;
}
led=1;
}
}
}
}
}
voidINT0ISQ()interrupt1//定时器中断
{
TH0=0x3c;
TL0=0xb0;
w++;
if(w==20)//秒十分的自加进位及置零判断
{
w=0;
s[0]++;
}
if(s[0]==10)
{
s[1]++;
s[0]=0;
}
if(s[1]==6)
{
s[2]++;
s[1]=0;
}
if(s[2]==10)
{
s[3]++;
s[2]=0;
}
if(s[3]==6)
{
s[4]++;
s[3]=0;
}
if(s[4]==10)
{
s[5]++;
s[4]=0;
}
if(s[4]==4&&s[5]==2)//星期,年,月,日,的进位判断
{
s[4]=0;
s[5]=0;
s[6]++;
s[7]++;
}
if(s[6]==8)
s[6]=0;
if(s[7]==10)
{
s[8]++;
s[7]=0;
}
if(s[7]==1&&s[8]==3)
{
s[9]++;
s[7]=1;
s[8]=0;
}
if(s[11]==10)
{
s[10]++;
s[9]=0;
}
if(s[9]==3&&s[10]==1)
{
s[11]++;
s[9]=1;
s[10]=0;
}
if(s[11]==10)
{
s[12]++;
s[11]=0;
}
}
五、仿真图演示
1、整体布局
2、实现加减剩除运算
(1)加运算(12+12=24)
(2)减运算(1367885-56791=1311094)
(3)剩运算(1326*237=314262)
(4)除运算(314262/1326=237)
3、时钟与计算器的切换
切换前切换后
4、时钟的设置
设置前设置后
六、心得体会
通过本次课程设计对AT89C51单片机更加的了解了,提升了自己对程序的编写及修改能力,提升了自己的团队协作能力。