之前看到网上利用51和12864做计算器的资源比较少,找了很久才找到了一个帖子是用12864做的计算器,于是下载下来后做了一定程度的改进,于是想分享出来让更多吧友看到,也欢迎各位留言评论,咱们一起学习,个人的思想还是很狭隘的,一个人想问题时思绪容易走进死胡同出不来,希望各位吧友指出不足和改进意见。附件是仿真和程序,用keil5写的,keil4可能打不开哦(反正我用keil4打不开的),仿真也是protues8.6做的,低版本也可能打不开。
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- #include<reg52.h>
- #include<array.h>
- #include<stdio.h>
- #include<string.h>
- #define uint unsigned int
- #define uchar unsigned char
- sbit E=P2^0;
- sbit RW=P2^1;
- sbit RS=P2^2;
- sbit CS2=P2^3;
- sbit CS1=P2^4;
- sbit RST=P2^5;
- sbit BEEP=P2^6;
- uchar hang,lie; //行,列
- float dat1,dat2,count; //运算值
- uchar keynum; //按键返回值(0~17)
- uchar x; //按键所对应的字符在字符表中的行号
- uchar keyfun; //运算方式选择(1:*, 2:+, 3:-, 4:/)
- void delay(uchar i) //延迟10*n微秒
- {
- while(i--);
- }
- void delay_ms(uchar n) //延迟n毫秒
- {
- uchar i,j;
- for(i=n;n>0;n--)
- for(j=120;j>0;j--);
- }
- /********************************************************/
- /*********************检测工作状态***********************/
- //void checkbusy(void)
- //{
- // unsigned int timeout = 0;
- // E = 0;
- // RS = 0;
- // RW = 1;
- // E = 1;
- // while((P0 & 0x80)&& ++timeout != 0);//忙状态检测,等待超时时间为60ms
- // E = 0;
- //}
- /********************************************************/
- /************************写命令**************************/
- void write_cmd(uchar cmd)
- {
- // checkbusy();
- RS=0;
- RW=0;
- E=1;
- P0=cmd;
- delay(20);
- E=0;
- }
- /****************************************************/
- /***********************写数据***********************/
- void write_dat(uchar dat)
- {
- // checkbusy();
- RS=1;
- RW=0;
- E=1;
- P0=dat;
- delay(20);
- E=0;
- }
- /****************************************************/
- /*********************设置页与列*********************/
- void set(uchar page,uchar col)
- {
- page=page|0xb8; //页的首地址为0xb8
- col=col|0x40; //列的首地址为0x40
- write_cmd(col);
- write_cmd(page);
- }
- /****************************************************/
- /*******************选择左、右屏*********************/
- void Select_Screen(uchar swich)
- {
- switch(swich)
- {
- case 0:CS1=CS2=0;break; //全屏
- case 1:CS1=0;CS2=1;break; //左屏
- case 2:CS1=1;CS2=0;break; //右屏
- default:break;
- }
- }
- /***************************************************/
- /********************LCD初始化**********************/
- void Lcd_Init()
- {
- uchar i,j,k=0;
- RST=0;
- delay(10);
- RST=1;
- write_cmd(0xc0);//设置显示起始行11xxxxxx
- write_cmd(0x3f);//0x3f显示开,0x3e显示关
- Select_Screen(0);
- set(0,0);
- for(i=0;i<8;i++)
- {
- for(j=0;j<64;j++)
- write_dat(0x00);
- k++;
- set(k,0);
- }
- lie=2;hang=3;keyfun=0;
- dat1=0.0,dat2=0.0,count=0.0;
- }
- /*****************************************************/
- /********************计算窗口清空*********************/
- void Clear_jisuan()
- {
- uchar i,j;
- Select_Screen(0);
- for(i=3;i<6;i++) //从第三页开始写入数据0x00,清空计算窗口
- {
- for(j=0;j<64;j++)
- {
- set(i,j);
- write_dat(0x00);
- }
- }
- lie=2;hang=3;keyfun=0;
- dat1=0.0,dat2=0.0,count=0.0;
- }
- /**************************************************/
- /********************显示字符**********************/
- void Display_zifu(uchar n)
- {
- uchar i; //列数小于64时
- if(lie<64)
- {
- Select_Screen(1); //开左屏
- set(hang,lie); //设置行,列
- for(i=0;i<6;i++)
- write_dat(zifu[n++]); //写入数据
- lie=lie+7; //每输出一个字符列数加6
- if(hang>7) //行数大于7时回到初始值
- hang=3;
- }
- else //列数大于64时
- {
- Select_Screen(2);
- set(hang,lie-64);
- for(i=0;i<6;i++)
- write_dat(zifu[n++]);
- lie=lie+7;
- if(lie>123)
- {
- lie=0;hang++;
- Select_Screen(1);
- }
- if(hang>7)
- hang=3;
- }
- }
- /******************************************************/
- /***********将运算结果转化为字符串而后显示*************/
- void Display_string(uchar page,uchar col,float num)
- {
- uchar str[20];
- uchar tmp[16],i,j,k,c;
- int len;
- if((int)num==(int)(num+0.99999))//如果为整数
- {
- sprintf(str,"%d",(int)num); //将结果转化为字符串
- len=sprintf(str,"%d",(int)num); //sprintf函数的返回值为字符串的长度,不含'/0'
- }
- else //如果为小数
- {
- sprintf(str,"%.3f",num); //将结果转化为字符串
- len=sprintf(str,"%.3f",num);
- }
-
- if(col>63) //列数大于63开右屏
- {
- Select_Screen(2);
- col=col-64;
- }
-
- for(i=0;i<len;i++) //将字符串逐个显示
- {
- if(col<63) //列数小于63开左屏
- {Select_Screen(1);}
- c=(str[i]-42)*6; //数组第一行*号的ASCII值为42,每个数组中的相应元素减去42得到其在数组中的行数
- for(j=0;j<10;j++)
- {tmp[j]=zifu[c];} //将数组zifu相应字符的ASCII码输送给数组tmp
- set(page,col);
- for(k=0;k<6;k++)
- write_dat(zifu[c++]); //写入数据
-
- col=col+6; //每写一个字符列数加6,继续写入下一个字符
- delay(100);
- }
- }
- /*****************************************************/
- /***********************显示汉字**********************/
- void Display_Project(uchar screen,uchar page,uchar col,uchar n,uchar table[][32])
- {
- uchar i,temp[32];
- for(i=0;i<16;i++) //将table数组中的相应汉字的ascii码输送给数组temp
- temp[i]=table[n][i];
- for(i=16;i<32;i++)
- temp[i]=table[n][i];
-
- Select_Screen(screen);
- set(page,col);
- for(i=0;i<16;i++) //写汉字的上半部分
- write_dat(temp[i]);
-
- set(page+1,col);
- for(i=0;i<16;i++) //写汉字的下半部分
- write_dat(temp[i+16]);
- }
- /***********************************************************/
- /******************** 响铃 *********************************/
- //void play()
- //{
- //
- // BEEP=0;
- // delay_ms(1000);
- // BEEP=1;
- //
- //}
- /***********************************************************/
- /********************选择计算类型***************************/
- float calulate()
- {
- switch(keyfun)
- {
- case 1: count=dat2*dat1;dat1=count;break;
- case 2: count=dat2+dat1;dat1=count;break;
- case 3: count=dat2-dat1;dat1=count;break;
- case 4: count=dat2/dat1;dat1=count;break;
- default: break;
- }
- return(count);
- }
- /********************************************************/
- /***********************计算过程*************************/
- void cal_process()
- {
- uchar str_mul[10],len_mul;
- if(x!=19)
- {Display_zifu(x*6);}
- while((P3&0xf0)!=0xf0); //按键按下有效,显示刷新
-
- switch(keynum)
- {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- case 8:
- case 9: dat1=dat1*10+keynum;break; //例如:输入12,初始dat1=0;则dat1=0*10+1=1;dat1=1*10+2=12
- /* * */ case 10:calulate();dat2=dat1;dat1=0;keyfun=1;break;
-
- /* + */ case 11:calulate();dat2=dat1;dat1=0;keyfun=2;break;
-
- /* - */ case 12:calulate();dat2=dat1;dat1=0;keyfun=3;break;
-
- /* / */ case 13:calulate();dat2=dat1;dat1=0;keyfun=4;break;
-
- /* = */ case 14:hang=5;lie=0;Display_zifu(19*6);
- switch(keyfun)
- {
- case 1: count=dat2*dat1;break;
- case 2: count=dat2+dat1;break;
- case 3: count=dat2-dat1;break;
- case 4: count=dat2/dat1;break;
- default:break;
- }
- if(count<999999999)
- {
- if(keyfun==1)
- {
- if((len_mul=sprintf(str_mul,"%d",count))<8) //多位整数乘法若结果大于6则显示?
- Display_string(5,6,count);
- }
- else if(keyfun==4)
- {
- if(dat1!=0) //除数为0则输出?
- Display_string(5,6,count);
- }
- else
- Display_string(5,6,count);
- }
-
- else Display_zifu(20*6);break;
- default: break;
- }
- }
- /********************************************************/
- /*****************矩阵按键扫描(逐行扫描)*****************/
- void keyscan()
- {
- uchar key;
- P3=0xfe; //令第一行为0,判断列
- if(P3!=0Xfe)
- {
- delay(100); //消抖
- if(P3!=0xfe)
- {
- key=P3&0xf0;
- switch(key)
- {
- case 0xe0:keynum=7; x=13;cal_process();break; // 7
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
计算器12864带字.rar
(139.63 KB, 下载次数: 195)
|