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

实验目的:用矩阵键盘输入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;
		 }
	}	
}

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

  • 12
    点赞
  • 94
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
Proteus单片机设计仿真51单片机220个Proteus仿真实例源码文件: 100000秒以内的计时程序.DSN 10秒的秒表 (2).DSN 10秒的秒表.DSN 12864LCD显示24C08保存的开机画面.DSN 12864LCD显示EPROM2764保存的开机画面.DSN 12864LCD显示计算器键盘按键实验.DSN 12864图形液晶滚动演示.DSN 160128LCD中文显示温度与时间.DSN 160128LCD图文演示.DSN 160128液晶中文显示ADC0832两路模数转换结果.DSN 160128液晶显示当前压力.DSN 160128液晶曲线显示ADC0832两路模数转换结果.DSN 1602LCD显示仿手机键盘按键字符.DSN 1602LCD显示电话拨号键盘按键实验.DSN 1602LCD显示的秒表.DSN 1602LCD随机模拟显示乘法口诀.DSN 1602字符液晶滚动演示程序.DSN 1602液晶显示DS1302实时时钟.DSN 16×16点阵屏-四块8x8并排的效果.DSN 24C04与数码管.DSN 2×20串行字符液晶演示.DSN 4×4键盘矩阵控制条形LED显示 (2).DSN 4×4键盘矩阵控制条形LED显示.DSN 555定时器实验.DSN 6264扩展内存.DSN 74HC154译码器应用.DSN 74HC595串入并出芯片应用.DSN 74LS138译码器应用.DSN 74LS148扩展中断.DSN 8×8LED点阵屏仿电梯数字滚动显示.DSN 8×8LED点阵屏显示数字.DSN 8只数码管显示多个不同字符.DSN 8只数码管滚动显示单个数字 (2).DSN 8只数码管滚动显示单个数字.DSN 8只数码管滚动显示数字串.DSN ADC0808 PWM实验.DSN ADC0809模数转换与显示.DSN ADC0832模数转换与显示.DSN BCD译码数码管显示数字.DSN DS1621温度传感器实验.DSN DS18B20温度传感器实验.DSN LED模拟交通灯 (2).DSN LED模拟交通灯.DSN MAX7221控制数码管动态显示.DSN PCF8591模数与数模转换实验.DSN T0控制LED实现二进制计数.DSN TIMER0与TIMER1控制条形LED.DSN TIMER0控制单只LED闪烁 (2).DSN TIMER0控制单只LED闪烁.DSN TIMER0控制四只LED滚动闪烁.DSN TIMER0控制流水灯 (2).DSN TIMER0控制流水灯.DSN tu1.DSN 串口发送数据到2片8×8点阵屏滚动显示.DSN 串行数据转换为并行数据.DSN 交通灯控制器.DSN 从左到右的流水灯 (2).DSN 从左到右的流水灯.DSN 光耦控制点亮和延时关闭照明设备.DSN 单只数码管循环显示0-9 (2).DSN 单只数码管循环显示0-9.DSN 单片机与PC机串口通讯仿真.DSN 单片机之间双向通信.DSN 单片机向主机发送字符串.DSN 单片机系统中自制硬件字库的应用.DSN 可以调控的走马灯.DSN 可演奏的电子琴.DSN 字符液晶显示的频率计.DSN 定时器控制交通指示灯.DSN 定时器控制数码管动态显示 (2).DSN 定时器控制数码管动态显示.DSN 左右来回的流水灯 (2).DSN 左右来回的流水灯.DSN 左右来回的流水灯.PWI 并行数据转换为串行数据.DSN 开关控制12864LCD串行模式显示.DSN 开关控制LED.DSN 开关控制报警器.DSN 报警器与旋转灯.DSN 按键发音.DSN 按键控制8×8LED点阵屏显示图形.DSN 按键控制定时器选播多段音乐.DSN 按键控制定时器选播多段音乐.PWI 按键选播电子音乐.DSN 按键选播电子音乐.PWI 播放一段音乐 (2).DSN 播放一段音乐.DSN 数码管显示4×4键盘矩阵按键 (2).DSN 数码管显示4×4键盘矩阵按键.DSN 数码管显示拨码开关编码.DSN 数码管显示的温控电机.DSN 数码管显示的频率计.DSN 数码管闪烁显示.DSN 数码管随机模拟显示乘法口诀.DSN 模拟射击游戏.DSN 正反转可控的步进电机.DSN 正反转可控的直流电机.DSN 温度控制直流电机转速.DSN 演奏一段音阶.DSN 用1602LCD与DS18B20设计的温度报警器.DSN 用1602LCD设计的可调式电子钟.DSN 用24C04与1602LCD设计电子密码锁.DSN 用74HC595与74LS154设计的16×16点阵屏.DSN 用8051与1601LCD设计的计算器.DSN 用8255与74LS154设计的16×16点阵屏.DSN 用8255实现接口扩展.DSN 用ADC0808设计的调温报警

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值