用Proteus实现计算器功能的实现:实现加(减)功能。
单片机源程序如下:
- #include <reg52.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit rs=P0^0;
- sbit rw=P0^1;
- sbit e=P0^2;
- sbit k0=P1^0;
- sbit k1=P1^1;
- sbit k2=P1^2;
- sbit k3=P1^3;
- sbit k4=P1^4;
- sbit k5=P1^5;
- sbit k6=P1^6;
- sbit k7=P1^7;
- unsigned char code digit[ ]={"0123456789"}; //定义字符数组显示数字
- unsigned char s,m,h,day,month,year,count;
- void write_dat(uchar dat);
- void write_com(uchar com);
- void keyscan();
- /**********************
- 功能说明:
- 显示编码,加上0x30,
- 分别为'1','2','3','+',
- '4','5','6','-',等
- **********************/
- uchar code table1[]=
- {
- 1,2,3,0x2b-0x30,
- 4,5,6,0x2d-0x30,
- 7,8,9,0x2a-0x30,
- 0,0x3d-0x30,0x01-0x30,0x2f-0x30
- };
- uchar k=0,flag=0,num,fuhao,i;
- long a,b,c;
- void delay(uint z)
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=110;y>0;y--);
- }
- /*****************************************************
- 函数功能:指定字符显示的实际地址
- 入口参数:x
- ***************************************************/
- void WriteAddress(unsigned char x)
- {
- write_com(x|0x80); //显示位置的确定方法规定为"80H+地址码x"
- }
- /******************************************************************************
- 函数功能:显示小时
- ******************************************************************************/
- void DisplayHour()
- {
- unsigned char i,j;
- i=h/10; //取整运算,求得十位数字
- j=h%10; //取余运算,求得各位数字
- WriteAddress(0x45); //写显示地址,将十位数字显示在第2行第0列
- write_dat(digit[i]); //将十位数字的字符常量写入LCD
- write_dat(digit[j]); //将个位数字的字符常量写入LCD
-
- }
- /******************************************************************************
- 函数功能:显示分钟
- ******************************************************************************/
- void DisplayMinute()
- {
- unsigned char i,j;
- i=m/10; //取整运算,求得十位数字
- j=m%10; //取余运算,求得各位数字
- WriteAddress(0x48); //写显示地址,将十位数字显示在第2行第3列
- write_dat(digit[i]); //将十位数字的字符常量写入LCD
- write_dat(digit[j]); //将个位数字的字符常量写入LCD
-
- }
- /******************************************************************************
- 函数功能:显示秒
- ******************************************************************************/
- void DisplaySecond()
- {
- unsigned char i,j;
- i=s/10; //取整运算,求得十位数字
- j=s%10; //取余运算,求得各位数字
- WriteAddress(0x4b); //写显示地址,将十位数字显示在第2行第6列
- write_dat(digit[i]); //将十位数字的字符常量写入LCD
- write_dat(digit[j]); //将个位数字的字符常量写入LCD
- }
- /******************************************************************************
- 函数功能:显示小时
- ******************************************************************************/
- void DisplayYear()
- {
- unsigned char i,j;
- i=year/10; //取整运算,求得十位数字
- j=year%10; //取余运算,求得各位数字
- WriteAddress(0x07); //写显示地址,将十位数字显示在第2行第0列
- write_dat(digit[i]); //将十位数字的字符常量写入LCD
- write_dat(digit[j]); //将个位数字的字符常量写入LCD
-
- }
- /******************************************************************************
- 函数功能:显示分钟
- ******************************************************************************/
- void DisplayMonth()
- {
- unsigned char i,j;
- i=month/10; //取整运算,求得十位数字
- j=month%10; //取余运算,求得各位数字
- WriteAddress(0x0a); //写显示地址,将十位数字显示在第2行第3列
- write_dat(digit[i]); //将十位数字的字符常量写入LCD
- write_dat(digit[j]); //将个位数字的字符常量写入LCD
-
- }
- /******************************************************************************
- 函数功能:显示秒
- ******************************************************************************/
- void DisplayDay()
- {
- unsigned char i,j;
- i=day/10; //取整运算,求得十位数字
- j=day%10; //取余运算,求得各位数字
- WriteAddress(0x0d); //写显示地址,将十位数字显示在第2行第6列
- write_dat(digit[i]); //将十位数字的字符常量写入LCD
- write_dat(digit[j]); //将个位数字的字符常量写入LCD
- }
- void keyscan2()
- {if(k0==0)
- {delay(5);
- if(k0==0)
- {
- s++;
- if(s==60)
- s=0;
- }
- }
- if(k1==0)
- {delay(5);
- if(k1==0)
- {m++;
- if(m==60)
- m=0;
- }
- }
- if(k2==0)
- {delay(5);
- if(k2==0)
- {h++;
- if(h==60)
- h=0;
- }
- }
-
- if(k3==0)
- {delay(5);
- if(k3==0)
- {day++;
- if(day==30)
- day=0;
- }
- }
- if(k4==0)
- {delay(5);
- if(k4==0)
- {month++;
- if(month==13)
- month=0;
- }
- }
- if(k5==0)
- {delay(5);
- if(k5==0)
- {year++;
- if(year==99)
- year=0;
- }
- }
- }
-
- void keyscan()
- {
- uchar temp;
- P3=0xfe;
- temp=P3;
- temp=temp&0xf0;
- while(temp!=0xf0)
- {
- delay(5);
- temp=P3;
- temp=temp&0xf0;
- while(temp!=0xf0)
- {
- temp=P3;
- switch(temp)
- {
- case 0xee:num=0;
- break;
- case 0xde:num=1;
- break;
- case 0xbe:num=2;
- break;
- case 0x7e:num=3;
- break;
- }
- while(temp!=0xf0)
- { temp=P3;
- temp=temp&0xf0;
- }
- }
- /*当按下1,2,3,松手后执行下面这段语句*/
- if(num==0||num==1||num==2)
- {
-
- if(flag==0)
- a=a*10+table1[num];//如果没有按符号键,符号前的数值为a
- else if(flag==1)
- b=b*10+table1[num]; //如果按了符号键,符号后的数值为b
-
- if(k==1) //如果之前按了'='号,再按键时清屏,进行下一次计算
- {
- k=0;
- write_com(0x01);
- }
- }
- else if(num==3) //判断按下'+'
- {
- flag=1;
- fuhao=1;
- }
-
- i=table1[num]; //显示按下的键
- write_dat(0x30+i);
-
- }
- P3=0xfd;
- temp=P3;
- temp=temp&0xf0;
- while(temp!=0xf0)
- {
- delay(5);
- temp=P3;
- temp=temp&0xf0;
- while(temp!=0xf0)
- {
- temp=P3;
- switch(temp)
- {
- case 0xed:num=4;
- break;
- case 0xdd:num=5;
- break;
- case 0xbd:num=6;
- break;
- case 0x7d:num=7;
- break;
- }
- while(temp!=0xf0)
- { temp=P3;
- temp=temp&0xf0;
- }
- }
- if(num==4||num==5||num==6) //判断是否按下'4','5','6'
- {
- if(k==1)
- {
- k=0;
- write_com(0x01);
- }
- if(flag==0)
- a=a*10+table1[num];
- else if(flag==1)
- b=b*10+table1[num];
- }
- else if(num==7)
- {
- flag=1;
- fuhao=2;
- }
- i=table1[num]; //显示按下的键
- write_dat(0x30+i);
- }
- P3=0xfb;
- temp=P3;
- temp=temp&0xf0;
- while(temp!=0xf0)
- {
- delay(5);
- temp=P3;
- temp=temp&0xf0;
- while(temp!=0xf0)
- {
- temp=P3;
- switch(temp) //
- {
- case 0xeb:num=8;
- break;
- case 0xdb:num=9;
- break;
- case 0xbb:num=10;
- break;
- case 0x7b:num=11;
- break;
- }
- while(temp!=0xf0)
- { temp=P3;
- temp=temp&0xf0;
- }
- }
- if(num==8||num==9||num==10) //判断是否按下'7','8','9'
- {
- if(k==1)
- {
- k=0;
- write_com(0x01);
- }
- if(flag==0)
- a=a*10+table1[num];
- else if(flag==1)
- b=b*10+table1[num];
-
- }
- else if(num==11) //判断是否按下'*'
- {
- flag=1;
- fuhao=3;
-
- }
- i=table1[num];
- write_dat(0x30+i);
-
- }
- P3=0xf7;
- temp=P3;
- temp=temp&0xf0;
- while(temp!=0xf0)
- {
- delay(5);
- temp=P3;
- temp=temp&0xf0;
- while(temp!=0xf0)
- {
- temp=P3;
- switch(temp)
- {
- case 0xe7:num=12; // 0键
- break;
- case 0xd7:num=13; // '='
- break;
- case 0xb7:num=14; //清零键
- break;
- case 0x77:num=15; //'/'
- break;
- }
- while(temp!=0xf0)
- { temp=P3;
- temp=temp&0xf0;
- }
- }
- switch(num)
- {
- case 12:
- {
- if(k==1)
- {
- k=0;
- write_com(0x01);
- }
- if(flag==0)
- a=a*10;
- else if(flag==1)
- b=b*10;
- write_dat(0x30);
- }
- break;
- case 13: //按=键
- {
- k=1;
- if(fuhao==1) //如果符号键是+,执行+运算
- {
-
- write_com(0x80+0x4f);
- write_com(0x04);
- c=a+b;
- while(c!=0)
- {
- write_dat(0x30+c%10);
- c=c/10;
-
-
- }
- write_dat(0x3d);
- fuhao=0;
- a=0;b=0;flag=0;
- }
- if(fuhao==2)
- {
- write_com(0x80+0x4f);
- write_com(0x04);
- if(a>=b)
- {
- c=a-b;
- while(c!=0)
- {
- write_dat(0x30+c%10);
- c=c/10;
- }
-
- }
- else if(a<b)
- {
- c=b-a;
- while(c!=0)
- {
- write_dat(0x30+c%10);
- c=c/10;
- }
- write_dat(0x2d);
- }
-
- write_dat(0x3d);
- a=0;b=0;flag=0;fuhao=0;
-
- }
- if(fuhao==3) //如果符号键是*
- {
- write_com(0x80+0x4f);
- write_com(0x04);
- c=a*b;
- while(c!=0)
- {
- write_dat(0x30+c%10);
- c=c/10;
- }
- write_dat(0x3d);
- a=0;b=0;flag=0;fuhao=0;
-
- }
- if(fuhao==4) //如果符号键是/
- {
- i=0;
- write_com(0x80+0x4f);
- write_com(0x04);
- c=(long)(((float)a/b)*1000000); //结果保留6位小数
- while(c!=0)
- {
- write_dat(0x30+c%10);
- c=c/10;
- i++;
- if(i==6) // 显示完六位小数后,显示·
- write_dat(0x2e);
- }
- if(a/b<=0)
- write_dat(0x30);
- write_dat(0x3d);
- a=0;b=0;flag=0;fuhao=0;
- }
- }
- break;
- case 14:
- { write_com(0x01);
- a=0;b=0;flag=0;fuhao=0;
- }
- break;
- case 15:
- {
- flag=1;
- fuhao=4;
- write_dat(0x30+table1[num]);
-
- }
- break;
-
- }
-
- }
-
- }
- /*******led1602*******/
- void write_com(uchar com)
- {
- rs=0;//选择写指令
- rw=0;
- P2=com;
- e=1;
- delay(5);//无延时不能正常工作
- e=0;
- }
- void write_dat(uchar dat)
- {
- rs=1;//选择写数据
- rw=0;
- P2=dat;
- e=1;
- delay(5);//无延时不能正常工作
- e=0;
- }
- void init() //初始化
- {
- delay(15);
- write_com(0x38);
- delay(6);
- write_com(0x38);
- delay(6);
- write_com(0x38);
- write_com(0x38);
- write_com(0x0c); //开显示,关光标
- write_com(0x06);//光标移动 设置
- write_com(0x01);//清屏
-
- }
- void geshi()
- {
- WriteAddress(0x00);
- write_dat('D');
- WriteAddress(0x01);
- write_dat('a');
- WriteAddress(0x02);
- write_dat('t'); //将分号的字符常量写入LCD
- WriteAddress(0x03);
- write_dat('e');
- WriteAddress(0x04);
- write_dat(':');
- WriteAddress(0x05);
- write_dat('2');
- WriteAddress(0x06);
- write_dat('0');
- WriteAddress(0x09);
- write_dat('-');
- WriteAddress(0x0c);
- write_dat('-');
- WriteAddress(0x40);
- write_dat('T');
- WriteAddress(0x41);
- write_dat('i');
- WriteAddress(0x42);
- write_dat('m');
- WriteAddress(0x43); //写地址,将第二个分号显示在第2行第7列
- write_dat('e'); //将分号的字符常量写入LCD
- WriteAddress(0x44); //写地址,将第二个分号显示在第2行第10列
- write_dat(':'); //将分号的字符常量写入LCD
- WriteAddress(0x47);
- write_dat(':');
- WriteAddress(0x4a);
- write_dat(':');
- }
-
- void main()
- {
-
-
- init();
- TMOD=0x01; //使用定时器T0的模式1
- TH0=(65536-46083)/256; //定时器T0的高8位设置初值
- TL0=(65536-46083)%256; //定时器T0的低8位设置初值
- EA=1; //开总中断
- ET0=1; //定时器T0中断允许
- TR0=1; //启动定时器T0
- count=0; //中断次数初始化为0
- s=0; //秒初始化为0
- m=0; //分钟初始化为0
- h=0; //小时初始化为0
- year=0;
- month=0;
- day=0;
- while(1)
- {
- keyscan();
- if(k6==0)
- { k6=0;
- write_com(0x01);
- while(1)
- {
- keyscan2();
- geshi();
- delay(5);
- DisplayHour();
- delay(5);
- DisplayMinute();
- delay(5);
- DisplaySecond();
- delay(5);
- DisplayYear();
- delay(5);
- DisplayMonth();
- delay(5);
- DisplayDay();
- delay(5);
- if(k7==0)
- {
- k6=1;
- write_com(0x01);
- break;
- }
-
- }
-
- }
-
- }
-
- }
- /*******************************************************
- 函数功能:定时器T0的中断服务函数
- ********************************************************/
- void Time0(void ) interrupt 1 using 1 //定时器T0的中断编号为1,使用第1组工作寄存器
- {
- count++; //每产生1次中断,中断累计次数加1
- if(count==20) //如果中断次数计满20次
- {
- count=0; //中断累计次数清0
- s++; //秒加1
- if(s==60) //如果计满60秒
- {
- s=0; //秒清0
- m++; //分钟加1
- }
- if(m==60) //如果计满60分
- {
- m=0; //分钟清0
- h++; //小时加1
- }
-
- if(h==24)
- {
- h=0;
- day++;
- }
- if(day==30)
- {
- day=0;
- month++;
- }
- if(month==13)
- { month=0;
- year++;
- }
- if(year==99)
- {
- year=0;
- }
- TH0=(65536-46083)/256; //定时器T0高8位重新赋初值
- TL0=(65536-46083)%256; //定时器T0低8位重新赋初值
- }
- }
复制代码
所有资料51hei提供下载:
计算器.rar
(3.28 KB, 下载次数: 13)
|