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

本文对矩阵按键的一个扩展,利用矩阵按键和动态数码管设计一个简易计算器。代码参考: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();
			}
			
		}
		
	}
}

仿真结果:

矩阵按键实现简易计算器

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/236022.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

15Linux、GIT及相关相似面试题、PostMan

Linux和git相似是命令相关的层次结构相似 Linux Linux Linux常用操作_linux操作-CSDN博客 程序员常用的10个Linux命令_简介linux系统中的10个常用命令及功能-CSDN博客 help help 命令 &#xff1a;获得 shell 内置命令的帮助信息&#xff0c;常用形式 help cd ls --help …

SPI 通信-stm32入门

本节我们将继续学习下一个通信协议 SPI&#xff0c;SPI 通信和我们刚学完的 I2C 通信差不多。两个协议的设计目的都一样&#xff0c;都是实现主控芯片和各种外挂芯片之间的数据交流&#xff0c;有了数据交流的能力&#xff0c;我们主控芯片就可以挂载并操纵各式各样的外部芯片&…

SpringBoot+Netty+Websocket实现消息推送

这样一个需求&#xff1a;把设备异常的状态每10秒推送到页面并且以弹窗弹出来&#xff0c;这个时候用Websocket最为合适&#xff0c;今天主要是后端代码展示。 添加依赖 <dependency><groupId>io.netty</groupId><artifactId>netty-all</artifact…

【SpringSecurity】-- 认证、授权

文章目录 SpringSecurity简介快速入门1.准备工作1.2引入SpringSecurity 认证1.登录校验流程2.原理2.1SpringSecurity完整流程2.2认证流程详解 3.解决问题3.1思路分析3.2准备工作3.3.实现3.3.1数据库校验用户3.3.2密码加密存储3.3.3登录接口3.3.4认证过滤器3.3.5退出登录 授权1.…

YOLOv8改进 | Neck篇 | Slim-Neck替换特征融合层实现超级涨点 (又轻量又超级涨点)

一、本文介绍 本文给大家带来的改进机制是Slim-neck提出的Neck部分&#xff0c;Slim-neck是一种设计用于优化卷积神经网络中neck部分的结构。在我们YOLOv8中&#xff0c;neck是连接主干网络&#xff08;backbone&#xff09;和头部网络&#xff08;head&#xff09;的部分&…

Tair(2):Tair安装部署

1 安装相关依赖库 yum install -y gcc gcc-c make m4 libtool boost-devel zlib-devel openssl-devel libcurl-devel yum&#xff1a;是yellowdog updater modified 的缩写&#xff0c;Linux中的包管理工具gcc&#xff1a;一开始称为GNU C Compiler&#xff0c;也就是一个C编…

本地如何使用PHP搭建简单Imagewheel云图床,结合内网穿透实现在外远程访问?

文章目录 1.前言2. Imagewheel网站搭建2.1. Imagewheel下载和安装2.2. Imagewheel网页测试2.3.cpolar的安装和注册 3.本地网页发布3.1.Cpolar临时数据隧道3.2.Cpolar稳定隧道&#xff08;云端设置&#xff09;3.3.Cpolar稳定隧道&#xff08;本地设置&#xff09; 4.公网访问测…

vue3使用Mars3D写区块地图

效果图 引入相关文件 因为我也是第一次使用&#xff0c;所以我是把插件和源文件都引入了&#xff0c;能使用启动 源文件 下载地址&#xff1a; http://mars3d.cn/download.html 放入位置 在index.html中引入 <!--引入cesium基础lib--><link href"/static/C…

Stable diffusion 简介

Stable diffusion 是 CompVis、Stability AI、LAION、Runway 等公司研发的一个文生图模型&#xff0c;将 AI 图像生成提高到了全新高度&#xff0c;其效果和影响不亚于 Open AI 发布 ChatGPT。Stable diffusion 没有单独发布论文&#xff0c;而是基于 CVPR 2022 Oral —— 潜扩…

爆肝整理,Java接口自动化测试实战-rest-assured(详细总结)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、关于rest-assu…

聊个开心的敏捷话题——40小时工作制

近年来&#xff0c;加班现象在很多行业已经普遍制度化&#xff0c;甚至“996”已成为一些行业标签。企业高强度的压榨让员工不堪重负&#xff0c;且时常由此引发的各种悲剧也并不鲜见。 所以&#xff0c;今天我们一起来聊一个开心轻松的话题——极限编程的40h工作制原则。 40…

本科毕业论文查重率高吗【一文读懂】

大家好&#xff0c;今天来聊聊本科毕业论文查重率高吗&#xff0c;希望能给大家提供一点参考。 以下是针对论文重复率高的情况&#xff0c;提供一些修改建议和技巧&#xff1a; 本科毕业论文查重率高吗&#xff1f;重要性与应对策略 摘要&#xff1a;对于本科毕业生来说&#…

PyQt6 QDateEdit日期控件

​锋哥原创的PyQt6视频教程&#xff1a; 2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~共计39条视频&#xff0c;包括&#xff1a;2024版 PyQt6 Python桌面开发 视频教程(无废话…

java--正则表达式书写规则

1.正在表达式 ①就是由一些特定的字符组成&#xff0c;代表的是一个规则。 ②作用一&#xff1a;用来校验数据格式是否合法。 ③作用二&#xff1a;在一段文本中查找满足要求的内容 2.String提供了一个匹配正则表达式的方法 3.正则表达式的书写规则

Uniapp安卓原生插件开发Demo

文章目录 前言一、安装开发工具二、导入uni插件原生项目三、开发Module四、开发Component五、合并原生代码到uniapp项目中总结 前言 当HBuilderX中提供的能力无法满足App功能需求&#xff0c;需要通过使用Andorid/iOS原生开发实现时&#xff0c;可使用App离线SDK开发原生插件来…

第二十一章,网络通信

网络协议 IP协议 IP是Internet Protocol的简称&#xff0c;是一种网络协议。Internet 网络采用的协议是TCP/IP协议&#xff0c;其全称是Transmission Control Protocol/Internet Protocol。Internet 依靠TCP/IP协议&#xff0c;在全球范围内实现了不同硬件结构、不同操作系统…

排序算法之三:希尔排序

希尔排序基本思想 希尔排序法又称缩小增量法 希尔排序法的基本思想是&#xff1a;先选定一个整数&#xff0c;把待排序文件中所有记录分成个组&#xff0c;所有距离为的记录分在同一组内&#xff0c;并对每一组内的记录进行排序。然后&#xff0c;取&#xff0c;重复上述分组…

Vue3+ElementPlus:icon图标不显示(给表格字段里添加图标)

一、背景 在Vue3项目中&#xff0c;想在表格的字段中引入图标因为给字段做了触发提示&#xff0c;希望用户能够注意到这个功能&#xff0c;因此想加个图标提示一下用户&#xff0c;效果如下&#xff1a; 触发提示效果如下&#xff1a; &#xff08;样式这里就不进行优化了&am…

【VS Code开发】使用Live Server搭建MENJA小游戏并发布至公网远程访问

文章目录 前言1. 编写MENJA小游戏2. 安装cpolar内网穿透3. 配置MENJA小游戏公网访问地址4. 实现公网访问MENJA小游戏5. 固定MENJA小游戏公网地址 前言 本篇教程&#xff0c;我们将通过VS Code实现远程开发MENJA小游戏&#xff0c;并通过cpolar内网穿透发布到公网&#xff0c;分…

【nodejs升级版本】win10 nodejs版本低升级版本流程

首先 网上说的n模块不支持window系统&#xff01;&#xff01;&#xff01; window系统升级node只能到node官网下载window安装包来覆盖之前的node 升级步骤如下&#xff1a; 1&#xff0c;找到你node的安装路径&#xff0c;不知道的可以cmd命令行中输入这个命令就可以看到了…