文档库 最新最全的文档下载
当前位置:文档库 › 51单片机矩阵键盘计算器

51单片机矩阵键盘计算器

/**********413暑假作品*********12864液晶显示屏,结合4*4矩阵键盘,简易计算器*,存储地址:STC-hex2 , LCD12864.c *************************************/
/***功能:1、基本整数的加减乘除; 2、有清除功能;3、除法计算,结果保留两位小数;4、分母为0报错********/
/*********5、小数减大数可显示负号;6、只能做两个数的加减乘除;7、可做10位数的有效运算***********************************/
/******注意:计算结果要求余显示,比如正确结果123,求余显示321,所以将321逐个赋给某一数组,倒序向12864输出**/


#include
#define uint unsigned int
#define uchar unsigned char
#define ulong unsigned long

sbit rs=P3^7;
sbit rw=P3^6;
sbit e=P3^5;
sbit psb=P3^4; //串并选择,H=串 L=并,此程序让12864并行输出

bit flag1=0; //数字标记位
bit flag11=0; // +标记位
bit flag12=0; // —标记位
bit flag13=0; // *标记位
bit flag14=0; // /标记位
bit flag15=0; // =标记位
bit flag16=0; //清除位
bit flag2=0; // 负号标记
bit flag3=0; // 分子小于分母,结果只有两位有效数字时,扩大100倍有两位有效数字
bit flag4=0; // 分子小于分母,结果只有一位效数字时,扩大100倍有1位有效数字

void init(); //初始化16824子函数
void write_com(uchar); //写命令
void write_dat(uchar); //写数据,即显示内容
void display1(uchar); //显示字符
void delete(); //清除显示
void delay(uint); //延时
void keyscan(); //键盘扫描
void scan(); //扫描运算符,设定两个数计算
void display_value(); // 计算结果显示
void value(); // 计算
void begin(); //开机屏幕显示
void math_error(); //数学错误显示

uchar code table1[]="0123456789.+-*/=";
uchar code table3[]="welcome to";
uchar code table4[]=" 51 calculator" ;
uchar code table5[]="math error";

long table2[19]; //存储结果的数组,20就出错?
long s,a,b,num1; //s为计算结果,a为第一个数,b为第二个数,num1对应为键对应的值为显12864显示服务
/***********************************主**函**数***********************************************************/
void main()
{
init();
delay(5);
begin(); //开机初始化
delay(5);
write_com(0x80); //输入数在第一行显示
while(1) //大循环使其不断的显示
{
keyscan();
scan();
value();
display_value();
delete();

}
}

/***********初始化********************************/
void init()
{
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);
}
/****************写指令***************************/
void write_com(uchar com)
{
rs=0; //表示写命令
rw=0;
e=0;
P0=com;
delay(5);
e=1;
delay(5);
e=0;
}
/*****************写数据***************************/
void write_dat(uchar dat)
{
rs=1; //表示写数据
rw=0;
e=0;
P0=dat;
delay(5);
e=1;
delay(5);
e=0;
}

/*****************显示字符函数*************************/
void display1(uchar num1)
{
write_dat(table1[num1]);
delay(2);
}

/*************************************键**盘**扫**描 P1口*********************************/
void keyscan()
{ uchar temp;
/*第一行*/
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)
{
case 0xee:num1=7;flag1=1; //第一个键 7
break;
case 0xde:num1=8;flag1=1;; //第二个键 8
break;
case 0xbe:num1=9;flag1=1; //第三个键 9
break;
case 0x7e: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)
{
case 0xed:num1=4;flag1=1; //4
break;
case 0xdd:num1=5;flag1=1; //5
break;
case 0xbd:num1=6;flag1=1; //6
break;
case 0x7d: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)
{
case 0xeb:num1=1;flag1=1; // 1
break;
case 0xdb:num1=2;flag1=1; //2
break;
case 0xbb:num1=3;flag1=1; //3
break;
case 0x7b: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)
{
case 0xe7:num1=15;flag15=1; // =
break;
case 0xd7:num1=0;flag1=1; //0
break;
case 0xb7: flag16=1;//清屏,要把所有标识位给清除
break;
case 0x77:num1=14;flag14=1; // /除号
break;
}
while(temp!=0xf0)
{
temp=P1;
temp=temp&0xf0;
}
display1(num1);
}
}

}

/**********************************扫描运算符,设定两个数计算*****************8*********************/
void scan()
{
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;
}
}
}
/**********************************************计****算******************************************************************/
void value()
{
if(flag15==0) // 只有没按 等号 才能进入,只要按等号就不会运算,防止死循环
{
if(flag11==1) //加法
{ s=a+b; }

else if(flag12==1) //减法
{
if(a>=b) //做减法时,判断两个数大小
{ s=a-b; }
else
{
s=b-a;
flag2=1; //如果a}
}

else if(flag13==1) //乘法
{ s=a*b; }

else if(flag14==1) //除法
{
s=(((float)a/b)*100); //s为long,将a/b结果转化为float
}
}
}

/****************************************************计算结果显示************************************************/
void display_value()
{
long n=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');
delay(2);
write_dat('.');
write_dat('0');
delay(2);
}
write_dat(0x30+table2[n]); //倒序显示结果
n--;

if(flag14==1)
{
if(n==2) //如果按/键,结果保留两位小数
{ write_dat('.'); } }

}
}
}

}
/***************清除显示*****************/
void delete()
{

if(flag16==1)
{
write_com(0x01);
flag1=flag2=flag3=flag4=0;
flag11=flag12=flag13=flag14=flag15=flag16=0;
s=0;
a=0;
b=0;
}
}
/*********开机屏幕显示**********/
void begin()
{
uchar num;
write_com(0x91);
delay(2);
for(num=0;num<11;num++)
{
write_dat(table3[num]);
delay(2);
}
write_com(0x88);
delay(2);
for(num=0;num<14;num++)
{
write_dat(table4[num]);
delay(2);
}
delay(8000);
write_com(0x01);
}
/***********输出数学错误,分母为0******/
void math_error()
{

uchar num;
write_com(0x90);
delay(2);
for(num=0;num<10;num++)
{
write_dat(table5[num]);
delay(2);
}
}
/**************延时***********************************/
void delay(uint x) //毫秒
{
uint i,j;
for(i=x;i>0;i--)
for(j=110;j>0;j--);
}

相关文档
相关文档 最新文档