Proteus仿真C51单片机实现简易计算器(LCD1602,矩阵键盘)

该程序设计了一个使用矩阵键盘输入数字和运算符(加、减、乘、除及清屏)的系统,实现了简单的算术运算,包括处理负数的情况,并在LCD显示器上显示结果。通过扫描矩阵键盘获取输入,然后调用相应的运算函数进行计算,并在特定按键(如清屏键)按下时清除屏幕。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实验目的:用矩阵键盘输入0-9和“+”、“-”、“*”、“/”,最后一个按键作为清屏按钮,实现一位加减乘除(可表示负数)。

目录

 测试用例

代码部分 

头文件以及数组定义

延时函数

LCD初始化部分

矩阵键盘扫描

算术模块

主函数


 测试用例

矩阵键盘第一行分别代表数值0、1、2、3

矩阵键盘第一列分别代表数值0、4、8、*

代码部分 

头文件以及数组定义

#include <reg51.h>
#include <intrins.h>
#include <stdio.h>
#define uchar unsigned char
#define uint unsigned int
#define out P0
sbit RS=P2^6;
sbit RW=P2^5;
sbit E=P2^7;
sbit b1=P3^0;
sbit b2=P3^1;
sbit b3=P3^2;
uint keyval;
uchar key;
uchar num[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x24,0x25,0x2b,0x2d,0x01};
uchar num1[]={'0','1','2','3','4','5','6','7','8','9','+','-','*','/','=',0x01};

延时函数

void delay10ms(void){
	int i,j;
	for(i=0;i<100;i++)
		for(j=0;j<100;j++)
		{;}
}

LCD初始化部分

void write_command(uchar com) //lcd写命令
{
	E=0;
	RS=0;
	RW=0;
	out=com;
	E=1;
	delay(5);
	E=0;
	delay(5);
}
void write_data(uchar dat)  //lcd写数据
{
	E=0;
	RS=1;
	RW=0;
	out=dat;
	E=1;
	delay(5);
	E=0;
	delay(5);
}
void LCD_initial(void)  //lcd初始化
{
	write_command(0x38);
	delay(5);
	write_command(0x0c);
	delay(5);
	write_command(0x06);
	delay(5);
}

矩阵键盘扫描

uint _scanf()
{	
	P1=0xf0;
	if(P1!=0xf0)
	{
		delay10ms();
		if(P1!=0xf0)     //先扫描行确定是在哪一行有按键按下
		{
			switch(P1)
			{
			case 0xe0: keyval=0;break;
			case 0xd0: keyval=1;break;
			case 0xb0: keyval=2;break;
			case 0x70: keyval=3;break;
			}
			P1=0x0f;
			switch(P1)  //再扫描列确定再哪一列
			{
			case 0x0e: keyval=keyval;break;
			case 0x0d: keyval+=4;break;
			case 0x0b: keyval+=8;break;
			case 0x07: keyval+=12;break;
			}
		}
		return  keyval;  //keyval代表数值,第一行第一列keyval的值为0
	 }
	   
	else if(P1==0Xf0) //如果没有按键按下返回一个值,在主函数中利用这个值让程序循环等待
		{	keyval=99;
		return 	  keyval;}
}

算术模块

uint add(uchar x, uchar y) //加
{
	uchar a;
	a=x+y;
    return a;
}
 
uint mul(uint x, uint y)  //乘
{		uint a;
	a=x*y;
    return a;
}
 
uint sub(uint x, uint y)  //减
{	uint a;
	a=x-y;
    return a;
}
 
uint div(uint x, uint y)  //除
{	uint a;
	a=x/y;
    return a;
}

主函数

void main()
{		  
	uint flag;  //存放keyval的值
	uint i=0;
	uint j=0;
	uint z,x,c;  //存放参与运算的数和运算符
	uint answer;
	write_command(0x01);
	_scanf();
	delay10ms();
	LCD_initial();
	while(1)
	{
		flag=_scanf();
		switch(i)
		{	
		case 0:z=flag;
		case 1:x=flag;
		case 2:c=flag;
	 	}

	 	if(flag!=99) //有按键按下在1602上依次输出flag的值
		{	

			write_data(num1[flag]);
			delay(500);
			i++;
	   		
		}
	if(i==3)  //第三个数输出后在1062上换行并输出计算结果
	{
		write_command(2);
		write_command(0x80+0x42);
		if(x==10)  //加法
		{
			if(add(z,c)>9)
			{write_data(num1[add(z,c)/10]);
			write_data(num1[add(z,c)%10]);
			}
			else
			write_data(num1[add(z,c)]);
			
		}
		if(x==11)  //减法
		{
			if(z<c)  //如果被减数小于减数,输出负号
			{
				write_data('-');
				write_data(num1[sub(c,z)]);
			}
			else
			write_data(num1[sub(z,c)]);
		}
		if(x==12)  //乘法
		{
			write_data(num1[mul(z,c)/10]);
			write_data(num1[mul(z,c)%10]);
		}
		if(x==13)  //除法
		{
			write_data(num1[div(z,c)%10]);
		}
	}
		if(flag==15)  //最后一个按键被按下,1602清屏
		{
		write_command(0x01);
		 i=0;
		 j=0;
		 }
	}	
}

这个方法麻烦,但我觉得容易理解,欢迎大佬指教。

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值