【51单片机系列】矩阵按键扩展实验

2023-12-14 19:34:37

本文对矩阵按键的一个扩展,利用矩阵按键和动态数码管设计一个简易计算器。代码参考:https://blog.csdn.net/weixin_47060099/article/details/106664393

实现功能:使用矩阵按键,实现一个简易计算器,将计算数据及计算结果显示在数码管中。

矩阵按键设计如下图

使用矩阵按键实现一个简易计算器

代码实现:

/*
	实现功能:使用矩阵按键实现简易计算器
	[2023-12-07] zoya
*/
#include "reg52.h"

typedef unsigned char u8;
typedef unsigned int u16;


sbit LSA = P2^2;
sbit LSB = P2^3;
sbit LSC = P2^4;

#define GPIO_DIG P0  // 动态数码管
#define GPIO_KEY P1  // 矩阵按键

u16 KeyValue;  // 存放读取到的键值
u16 keyflag, i;  // 用来判断按下的数字还是运算符或是清空键
u8 code smg[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71, 0x00};  // 共阴极数码管

u16 wei[8] = {0};  // 存放每一位数码管数字的数组

// 延时函数,i=1延时10us
void delay(u16 i)
{
	while(i--);
}

// 扫描显示动态数码管
void Display()
{
	LSA = 0; LSB = 0; LSC = 0; GPIO_DIG = smg[wei[7]]; delay(50); GPIO_DIG = 0x00; // 段选Y0,位选显示,延时,消隐
	LSA = 1; LSB = 0; LSC = 0; GPIO_DIG = smg[wei[6]]; delay(50); GPIO_DIG = 0x00; // 段选Y0,位选显示,延时,消隐
	LSA = 0; LSB = 1; LSC = 0; GPIO_DIG = smg[wei[5]]; delay(50); GPIO_DIG = 0x00; // 段选Y0,位选显示,延时,消隐
	LSA = 1; LSB = 1; LSC = 0; GPIO_DIG = smg[wei[4]]; delay(50); GPIO_DIG = 0x00; // 段选Y0,位选显示,延时,消隐
	LSA = 0; LSB = 0; LSC = 1; GPIO_DIG = smg[wei[3]]; delay(50); GPIO_DIG = 0x00; // 段选Y0,位选显示,延时,消隐
	LSA = 1; LSB = 0; LSC = 1; GPIO_DIG = smg[wei[2]]; delay(50); GPIO_DIG = 0x00; // 段选Y0,位选显示,延时,消隐
	LSA = 0; LSB = 1; LSC = 1; GPIO_DIG = smg[wei[1]]; delay(50); GPIO_DIG = 0x00; // 段选Y0,位选显示,延时,消隐
	LSA = 1; LSB = 1; LSC = 1; GPIO_DIG = smg[wei[0]]; delay(50); GPIO_DIG = 0x00; // 段选Y0,位选显示,延时,消隐
}

// 检测有按键按下并读取键值
void KeyDown()
{
	u16 a = 0;
	GPIO_KEY = 0x0f;  // 行全部为低电平,列全部为高电平
	if(0x0f != GPIO_KEY)  // 读取按键是否按下
	{
		delay(1000);  // 延时10ms进行消隐
		if(0x0f != GPIO_KEY)
		{
			// 测试列
			GPIO_KEY = 0x0f;
			switch(GPIO_KEY)  // 行列扫描法
			{
				case 0x07: KeyValue = 0; break;
				case 0x0b: KeyValue = 1; break;
				case 0x0d: KeyValue = 2; break;
				case 0x0e: KeyValue = 3; break;
			}
			
			// 测试行
			GPIO_KEY = 0xf0;
			switch(GPIO_KEY)  // 行列扫描法
			{
				case 0x70: KeyValue = KeyValue; break;
				case 0xb0: KeyValue = KeyValue + 4; break;
				case 0xd0: KeyValue = KeyValue + 8; break;
				case 0xe0: KeyValue = KeyValue + 12; break;
			}
			
			if(KeyValue==0 || KeyValue==1 || KeyValue==2 || KeyValue==3 || KeyValue==4 || KeyValue==5
				|| KeyValue==6 || KeyValue==7 || KeyValue==8 || KeyValue==9)
			{
				keyflag=1;
			}
			
		}
		while( (a < 50) && (GPIO_KEY != 0xf0) )  // 按键松手检测
		{
			delay(1000);
			a++;
		}
			
	}
}


void main()
{
	
	u16 a=0, b=0, c=0;
	while(1)
	{
		Display();  
		KeyDown();  // 键入第一个数字
		if(1 == keyflag)
		{
			for(i=7;i>0;i--)
			{
				wei[i] = wei[i-1];  // 键入一位数字向左移动一位
			}
			wei[0] = KeyValue;
			keyflag = 0;
		}
		else if(14 == KeyValue)  // 清空显示
		{
			for(i=0;i<8;i++)
			{
				wei[i] = 0;
			}
			
			Display();
		}
		else if(10 == KeyValue)  // 加法运算
		{
			a = wei[0] + wei[1]*10 + wei[2]*100 + wei[3]*1000 +
					wei[4]*10000 + wei[5]*100000 + wei[6]*1000000 + 
					wei[7]*10000000;
			for(i=0; i<8; i++)
			{
				wei[i] = 0;
			}
			// 输入第二个数
			while(1)
			{
				Display();
				KeyDown();  // 输入第二个数
				if(15 == KeyValue)
					break;  // 当识别到等号时,停止输入
				if(1 == keyflag)
				{
					for(i=7; i>0; i--)
					{
						wei[i] = wei[i-1];
					}
					wei[0] = KeyValue;
					keyflag = 0;
				}
			}
			
			b = wei[0] + wei[1]*10 + wei[2]*100 + wei[3]*1000 +
					wei[4]*10000 + wei[5]*100000 + wei[6]*1000000 + 
					wei[7]*10000000;
			
			c = a + b;
			wei[0] = c%10;  // 计算C的各个位的数字
			wei[1] = c/10%10;
			wei[2] = c/100%10;
			wei[3] = c/1000%10;
			wei[4] = c/10000%10;
			wei[5] = c/100000%10;
			wei[6] = c/1000000%10;
			wei[7] = c/10000000%10;
			
			Display();
		}
		else if(11 == KeyValue)  // 减法运算
		{
			a = wei[0] + wei[1]*10 + wei[2]*100 + wei[3]*1000 +
					wei[4]*10000 + wei[5]*100000 + wei[6]*1000000 + 
					wei[7]*10000000;
			for(i=0; i<8; i++)  // 清空数码管
			{
				wei[i] = 0;
			}
			// 输入第二个数
			while(1)
			{
				Display();
				KeyDown();  // 输入第二个数
				if(15 == KeyValue)
					break;  // 当识别到等号时,停止输入
				if(1 == keyflag)
				{
					for(i=7; i>0; i--)
					{
						wei[i] = wei[i-1];
					}
					wei[0] = KeyValue;
					keyflag = 0;
				}
			}
			
			b = wei[0] + wei[1]*10 + wei[2]*100 + wei[3]*1000 +
					wei[4]*10000 + wei[5]*100000 + wei[6]*1000000 + 
					wei[7]*10000000;
			if(a > b)
			{
				c = a - b;
				wei[0] = c%10;  // 计算C的各个位的数字
				wei[1] = c/10%10;
				wei[2] = c/100%10;
				wei[3] = c/1000%10;
				wei[4] = c/10000%10;
				wei[5] = c/100000%10;
				wei[6] = c/1000000%10;
				wei[7] = c/10000000%10;
			}
			else if(a < b)
			{
				u16 e = 0;
				c = b-a;
				wei[0] = c%10;
				wei[1] = c/10%10;
				if(wei[1] == 0)
				{
					wei[1] = 16;
					e=1;
				}
				wei[2] = c/100%10;
				if(wei[2]==0 && e==0)
				{
					wei[2] = 16;
					e=1;
				}
				wei[3] = c/1000%10;
				if(wei[3]==0 && e==0)
				{
					wei[3] = 16;
					e=1;
				}
				wei[4] = c/10000%10;
				if(wei[4]==0 && e==0)
				{
					wei[4] = 16;
					e=1;
				}
				wei[5] = c/100000%10;
				if(wei[5]==0 && e==0)
				{
					wei[5] = 16;
					e=1;
				}
				wei[6] = c/1000000%10;
				if(wei[6]==0 && e==0)
				{
					wei[6] = 16;
					e=1;
				}
				wei[7] = c/10000000%10;
				if(wei[7]==0 && e==0)
				{
					wei[7] = 16;
					e=1;
				}
				
			}
			
			Display();
		}
		else if(12 == KeyValue)  // 乘法运算
		{
			a = wei[0] + wei[1]*10 + wei[2]*100 + wei[3]*1000 +
					wei[4]*10000 + wei[5]*100000 + wei[6]*1000000 + 
					wei[7]*10000000;
			for(i=0; i<8; i++)
			{
				wei[i] = 0;
			}
			// 输入第二个数
			while(1)
			{
				Display();
				KeyDown();  // 输入第二个数
				if(15 == KeyValue)
					break;  // 当识别到等号时,停止输入
				if(1 == keyflag)
				{
					for(i=7; i>0; i--)
					{
						wei[i] = wei[i-1];
					}
					wei[0] = KeyValue;
					keyflag = 0;
				}
			}
			
			b = wei[0] + wei[1]*10 + wei[2]*100 + wei[3]*1000 +
					wei[4]*10000 + wei[5]*100000 + wei[6]*1000000 + 
					wei[7]*10000000;
			
			c = a * b;
			wei[0] = c%10;  // 计算C的各个位的数字
			wei[1] = c/10%10;
			wei[2] = c/100%10;
			wei[3] = c/1000%10;
			wei[4] = c/10000%10;
			wei[5] = c/100000%10;
			wei[6] = c/1000000%10;
			wei[7] = c/10000000%10;
			
			Display();
		}
		else if(13 == KeyValue)  // 除法运算
		{
			a = wei[0] + wei[1]*10 + wei[2]*100 + wei[3]*1000 +
					wei[4]*10000 + wei[5]*100000 + wei[6]*1000000 + 
					wei[7]*10000000;
			for(i=0; i<8; i++)
			{
				wei[i] = 0;
			}
			// 输入第二个数
			while(1)
			{
				Display();
				KeyDown();  // 输入第二个数
				if(15 == KeyValue)
					break;  // 当识别到等号时,停止输入
				if(1 == keyflag)
				{
					for(i=7; i>0; i--)
					{
						wei[i] = wei[i-1];
					}
					wei[0] = KeyValue;
					keyflag = 0;
				}
			}
			
			b = wei[0] + wei[1]*10 + wei[2]*100 + wei[3]*1000 +
					wei[4]*10000 + wei[5]*100000 + wei[6]*1000000 + 
					wei[7]*10000000;
			if(0 != b)
			{
				c = a / b;
				wei[0] = c%10;  // 计算C的各个位的数字
				wei[1] = c/10%10;
				wei[2] = c/100%10;
				wei[3] = c/1000%10;
				wei[4] = c/10000%10;
				wei[5] = c/100000%10;
				wei[6] = c/1000000%10;
				wei[7] = c/10000000%10;
				
				Display();
			}
			
		}
		
	}
}

仿真结果:

矩阵按键实现简易计算器

文章来源:https://blog.csdn.net/sinat_41752325/article/details/134854488
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。