51计算器篇

基于51最小系统计算机制作

一、设计目标

1. 矩阵按键控制的LCD显示计算器

附带 加、减、乘、除和复位以及报错功能;

除法运算结果显示包括三位小数;

2. 计数器(定时器实现)

3. DXP布线

二、硬件要求

51单片机最小系统

矩阵按键

LCD液晶显示屏

三、软件设计

(1)程序框图

(2)根据要求写出51程序

四、设计思路与原理分析

设计思路:

按键赋值,给每个按键赋予一种特定的功能(例如代表数字1、2、3或者+、-、*、/)

通过安检扫描识别被按下的按键,并给出相应的反馈(即键值);

配置LED,初始化,忙检测;

设计原理:

(1)按键检测(移位检测)

 

 

 

 

按键检测

uchar code key[]={0xef,0xdf,0xbf,0x7f}; //行检测

uchar code key1[]={0x7f,0xbf,0xdf,0xef};//列检测

uchar i,j,temp;

for(i=0;i<4;i++)

     {   

P1=key[i]; //高四位一次置低电平

temp=P1;  

temp=temp<<4|0x0f;

for(j=0;j<4;j++) //一次检测按键按下使得那一列置低电平

{    

if(key1[j]==temp)  

{    

number=i*4+j;//按键位置计算

}

}

}

 

 

 

(2)LCD初始化以及相关命令操作

     ①LCD管脚说明

          

 

 

 

 ②LCD初始化时序

 

 

 

 

 

 

 

 

 

 

③初始化设置

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

④读写操作时序

 

 

 

 

 

 

 

 

 

⑤忙检测

 

 

 

 

 

 

 

 

 

 

 

 

 

⑥其余相关命令设置

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

五、程序框图

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

六、测试程序

/********************************************************

*********矩阵按键完成基本计算器功能同时兼有报错功能*****

********************************************************/

#include <reg52.h>

#include <intrins.h>

#define uchar unsigned char

#define uint unsigned int

#define ulong unsigned long

#define P 0x80 //用于忙检测

 

sbit rs=P2^6;// 1602

sbit rw=P2^5;// 使能

sbit e=P2^7;// 控制端

 

uchar code tab1[]={'c',0,'=','+',1,2,3,'-',4,5,6,'*',7,8,9,'/'};//按键对应键值

uchar code table[]="   error!!!       ";

 

uint flag0=0; // = 标志位

uint flag1=0; // +

uint flag2=0;//  -

uint flag3=0;//  *

uint flag4=0; // /

uint fuhao=0; // 负号

uint point=0; //小数点

 

uchar T=0;  //报错标志位

ulong a=0,b=0;//储存键值变量

uchar number;//按键标号

uchar code key[]={0xef,0xdf,0xbf,0x7f};//行检测

uchar code key1[]={0x7f,0xbf,0xdf,0xef};//列检测

 

void delay(uint z) //延时函数

{

uint x,y;

for(x=z;x>0;x--)  

for(y=115;y>0;y--);

}

 

uchar busy()  //忙检测

{

rs=0;

rw=1;

e=1;  

delay(1);

while(P0&P);  //判断数据位高位是否为0(允许)

e=0;

return P0;

}

 

void wdat(uchar dat) //写数据函数

{  

P0=dat;

busy();

rs=1;

rw=0;

delay(5);

e=1;

delay(5);

e=0;

}

 

void wcmd(uchar cmd,uchar Q) //写命令Q决定是否需要检测忙

{

P0=cmd;

if(Q)

busy();

rs=0;

rw=0;

delay(5);

e=1;  

delay(5);

e=0;

}

 

void init() //

{  

  e=0;  

wcmd(0x38,0);//2*16 显示5*7 8位数据显示

wcmd(0x38,0);

wcmd(0x38,0);

wcmd(0x38,1);  

wcmd(0x01,1); //清屏

wcmd(0x06,1); //地址加一

wcmd(0x0c,1); //开显示屏 无光标

  wcmd(0x01,1); //清屏

}

 

void ankey() //按键输入反馈

{  

uchar i,j,temp;

  uchar w;

for(i=0;i<4;i++)

  {   

P1=key[i];

temp=P1;  

temp=temp<<4|0x0f;

for(j=0;j<4;j++)

{    

if(key1[j]==temp)  

{    

number=i*4+j;

switch(number)

{     

 

case0:{wcmd(0x01,1);T=1;flag0=0;flag1=0;flag2=0;flag3=0;

flag4=0;fuhao=0;point=0;a=0;b=0;} break;  复位

   case 2:flag0=1;break; // =

case 3:{flag1=1;wdat(0x2b);}break;//+

case 7:{flag2=1;wdat(0x2d);}break;//

case 11:{flag3=1;wdat(0x2a);}break; //

case 15:{flag4=1;wdat(0x2f);}break; //

case 4://1   

case 5://2

case 6://3

case 8://4  

case 9://5

case 10://6   

case 12://7  

case 13://8

case 14://9

  case 1: //0

if(flag2||flag3||flag4||flag1)//

{

b=b*10+tab1[number]; //            wdat(0x30+tab1[number]);  

{

                      wcmd(0x01,0);

wcmd(0xc0,0);

for(w=0;w<16;w++)

    {

                                     wdat(table[w]);

delay(1);

                                  }

 b=0;

 }

                      }    

else     

{      

if(flag0)     //

{     

flag0=0;    

wcmd(0x01,1);

wdat(0x30 +tab1[number]);

}     

else    

{      

a=a*10+tab1[number];//

wdat(0x30+tab1[number]);

if(a>1000000000)//¾¯½äΪ ±¨´í

{

  wcmd(0x01,0);

  wcmd(0xc0,0);

  for(w=0;w<16;w++)

   {

               wdat(table[w]);

delay(1);

               }

a=0;

   }

}     

}    break;  

default:break;   

}  

 }  

while((key[i]!=P1)&&(key1[j]!=P1))

P1=key[i];

         P1=key1[j];

         delay(3);

    }

}  

}

void keysure()//ÑÓʱÏû¶¶

{

P1=0x0f;

if((P1&0x0f)!=0x0f)

{  

delay(10);

if((P1&0x0f)!=0x0f)

ankey(); //È¡°´¼üÊäÈëÖµnumber

}

}

 

ulong ji_suan()//

 {  

 uchar w=0;

  ulong ans;

  if(flag0==1)//

{

if(flag2||flag3||flag4||flag1)//

{

if(flag1==1)//

{

ans=a+b;

}

if(flag2==1)//

{

if(a>=b)

{

 ans=a-b;

}

else

{

 ans=b-a;

 fuhao=1;//

}  

}

if(flag3==1)//Èç¹û³ËºÅ¼ü°´ÏÂ

{

ans=a*b;

}

if(flag4==1)//

{

ans=(ulong)(((float)a/b)*1000);

point=1;//

 }

 }

 

    }

return ans;

}

void result()//

{   

uchar w;

uchar c=0;

ulong res;//½á¹û

res=ji_suan();//

 if(flag0==1)//

 {

if(res>1000000000)//

 {

 wcmd(0x01,0);

 wcmd(0xc0,0);//

  while(T)//

   {

 for(w=0;w<16;w++)

{

wdat(table[w]);

delay(1);

 }

 delay(500);

 T=0;

 }

 }

 else{

  wcmd(0x04,0);//

wcmd(0xcf,0);//

 do

 {

 wdat(0x30+res%10);

 c++;

 if(c==3&point)

wdat(0x2e);

 res=res/10;

 delay(10);

       }

 while(res);

 if(point&res==0&&c==3)

 wdat(0x30);

 if(point&c<3)

 {

         while(3-c)

 {

           wdat(0x30);

 c++;

         }

 wdat(0x2e);

 wdat(0x30);

        }

 if(fuhao)

           wdat(0x2d);

 wdat(0x3d);

flag1=0;

flag2=0;

flag3=0;

flag4=0;

a=0;

b=0;

 }  

 }  

 }

/*********************************************************************

*************************主函数***************************************

*********************************************************************/

 void main()

 {  

init();//

while(1)

{  

keysure(); //

result();//

}

 }

51计算器程序#include #include #define uchar unsigned char #define uint unsigned int sbit lcden=P3^4; sbit lcdrw=P3^6; sbit lcdrs=P3^5; uchar num,temp,jia=0,cheng=0,chu=0,jian=0,qing=0; uint key,key1,shu; uchar fuhao,flag1,flag=0; uchar table[]={ 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00,}; void delay(uint z) { uint x,y; for(x=z;x>0;x--) for(y=114;y>0;y--); } bit lcd_bz() { bit result; lcdrs = 0; lcdrw= 1; lcden = 1; _nop_(); _nop_(); _nop_(); _nop_(); result=(bit)(P0&0x80;); lcden=0; return result; } void write_com(uchar com) { while(lcd_bz()); lcdrs=0; lcden=0; lcdrw=0; P0=com; delay(5); lcden=1; delay(5); lcden=0; } void write_date(uchar date) { while(lcd_bz()); lcdrs=1; lcden=0; lcdrw=0; P0=date; delay(5); lcden=1; delay(5); lcden=0; } void lcd_init() { lcden=0; write_com(0x38); write_com(0x0c); write_com(0x06); write_com(0x01); } void keyscan() { 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:key=1;num=0;break; case 0xde:key=2;num=0;break; case 0xbe:key=3;num=0;break; case 0x7e:num=1;break; //¼ÓºÅ } while(temp!=0xf0) { temp=P3; temp=temp&0xf0; } } } 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:key=4;num=0;break; case 0xdd:key=5;num=0;break; case 0xbd:key=6;num=0;break; case 0x7d:num=2;break; //¼õºÅ } while( temp!=0xf0) { temp=P3; temp=temp&0xf0; } } } 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:key=7;num=0;break; case 0xdb:key=8;num=0;break; case 0xbb:key=9;num=0;break
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值