/**********413暑假作品*********12864液晶显示屏,结合4*4矩阵键盘,简易计算器*,存储地址:STC-hex2,LCD12864.c*************************************//***功能:1、基本整数的加减乘除;2、有清除功能;3、除法计算,结果保留两位小数;4、分母为0报错********//*********5、小数减大数可显示负号;6、只能做两个数的加减乘除;7、可做10位数的有效运算***********************************//******注意:计算结果要求余显示,比如正确结果123,求余显示321,所以将321逐个赋给某一数组,倒序向12864输出**/#includereg52.h#defineuintunsignedint#defineucharunsignedchar#defineulongunsignedlongsbitrs=P3^7;sbitrw=P3^6;sbite=P3^5;sbitpsb=P3^4;//串并选择,H=串L=并,此程序让12864并行输出bitflag1=0;//数字标记位bitflag11=0;//+标记位bitflag12=0;//—标记位bitflag13=0;//*标记位bitflag14=0;///标记位bitflag15=0;//=标记位bitflag16=0;//清除位bitflag2=0;//负号标记bitflag3=0;//分子小于分母,结果只有两位有效数字时,扩大100倍有两位有效数字bitflag4=0;//分子小于分母,结果只有一位效数字时,扩大100倍有1位有效数字voidinit();//初始化16824子函数voidwrite_com(uchar);//写命令voidwrite_dat(uchar);//写数据,即显示内容voiddisplay1(uchar);//显示字符voiddelete();//清除显示voiddelay(uint);//延时voidkeyscan();//键盘扫描voidscan();//扫描运算符,设定两个数计算voiddisplay_value();//计算结果显示voidvalue();//计算voidbegin();//开机屏幕显示voidmath_error();//数学错误显示ucharcodetable1[]=0123456789.+-*/=;ucharcodetable3[]=welcometo;ucharcodetable4[]=51calculator;ucharcodetable5[]=matherror;longtable2[19];//存储结果的数组,20就出错?longs,a,b,num1;//s为计算结果,a为第一个数,b为第二个数,num1对应为键对应的值为显12864显示服务/***********************************主**函**数***********************************************************/voidmain(){init();delay(5);begin();//开机初始化delay(5);write_com(0x80);//输入数在第一行显示while(1)//大循环使其不断的显示{keyscan();scan();value();display_value();delete();}}/***********初始化********************************/voidinit(){psb=1;//并口传输方式delay(50);//先等待50个毫秒write_com(0x30);//基本操作指令delay(5);write_com(0x0e);//显示状态开/关,08什么也没有;0c无光标;0e有光标但不闪;0f有光标闪烁delay(5);write_com(0x01);//清除显示delay(5);write_com(0x06);//进入点设置delay(5);}/****************写指令***************************/voidwrite_com(ucharcom){rs=0;//表示写命令rw=0;e=0;P0=com;delay(5);e=1;delay(5);e=0;}/*****************写数据***************************/voidwrite_dat(uchardat){rs=1;//表示写数据rw=0;e=0;P0=dat;delay(5);e=1;delay(5);e=0;}/*****************显示字符函数*************************/voiddisplay1(ucharnum1){write_dat(table1[num1]);delay(2);}/*************************************键**盘**扫**描P1口*********************************/voidkeyscan(){uchartemp;/*第一行*/P1=0xfe;//将第一行置为低电平,其余行线置为高电平temp=P1;//读取P3口当前状态赋给临时变量temp,用于后面计算temp=temp&0xf0;//判断第一行是否有按键按下while(temp!=0xf0)//消抖{delay(5);temp=P1;temp=temp&0xf0;while(temp!=0xf0){temp=P1;switch(temp){case0xee:num1=7;flag1=1;//第一个键7break;case0xde:num1=8;flag1=1;;//第二个键8break;case0xbe:num1=9;flag1=1;//第三个键9break;case0x7e:num1=11;flag11=1;//第四个键+break;}while(temp!=0xf0)//等待按键释放{temp=P1;temp=temp&0xf0;}display1(num1);}}/*第二行*/P1=0xfd;temp=P1;temp=temp&0xf0;while(temp!=0xf0){delay(5);temp=P1;temp=temp&0xf0;while(temp!=0xf0){temp=P1;switch(temp){case0xed:num1=4;flag1=1;//4break;case0xdd:num1=5;flag1=1;//5break;case0xbd:num1=6;flag1=1;//6break;case0x7d:num1=12;flag12=1;//-break;}while(temp!=0xf0){temp=P1;temp=temp&0xf0;}display1(num1);}}/*第三行*/P1=0xfb;temp=P1;temp=temp&0xf0;while(temp!=0xf0){delay(5);temp=P1;temp=temp&0xf0;while(temp!=0xf0){temp=P1;switch(temp){case0xeb:num1=1;flag1=1;//1break;case0xdb:num1=2;flag1=1;//2break;case0xbb:num1=3;flag1=1;//3break;case0x7b:num1=13;flag13=1;//*break;}while(temp!=0xf0){temp=P1;temp=temp&0xf0;}display1(num1);}}/*第四行*/P1=0xf7;temp=P1;temp=temp&0xf0;while(temp!=0xf0){delay(5);temp=P1;temp=temp&0xf0;while(temp!=0xf0){temp=P1;switch(temp){case0xe7:num1=15;flag15=1;//=break;case0xd7:num1=0;flag1=1;//0break;case0xb7:flag16=1;//清屏,要把所有标识位给清除break;case0x77:num1=14;flag14=1;///除号break;}while(temp!=0xf0){temp=P1;temp=temp&0xf0;}display1(num1);}}}/**********************************扫描运算符,设定两个数计算*****************8*********************/voidscan(){if(flag15==0)//只有没按等号才能进入{if(flag11||flag12||flag13||flag14){if(flag1==1)//不使运算符对应的num1进入{b=b*10+num1;flag1=0;//b为第二个数,并防止b不断死循环}}if(flag1==1)//a为第一个数{a=a*10+num1;flag1=0;}}}/**********************************************计****算******************************************************************/voidvalue(){if(flag15==0)//只有没按等号才能进入,只要按等号就不会运算,防止死循环{if(flag11==1)//加法{s=a+b;}elseif(flag12==1)//减法{if(a=b)//做减法时,判断两个数大小{s=a-b;}else{s=b-a;flag2=1;//如果ab,flag2是负号标记}}elseif(flag13==1)//乘法{s=a*b;}elseif(flag14==1)//除法{s=(((float)a/b)*100);//s为long,将a/b结果转化为float}}}/****************************************************计算结果显示************************************************/voiddisplay_value(){longn=0,y;if(flag15==1){flag15=0;write_com(0x98);//结果在第四行显示if(s==0)//如果两数相减结果s为0,直接输出0{write_dat('0');}if(flag2==1)//如果小数减大数,先输出一个‘-’,再输出结果{write_dat('-');}if(s!=0){while(s)//求余,将结果赋给数组table2,运算结果为123,但求余赋给数组为321{y=s%10;//求余,s必须为整型,将余数逐个放入数组table2中table2[n]=y;s=s/10;n++;}n--;if(flag14==1)//除法{if(n==1)//分子小于分母,扩大100倍有两位有效数字{flag3=1;}if(n==0)//分子小于分母,扩大100倍有一位有效数字{flag4=1;}if(b==0)//分母为零,输出错误,为什么结果多输出一个/?有待解决{math_error();}}while(n=0)//将数组倒序输出*****************************{delay(2);if(flag3==1)//相除的数小于3位数{flag3=0;write_dat('0');delay(2);write_dat('.');}if((flag4==1)&(b!=0))//相除的数小于2位数,排除分母为0的情况{flag4=0;write_dat('0');d