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

概述

LCD液晶显示的51单片机简单计算器可实现完成了两个范围在0到255的数加、减、乘、除运算,其中减法可显示负数,除法只保留整数并由LCD液晶显示。并在实验室实验箱,实现上述功能。完成该任务需要熟悉和了解控制LCD液晶屏的显示的方法,矩阵键盘读取按键值的方法、89C51系列单片机的相关知识、C51编程和数字电子技术的相关知识。
完整代码:https://download.csdn.net/download/weixin_43786907/16524021

方案

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

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

系统输入有:0到9、“+”、“-”、“”、“/”、“=”与复位对应矩阵键盘的16个按键。我将矩阵键盘16个按键赋予按键值与并且与实际意义形成映射。
矩阵键盘按键值:
矩阵键盘按键值
矩阵键盘的输入映射:
矩阵键盘的输入映射
矩阵键盘实际上是一个2
8的矩阵按键,在矩阵键盘中,每条水平线和垂直线在交叉处不直接连通,而是通过一个按键加以连接。这样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 <reg52.h>                            //C51系列开发头文件
#include <absacc.h>                           //绝对地址访问头文件
#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<a)
							 {
								 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[i]=j;
						    }
							 k=i;
						for(j=0,i=i-1;j<k;i--,j++)
								{
									WR_Data((jieguo[i]+'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();	                  //运算
	}
}

完整代码:https://download.csdn.net/download/weixin_43786907/16524021

  • 7
    点赞
  • 86
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值