打印
[51单片机]

LCD液晶显示的51单片机简单计算器

[复制链接]
473|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主

方案

我使用实验室试验箱的2×8矩阵键盘作为的16个按键作为输入分别为0到9、“+”、“-”、“*”、“/”、“=”与复位,由单片机计算并通过LCD显示。


矩阵键盘输入映射与设计原理

系统输入有:0到9、“+”、“-”、“”、“/”、“=”与复位对应矩阵键盘的16个按键。我将矩阵键盘16个按键赋予按键值与并且与实际意义形成映射。


矩阵键盘按键值:


矩阵键盘的输入映射:

矩阵键盘实际上是一个28的矩阵按键,在矩阵键盘中,每条水平线和垂直线在交叉处不直接连通,而是通过一个按键加以连接。这样10个I/O口就可以扫描2*8=16个按键是否按下。

矩阵键盘原理图:

当A端口全部为低电平,D端口的1、2引脚不全为高电平就有按键按下。当确定有按键按下后,A端口的引脚轮流输出低电平,判断D端口的1、2引脚在A端口的哪个引脚为低电平时,D端口的1、2引脚会出现低电平,从而确定哪个按键按下。具体而言,让A端口信从“11111110”到“11111101”……“01111111”循环。D端口的1、2引脚接收两位行信号。A端口八列逐列扫描,当D端口的1、2引脚有一个引脚接收到低电平时便可确定在哪一列,按键按下,再确定D端口第一位为低电平,便可确定哪一列按下。行列结合便可确定哪个按键按下。


软件设计

软件设计思路

程序运行时,首先会判断是否按键按下,若有按键按下确定是哪个按键。并在LCD上显示,按下等号后开始计算,并在LCD上显示结果,并再次判断是否有按键按下,程序循环。若按下复位,程序恢复到初始状态。


软件代码

(1)基本定义部分


#include //C51系列开发头文件

#include //绝对地址访问头文件

#define u8 unsigned char //类型重命名

#define u16 unsigned int //类型重命名

#define keymax 100 //按键缺省值

#define Y1602C_W_CON XBYTE[0xC000] //LCD写命令地址

#define Y1602C_R_CON XBYTE[0xC001] //LCD读忙状态地址

#define Y1602C_W_Data XBYTE[0xC002] //LCD写数据地址

#define Y1602C_R_Data XBYTE[0xC003] //LCD读数据地址

xdata u8 COM_8255 _at_ 0xF003; //8255的控制口

xdata u8 PA_8255 _at_ 0xF000; //8255的PA口

xdata u8 PB_8255 _at_ 0xF001; //8255的PB口

xdata u8 PC_8255 _at_ 0xF002; //8255的PC口

void InitLCD(); //LCD初始化

void DelayXms(u8 X); //毫秒延时

void WR_Con(u8 ConData); //LCD写数据

void WR_Data(u8 wData); //LCD写数据

u8 AllKey(); //检测是否有按键按下

u8 keynum=0; //按键号码

u16 a=0,b=0; //当前数值与转存数值

u8 fuhao=0; //符号标志1:+ 2:- 3:* 4:/


(2)延时函数


void DelayXms(u8 X)

{ u8 i,j;

i = 2*X;

do

{ j = 250;

do

{}while(--j);

}while(--i);

}


(2)LCD相关函数


void WR_Data(u8 WData)

{ Y1602C_W_Data = WData;

while(Y1602C_R_CON & 0x80);

}//LCD写数据子程序


void WR_Con(u8 ConData)

{ Y1602C_W_CON = ConData;

while(Y1602C_R_CON & 0x80);

}//LCD写指令子程序


void InitLCD()

{ DelayXms(5);

WR_Con(0x38); //写指令,5*7点阵,8位CPU接口

WR_Con(0x0C); //设定为整体显示,光标不显示

WR_Con(0x06); //设定光标正向移动

WR_Con(0x01); //清屏

WR_Con(0X80); //显示初始位置

}//LCD初始化


(3)按键与显示相关函数


u8 AllKey()

{ PB_8255 = 0x0; //全"0"->扫描口

return ~PC_8255 & 0x3; //读键状态, 取低二位

}//判断是否有按键按下,返回0无按键按下


u8 keyi()

{

u8 i;

u8 j=keymax; //设置键值为缺省值

if (AllKey()!=0) //判断有无按键按下

{

DelayXms(10);

if (AllKey()!=0) //消抖再判断

{

i = 0xfe; //设置行扫描初值为00000001

j=0; //按键初值为0

while(i!=0xff)

{

PB_8255 = i;

if((PC_8255&0x1)==0)

{ //0行有键闭合

break;

}

else if((PC_8255&0x2)==0)

{ //1行有键闭合

j+=8; //按键值加8

break;

}

j++; //按键值加1

i=((i<<1)|1); //行扫描

}

}

while((AllKey()!=0)); //等待按键松开

}

if(j<10) //为数值

{

WR_Data((j+'0')); //数值转化为对应ASCII码

}

if(j==10)

{

WR_Data('+'); //显示“+”

}   //找元件现货上唯样商城

if(j==11)

{

WR_Data('-'); //显示“-”

}

if(j==12)

{

WR_Data('*'); //显示“*”

}

if(j==13)

{

WR_Data('/'); //显示“/”

}

if(j==14)

{

WR_Data('='); //显示“=”

}

if(j==15)

{

WR_Data(' '); //显示“空”

}

return j;

}//返回按键值并通过LCD显示映射值


(4)运算处理函数


void calculate()

{

u8 i,j,k;

u16 c;

u8 jieguo[10];

if(keynum<10) //数字处理

{

a=10*a+keynum; //原数值*10+现数值

keynum=keymax; //按值设为缺省

}

else if(keynum==10) //按键为“+”号

{

b=a;

a=0;

fuhao=1;

keynum=keymax;

}

else if(keynum==11) //按键为“”号

{

b=a;

a=0;

fuhao=2;

keynum=keymax;

}

else if(keynum==12) //按键为“*”号

{

b=a;

a=0;

fuhao=3;

keynum=keymax;

}

else if(keynum==13) //按键为“/”号

{

b=a;

a=0;

fuhao=4;

keynum=keymax;

}

else if(keynum==14) //按键为“=”号

{

if(fuhao==1) //加法处理

c=b+a;

if(fuhao==2)

{

if(b {

WR_Data('-'); //减法处理考虑负数

c=a-b;

}

else

c=b-a;

}

if(fuhao==3) //乘法处理考虑负数

c=a*b;

if(fuhao==4) //除法处理

(unsigned int)c=b/a;

if(c==0) //得数为0特殊处理

WR_Data('0');

else

{

for(i=0;c>0;i++) //得数显示

{

j=c%10;

c=c/10;

jieguo=j;

}

k=i;

for(j=0,i=i-1;j <k;i--,j++){</k;i--,j++)

WR_Data((jieguo+'0'));

}

}

a=0;b=0;fuhao=0; //计算完毕,回到初始值

}

if(keynum==15) //复位,回到初始值

{

a=0;

b=0;

fuhao=0;

InitLCD();

}

}


(5)主函数


void main()

{

COM_8255 = 0x89; //8255设置

InitLCD(); //LCD初始化

while(1)

{

keynum=keyi(); //读取键值

calculate(); //运算

}

}


使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

274

主题

274

帖子

0

粉丝