完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
基于51单片机的简易计算器
经历了一番学习,成功做出了一个简易的计算器,并且在程序开头加了一个小密码。我用的单片机是STC89C52,单片机类型不同,电路图也是不一样的。 一.设计思路 1.1LCD1602的电路图 该芯片引脚, ***it RS = P3^5; //液晶引脚定义 ***it RW = P3^6; ***it EN = P3^4; # 1.2主函数思路 主函数的思路图: 1.3主函数程序 main() { uchar i,num,sign,s; uchar temp[16]; bit firstflag; float a=0,b=0; Lcd_Init(); DelayMs(10); LcdWrite_cmd(0x01); LcdWrite_string(5,0,"WELCOM !"); LcdWrite_string(3,1,"LI HUA HUI"); for(s=0;s<25;s++) DelayMs(200); LcdWrite_cmd(0x01); mima(); DelayMs(200); LcdWrite_string(0,1," ");//清除该行 LcdWrite_string(0,1,"Right Open!>>>>");//密码正确显示的信息 for(s=0;s<25;s++) DelayMs(200); LcdWrite_cmd(0x01); while(1) { num=KeyPro(); if(num!=0xff) { if(i==0) LcdWrite_cmd(0x01); if(('+'==num) || ('-'==num) || ('*'==num) || ('/'==num) || ('='==num) || (i==16)) { i=0; LcdWrite_char(0,1, num);//应该输入字符,而不是字符串 if(firstflag==0) { sscanf(temp,"%f",&a); firstflag = 1; } else { sscanf(temp,"%f",&b); } for(s=0;s<16;s++) temp if(num!='=') sign=num; else { switch(sign) { case '+': a=a+b; break; case '-': a=a-b; break; case '*': a=a*b; break; case '/': a=a/b; break; default: break; } sprintf(temp,"%g",a); LcdWrite_string(4,1,temp); firstflag = 0; num=0;a=0;b=0;sign=0; for(s=0;s<16;s++) { temp } } } else if(i<16) { if((1==i) && (temp[0]=='0')) { if(num == '.' ) { temp[1]='.'; LcdWrite_char(1,0,num); i++; } else { temp[0]=num; LcdWrite_char(0,0,num);// } } else { temp=num; LcdWrite_char(i,0,num);//输出数据 i++; //输入数值累加 } } } } } 1.3 初始化 void LCD_Busy()//判忙函数 { uchar busy; P0=0Xff; RS=0; RW=1; do { EN=1; busy=P0; EN=0; } while(busy & 0x80); } void LcdWrite_cmd(uchar cmd) { Lcd_Busy(); RS=0; RW=0; P0=cmd; EN=1; EN=0; } void LcdWrite_date(uchar date) { Lcd_Busy(); RS=1; RW=0; EN=1; P0=date; EN=0; } void LcdWrite_char(uchar x,uchar y,uchar date)//写入字符 { Lcd_Busy(); if(y == 0)//=' 就是赋值‘==’ 就是判断数值是否相等 { LcdWrite_cmd(0x80 + x); } else { LcdWrite_cmd(0xC0 + x); } LcdWrite_date(date); } void LcdWrite_string(uchar x,uchar y,uchar *s)//写入字符串 { while(*s) { LcdWrite_char(x,y,*s); s++; x++; } } void DelayMs(int z)// 1ms延时函数 { int x,y; for (x=z;x>0;x--) for(y=110;y>0;y--); } void Lcd_Init()//初始化 { LcdWrite_cmd(0x38); DelayMs(5); LcdWrite_cmd(0x06); DelayMs(5); LcdWrite_cmd(0x0C); LcdWrite_cmd(0x01); } 1.4 键盘扫描 本文采用的是线反转法 uchar KeyScan() { uchar value_h,value_l; P3=0Xf0; if((P3&0xf0)!=0xf0)//判断是否有按键按下 { DelayMs(5); if((P3&0xf0)!=0xf0);//判断按键是否有效 { value_l=P3 & 0Xf0; P3=value_l | 0x0f; value_h=P3 & 0x0f; while( (P3 & 0x0f) != 0x0f );//松手检测 return(value_l+value_h); } } } uchar KeyPro() { switch( KeyScan() ) { //第一行键值码 case 0xee: return '1'; break; case 0xde: return '2'; break; case 0xbe: return '3'; break; case 0x7e: return '+'; break; //第二行键值码 case 0xed: return '4'; break; case 0xdd: return '5'; break; case 0xbd: return '6'; break; case 0x7d: return '-'; break; //第三行键值码 case 0xeb: return '7'; break; case 0xdb: return '8'; break; case 0xbb: return '9'; break; case 0x7b: return '*'; break; //第四行键值码 case 0xe7: return '0'; break; case 0xd7: return '.'; break; case 0xb7: return '='; break; case 0x77: return '/'; break; default:return 0xff;break; } } 1.5 密码程序 unsigned char code password[]={'2','2','3','3','4','4','5','5'}; void mima() { unsigned char num,i,j; unsigned char passwordtemp[16]; //最大输入16个 unsigned char inputtimes; //密码输入错误次数 unsigned char passwordlength,PLEN; //输入密码长度,实际密码长度 bit Flag; PLEN=sizeof(password) / sizeof(password[1]);// //数组占内存总空间,除以单个元素占内存空间大小 Lcd_Init(); //初始化液晶屏 DelayMs(10); //延时用于稳定,可以去掉 LcdWrite_cmd(0x01); ; //清屏 LcdWrite_string(0,0," Welcome! "); //写入第一行信息,主循环中不再更改此信息,所以在while之前写入 LcdWrite_string(0,1,"Input password!"); //写入第二行信息,提示输入密码 while (1) //主循环 { num=KeyPro(); //扫描键盘 if(num!=0xff) //如果扫描是按键有效值则进行处理 { if(i==0) //输入是第一个字符的时候需要把改行清空,方便观看密码 LcdWrite_string(0,1," ");//清除该行 if(i<16) { passwordtemp=num; LcdWrite_char(i,1,'*');//输入的密码用"*"代替 i++; } //i++; //输入数值累加 if(('='==num)|| (i==16))//输入按键值15或者密码输入到最大值16,表示输入结束,需要进行比对 { passwordlength=i-1; //计算输入密码长度 i=0; //计数器复位 if(passwordlength==PLEN)//长度相等则比较,否则直接输出错误 { Flag=1;//先把比较位置1 for(j=0;j } if(Flag==1)break; if(Flag)//如果比较全部相同,标志位置1 { inputtimes=0;//输入正确则次数清零,重新计数 Flag=0; //清除正确标志 } else { LcdWrite_string(0,1," ");//清除该行 LcdWrite_string(0,1,"Wrong! Retry!");//密码错误,提示重新输入 inputtimes++;//连续输入错误,则次数累加 if(inputtimes==3) { LcdWrite_string(0,1," ");//清除该行 LcdWrite_string(0,1,"Wrong 3 times!");//密码错误,提示重新输入 while(1);//停止该位置,重启电源后才能输入,实际实用中则需要等到一定时间后才能再次输入。 } } } } } } 二.成果显示 开机显示,要求输入密码 密码输入,密码比较简单,是12345678 密码输入成功,如果输入错误3次,就不能再输入,只能关机再开机 进入计算界面,并且输入计算的数字 LCD只有两行,第一行输入显示运算的两个数字,功能键显示在第二行的第一个位子,结果从第二行的第二个位子开始显示。 被减数和减号 减数和结果 |
|
|
|
只有小组成员才能发言,加入小组>>
2381 浏览 0 评论
921浏览 2评论
557浏览 1评论
321浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-9-18 11:28 , Processed in 1.263779 second(s), Total 50, Slave 42 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号