《计算器C51源程序.doc》由会员分享,可在线阅读,更多相关《计算器C51源程序.doc(34页珍藏版)》请在三一办公上搜索。
1、#include #define uchar unsigned char#define uint unsigned intsbit rs=P00;sbit rw=P01;sbit e=P02;sbit k0=P10;sbit k1=P11;sbit k2=P12;sbit k3=P13;sbit k4=P14;sbit k5=P15;sbit k6=P16;sbit k7=P17;unsigned char code digit =0123456789; /定义字符数组显示数字unsigned char s,m,h,day,month,year,count;void write_dat(uch
2、ar 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;x0;x-) for(y=110;y0;y-);/*函数功能:指定
3、字符显示的实际地址入口参数: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(digiti); /将十位数字的字符常量写入LCD write_dat(digitj); /将个位数字的字符常量写入LCD
4、 /* 函数功能:显示分钟 */void DisplayMinute() unsigned char i,j; i=m/10; /取整运算,求得十位数字j=m%10; /取余运算,求得各位数字 WriteAddress(0x48); /写显示地址,将十位数字显示在第2行第3列 write_dat(digiti); /将十位数字的字符常量写入LCD write_dat(digitj); /将个位数字的字符常量写入LCD /* 函数功能:显示秒 */void DisplaySecond() unsigned char i,j; i=s/10; /取整运算,求得十位数字j=s%10; /取余运算,求
5、得各位数字 WriteAddress(0x4b); /写显示地址,将十位数字显示在第2行第6列 write_dat(digiti); /将十位数字的字符常量写入LCD write_dat(digitj); /将个位数字的字符常量写入LCD /* 函数功能:显示小时 */void DisplayYear() unsigned char i,j;i=year/10; /取整运算,求得十位数字j=year%10; /取余运算,求得各位数字 WriteAddress(0x07); /写显示地址,将十位数字显示在第2行第0列 write_dat(digiti); /将十位数字的字符常量写入LCD wri
6、te_dat(digitj); /将个位数字的字符常量写入LCD /* 函数功能:显示分钟 */void DisplayMonth() unsigned char i,j; i=month/10; /取整运算,求得十位数字j=month%10; /取余运算,求得各位数字 WriteAddress(0x0a); /写显示地址,将十位数字显示在第2行第3列 write_dat(digiti); /将十位数字的字符常量写入LCD write_dat(digitj); /将个位数字的字符常量写入LCD /* 函数功能:显示秒 */void DisplayDay() unsigned char i,j;
7、 i=day/10; /取整运算,求得十位数字j=day%10; /取余运算,求得各位数字 WriteAddress(0x0d); /写显示地址,将十位数字显示在第2行第6列 write_dat(digiti); /将十位数字的字符常量写入LCD write_dat(digitj); /将个位数字的字符常量写入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+; i
8、f(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(te
9、mp!=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+table1num;/如果没有按符号键,符号前的数值为a else if(flag=1) b=b*10+table1num; /
10、如果按了符号键,符号后的数值为b if(k=1) /如果之前按了=号,再按键时清屏,进行下一次计算 k=0; write_com(0x01); else if(num=3) /判断按下+ flag=1; fuhao=1; i=table1num; /显示按下的键 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
11、; 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+table1num; else if(flag=1) b=b*10+table1num; else if(num=7) flag=1; fuhao=2; i=table1num; /显示按下的键 wr
12、ite_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=
13、9|num=10) /判断是否按下7,8,9 if(k=1) k=0; write_com(0x01); if(flag=0) a=a*10+table1num; else if(flag=1) b=b*10+table1num; else if(num=11) /判断是否按下* flag=1; fuhao=3; i=table1num; 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=
14、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 1
15、3: /按=键 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(ab) c=b-a; whi
16、le(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
17、_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
18、_dat(0x30+table1num); 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);
19、 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(
20、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); /将分号的字符常量写入LCDWriteAdd
21、ress(0x44); /写地址,将第二个分号显示在第2行第10列write_dat(:); /将分号的字符常量写入LCD WriteAddress(0x47); write_dat(:); WriteAddress(0x4a); write_dat(:); void main() init();TMOD=0x01; /使用定时器T0的模式1TH0=(65536-46083)/256; /定时器T0的高8位设置初值TL0=(65536-46083)%256; /定时器T0的低8位设置初值EA=1; /开总中断ET0=1; /定时器T0中断允许TR0=1; /启动定时器T0count=0; /中
22、断次数初始化为0s=0; /秒初始化为0m=0; /分钟初始化为0h=0; /小时初始化为0year=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次中断,中断累计次数