【单片机】矩阵键盘/定时器

news2025/1/9 4:44:21


目录

一、矩阵键盘

1、矩阵按键原理

1.1工作方式

1.2工作原理

1.3单片机IO口

2、矩阵键盘数字显示代码

3、矩阵键盘密码锁 

二、定时器(工作模式1)

1、定时器的原理

2、寄存器

2.1模式选择寄存器TMOD(不可位寻址)

2.2中断控制寄存器TCON(可位寻址)

3、使用独立按键点亮流水灯

4、简易秒表的实现


一、矩阵键盘

在键盘中按键数量较多时,将按键排列成矩阵可以减少IO口的占用。采用逐行或逐列的扫描,就可以读出任意位置按键的状态。

1、矩阵按键原理

1.1工作方式

和数码管一样,矩阵按键实现多个按键同时检测的方式为:读取第一行/列,读取第二行/列,读取第三行/列······不断循环这一过程,达到多个按键同时检测的效果。

矩阵按键越多,节约的IO口也会越多。

1.2工作原理

51单片机的矩阵按键使用8个引脚来控制16个按键(4*4)。

通过原理图不难发现P14-P17这4个引脚是控制矩阵按键横向的电平的,而P10-P13这4个引脚是控制矩阵按键纵向的电平的。

逐行扫描:逐行扫描就是让P13-P10循环执行0111,1011,1101,1110。例如我给P17-P14分别赋值1011,P13-P10分别检测各自引脚电平,如果P13检测到低电平,那么说明按键S5被按下了。

逐列扫描:对P10-P13进行赋值,由P14-P17根据引脚电平检测按键是否被按下。

1.3单片机IO口

上拉是指通过一个连接在IO口与电源之间的电阻将不确定或高电平但驱动能力不够的电位控制在高电平。上拉电阻越大,上拉能力越弱。51系列单片机P1、P2、P3为准双向口,均为弱上拉强下拉模式,当输出高电平时,能够输出的电流很小,很容易被别的强下拉拉低。

2、矩阵键盘数字显示代码

//按列扫描
uchar MatrixKey()
{
	uchar KeyNumber=0;
	P1=0XFF;//P1口整体赋为高电平
	P1_3=0;//P1的3号口给低电平
	//P1的14-17口循环检测按键状态
	if(P1_7==0)
	{
		delay_ms(20);//延时20ms消抖
		while(P1_7==0);//如果消抖完还没松手,就空循环
		delay_ms(20);//延时20ms消抖
		KeyNumber=1;//松手了
	}
	if(P1_6==0){delay_ms(20);while(P1_6==0);delay_ms(20);KeyNumber=5;}
	if(P1_5==0){delay_ms(20);while(P1_5==0);delay_ms(20);KeyNumber=9;}
	if(P1_4==0){delay_ms(20);while(P1_4==0);delay_ms(20);KeyNumber=13;}
	
	P1=0XFF;
	P1_2=0;
	if(P1_7==0){delay_ms(20);while(P1_7==0);delay_ms(20);KeyNumber=2;}
	if(P1_6==0){delay_ms(20);while(P1_6==0);delay_ms(20);KeyNumber=6;}
	if(P1_5==0){delay_ms(20);while(P1_5==0);delay_ms(20);KeyNumber=10;}
	if(P1_4==0){delay_ms(20);while(P1_4==0);delay_ms(20);KeyNumber=14;}
	
	P1=0XFF;
	P1_1=0;
	if(P1_7==0){delay_ms(20);while(P1_7==0);delay_ms(20);KeyNumber=3;}
	if(P1_6==0){delay_ms(20);while(P1_6==0);delay_ms(20);KeyNumber=7;}
	if(P1_5==0){delay_ms(20);while(P1_5==0);delay_ms(20);KeyNumber=11;}
	if(P1_4==0){delay_ms(20);while(P1_4==0);delay_ms(20);KeyNumber=15;}
	
	P1=0XFF;
	P1_0=0;
	if(P1_7==0){delay_ms(20);while(P1_7==0);delay_ms(20);KeyNumber=4;}
	if(P1_6==0){delay_ms(20);while(P1_6==0);delay_ms(20);KeyNumber=8;}
	if(P1_5==0){delay_ms(20);while(P1_5==0);delay_ms(20);KeyNumber=12;}
	if(P1_4==0){delay_ms(20);while(P1_4==0);delay_ms(20);KeyNumber=16;}
	return KeyNumber;
}
void main()
{
	LCD_Init();//初始化
	
	while(1)
	{
		uchar KeyNumber=0;
		KeyNumber=MatrixKey();
		if(KeyNumber!=0)//说明有按键被按下,下一次按键被按下才进入if中更改显示屏数据
		{
			LCD_ShowNum(1,1,KeyNumber,5);
		}
	}
}

3、矩阵键盘密码锁 

#include "LCD1602.h"
#include "MatrixKey.h"
typedef unsigned int uint;
uint KeyNumber=0,password=0,cnt=0;
void main()
{
	LCD_Init();//初始化
	LCD_ShowString(1,1,"password");
	while(1)
	{
		KeyNumber=MatrixKey();
		if(KeyNumber!=0)//说明有按键被按下,下一次按键被按下才进入if中更改显示屏数据
		{
			//输入密码
			if(KeyNumber<=10&&cnt<4)//如果KeyNumber小于等于10,认为是在输入密码
			{
				password*=10;
				password+=KeyNumber%10;
				++cnt;
				LCD_ShowNum(2,1,password,4);
			}
			//确认密码
			if(KeyNumber==11)//把11定义为确认密码键
			{
				if(password==1234)
				{
					LCD_ShowString(1,14,"OK ");
				}
				else
				{
					LCD_ShowString(1,14,"ERR");
				}
				password=cnt=0;//确认后清零
				LCD_ShowNum(2,1,password,4);//更新显示为0000
			}
			//按位取消已输入的密码
			if(KeyNumber==12)//把12定义为确认密码键
			{
				password/=10;
				--cnt;
				LCD_ShowNum(2,1,password,4);//更新显示为0000
			}
		}
	}
}

二、定时器(工作模式1)

1、定时器的原理

STC89C52有三个定时器(P1.0和P1.1会多一组定时器T2)。

T0和T1均有四种工作模式:

模式0:13位定时器/计数器

模式1:16位定时器/计数器(常用)

模式2:8位自动重装模式

模式3:两个8位计数器(T1定时器在该模式停止计数)

工作模式1简图:369148631f799aa0aa6fb63935618761.jpeg

从上图可以看出,中断系统能够暂停主程序,去运行另一个程序。(有点像系统编程里父进程调用wait函数,阻塞父进程,父进程等待子进程变成僵尸后,父进程拿到子进程的退出码和退出信号后,继续执行父进程。当然只是有点像,因为单片机是通过数据溢出发送中断,执行中断服务函数)

2、寄存器

图上这些英文标识就是51单片机的寄存器或寄存器的位的名字,所以写程序的时候控制这些寄存器就可以完成电路的闭合和优先级等操作。

2.1模式选择寄存器TMOD(不可位寻址)

GATE

0

仅由TRx(TR1或TR0)控制定时器/计数器,TRx=1,允许计数/定时

1

由外引脚ITNx(INT0或INT1)和TRx均为1时,允许计数/定时

C/T

0

定时器工作模式,对单片机的晶体振荡器分频后的脉冲进行计数。

1

计数器工作模式,计数器对外部输入引脚T0(P3.4)或T1(P3.5)的外部脉冲(负跳变)计数。

M1和M2

00

模式0:13位定时器/计数器

01

模式1:16位定时器/计数器(常用)

10

模式2:8位自动重装模式

11

模式3:两个8位计数器(T1定时器在该模式停止计数)

2.2中断控制寄存器TCON(可位寻址)

TF0

0

定时器/计数器T0溢出中断标志。该位为0表示未满

1

定时器/计数器T0溢出中断标志。溢出时,该位由硬件置1,并向CPU请求中断,响应后硬件清0

TR0

0

停止定时器/计数器工作

1

允许定时器/计数器工作

3、使用独立按键点亮流水灯

//Timer0.c
//初始化
void Timer0_Init()
{
	//TMOD=0X01;//选择工作模式1,只需将TMOD比特位置为0000 0001即可,不过这样会修改T1的状态
	//TMOD&=0XF0;//把TMOD的低四位清零,高四位保持不变
	TMOD|=0X01;//把TMOD的最低位置1,其他位不变
	TR0=1;//允许定时器开始计数
	TF0=0;//该位为0表示计数未满
	TH0=64535/256;//拿到64535的高8位
	TL0=64535%256;//拿到64535的低8位
	//控制电路的开关
	ET0=1;
	EA=1;
	PT0=0;//PT0用于设置优先级,默认是0,不写也行	
}
//key.c用于返回按键按下所对应的值
unsigned char Key()
{
	unsigned char KeyNumber=0;
	if(P3_1==0)
	{
		delay_ms(20);
		while(P3_1==0);//空循环
		delay_ms(20);
		KeyNumber=1;
	}
	if(P3_0==0){delay_ms(20);while(P3_0==0);KeyNumber=2;}
	if(P3_2==0){delay_ms(20);while(P3_2==0);KeyNumber=3;}
	if(P3_3==0){delay_ms(20);while(P3_3==0);KeyNumber=4;}
	return KeyNumber;
}
//main.c
#include <intrins.h>//左右移函数头文件
unsigned char KeyNumber,LedMode;
//定时器数据溢出发生中断,执行中断函数
//interrupt告诉编译器这是中断服务函数
//0:外部中断0;1:T0定时器/计数器;2:外部中断1;3:T1定时器/计数器;4:串行口
//数字越小,代表优先级越高
void Timer0_Routine() interrupt 1
{
	static unsigned int T0Count;//函数栈帧结束后保留T0Count
	TH0=64535/256;//每次进中断函数后,让这两个寄存器重新回到初值
	TL0=64535%256;
	T0Count++;//每中断一次T0Count++
	if(T0Count>=(500/(12/11)))//达到了定时0.5秒的作用(晶振11.0592)
	{
		T0Count=0;//重置为0
		if(LedMode==0)
			P2=_crol_(P2,1);//P2左移1位
		if(LedMode==1)
			P2=_cror_(P2,1);//P2右移1位
	}
}
void main()
{
	P2=0XFE;
	Timer0_Init();
	while(1)
	{
		KeyNumber=Key();
		if(KeyNumber==1) 
		{
			LedMode++;
			if(LedMode>=2)
			{
				LedMode=0;
			}
		}
		
	}
}

调用初始化函数,定时器开始计数,约1毫秒后发生溢出,每次发生溢出将会调用中断服务函数,中断服务函数运行完毕后,继续执行main函数。通过代码可以看到,这个中断服务函数将在约500次中断(0.5秒)后才会执行移位LED灯的操作,这个时候main函数已经运行至while循环中了,每隔0.5秒,LED灯将会循环右移(代码明明是写的左移呀,你为什么说LED在右移?代码确实在控制P2引脚低电平那一位左移,但是单片机的低位LED灯在最左边,所以看起来是在右移,不影响)当按下K1键时,LedMode变为1,流水灯将向反方向移动;再次按下K1,LedMode重新被置为0,流水灯的方向再次逆转。

4、简易秒表的实现

#include <REGX52.H>
#include "LCD1602.h"
#include "delay.h"
#include "Timer0.h"
unsigned char sec,min,hour;
void Timer0_Routine() interrupt 1
{
	static unsigned int T0Count;//函数栈帧结束后保留T0Count
	TH0=64535/256;//每次进中断函数后,让这两个寄存器重新回到初值
	TL0=64535%256;
	T0Count++;//每中断一次T0Count++
	if(T0Count>=(1000/(12/11)))//达到了定时1秒的作用(晶振11.0592)
	{
		T0Count=0;
		sec++;
		if(sec>=60)
		{
			sec=0;
			min++;
			if(min>=60)
			{
				min=0;
				hour++;
			}
		}
	}
}
void main()
{
	LCD_Init();
	Timer0_Init();
	LCD_ShowString(1,1,"Clock:");
	while(1)
	{
		LCD_ShowNum(2,1,hour,2);
		LCD_ShowString(2,3,":");
		LCD_ShowNum(2,4,min,2);
		LCD_ShowString(2,6,":");
		LCD_ShowNum(2,7,sec,2);
	}
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CentOS 搭建 WordPress 站点

博客链接:https://www.aiiyx.cn 内容纲要 1. 版本相关2. 主要内容3. 安装并配置 PHP4. 安装并配置 WordPress5. 配置 Nginx6. 配置 MySQL7. 初始化 WordPress 1. 版本相关 WordPress 版本 5.9.3PHP 版本 8.1MySQL 版本 5.7Nginx 版本 1.18 2. 主要内容 由于我的 CentOS 服务…

ChatGPT:将你的微信变成智能聊天机器人!

天天用微信的你有没有做个这样一种设想&#xff1a;让最先进的人工智能算法帮你聊天! 这机器人可以回答各种问题&#xff0c;上知天文下知地理&#xff0c;甚至还能写代码。无论是哄女朋友&#xff0c;应付老婆&#xff0c;或者勾搭陌生小姐姐&#xff0c;都能做到24小时在线&…

一文带领大家了解什么是泛型

对于泛型&#xff01;其实大家了解不是很多&#xff0c;在各大高校的学习中&#xff0c;如果你不去深入的了解泛型&#xff0c;老师只是会一水儿过&#xff0c;并不会单独去带领大家了解&#xff01;&#xff01;那么&#xff0c;笔者结合自身的学习泛型的想法&#xff0c;结合…

2022年双十二拼多多百亿补贴有活动吗?如何领红包?

2022年双十二拼多多百亿补贴有活动吗?如何领红包? 拼多多的活动大家都很清楚&#xff0c;平常没有活动的时候&#xff0c;价格也是比较实惠的&#xff0c;除了拼团购物之外&#xff0c;拼多多还有百亿补贴&#xff0c;所以商品比其他平台都要便宜&#xff0c;双十二拼多多百亿…

物理数据库服务器扫描hba卡识别共享磁盘命令

1、问题背景 默认情况&#xff0c;在扩容完1套物理rac共享存储后&#xff0c;rac主机是不能识别共享存储的。那么该怎么办呢&#xff1f; 2、解决办法 例如&#xff0c;在扩容完1套物理rac共享存储后&#xff0c;如果rac主机不能识别共享存储的话(一般需要执行命令后&#x…

Jboss弱口令Getshell

文章目录漏洞简介影响版本环境搭建漏洞复现漏洞简介 JBoss Administration Console存在默认账号密码admin/vulhub&#xff0c;如果Administration Console可以登录&#xff0c;就可以在后台部署war包getshell 影响版本 Jboss4.x及其之前的版本 console 管理路径为/jmx-consol…

day16【代码随想录】反转字符串、反转字符串中的元音字母、反转字符串||、反转字符串中的单词|||、替换空格、翻转字符串中的单词、左旋转字符串

文章目录一、反转字符串&#xff08;力扣344&#xff09;二、反转字符串中的元音字母&#xff08;力扣345&#xff09;三、反转字符串 II&#xff08;力扣541&#xff09;四、反转字符串中的单词 III&#xff08;力扣557&#xff09;五、替换空格&#xff08;剑指 Offer 05&…

Kubernetes ~ k8s 从入门到入坑。

Kubernetes ~ k8s 从入门到入坑。 文章目录Kubernetes ~ k8s 从入门到入坑。1. Kubernetes 介绍。1.1 应用部署方式演变。1.2 kubernetes 简介。1.3 kubernetes 组件。1.4 kubernetes 概念。2. kubernetes 集群环境搭建。2.1 前置知识点。2.2 kubeadm 部署方式介绍。2.3 安装要…

人工智能前沿——玩转OpenAI聊天机器人ChatGPT(免费中文版)

目录 2022 地表最强AI聊天机器人ChatGPT诞生&#xff01;&#xff01;&#xff01; 一、前言 &#x1f384;&#x1f388; ChatGPT是OpenAI开发的一个大型预训练语言模型。它是GPT-3模型的变体&#xff0c;GPT-3经过训练&#xff0c;可以在对话中生成类似人类的文本响应。Cha…

Vite + Vue3 项目中,使用 vw/vh 适配移动端,并通过 Android Studio 打包

目录 1. 使用 vw/vh 适配移动端 1.1 使用 vite 初始化项目 1.2 安装插件&#xff0c;将 px 转化成 vw 1.2.1 在 vite.config.ts 中&#xff0c;声明插件 1.2.2 手写 postcss 类型声明文件&#xff0c;解决 路径爆红、没有提示 1.2.3 tsconfig.config.json VS tsconfig.js…

Java 8 Stream 之 collect() 的奇技淫巧!

前言 本身我是一个比较偏向少使用Stream的人&#xff0c;因为调试比较不方便。 但是, 不得不说&#xff0c;stream确实会给我们编码带来便捷。 所以还是忍不住想分享一些奇技淫巧。 正文 Stream流 其实操作分三大块 &#xff1a; 创建 处理 收集 我今天想分享的是 收集…

核心内参:S参数的三个重要特性——因果性、无源性与互异性

1 从一个报错开始 S参数在射频、高速领域的应用非常广泛&#xff0c;相关知识点也非常多。最近浏览了一本2020年新出版的书《S Parameter for Signal Integrity》&#xff0c;作者是IEEE Fellow、业界大牛Peter J. Pupalaikis&#xff0c;现任职于Teledyne LeCroy。该书写的非…

《Linux运维实战:使用Percona Backup for MongoDB备份与恢复Mongodb数据》

一、备份与恢复方案 Percona Backup for MongoDB 是一个开源、分布式和低影响的解决方案&#xff0c;用于MongoDB分片集群和副本集的一致备份。从版本1.7.0开始&#xff0c;Percona Backup for MongoDB支持物理和逻辑备份和恢复&#xff0c;仅支持对逻辑备份进行时间点恢复。 …

linux支持ipv6

1. kernel config [*] Networking support ---> Networking options ---> <*> The IPv6 protocol ---> 2. test 2.1 /proc/net/if_inet6 查看/proc/net/if_inet6文件是否存在以确定你的系统是否支持IPv6。 如果没有&#xff0c;可尝试如下命令加载IPv6模…

磺化氰化物7酪胺Sulfo-Cy7 TSA,Sulfo-Cyanine7 TSA,Sulfo-Cyanine7 Tyramide

Sulfo-Cyanine7 Tyramide&#xff0c;Sulfo-Cy7 TSA&#xff0c;Sulfo-Cyanine7 TSA&#xff0c;磺酸基-花青素Cy7 酪酰胺产品结构&#xff1a; 产品规格&#xff1a; 1.Packaging specification&#xff1a;5mg, 10mg, 25mg, flexible packaging, including 100mg packaging a…

11.AOP之注解配置

1.使用IDEA创建工程 2.引入项目使用的依赖 <dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.2.RELEASE</version></dependency><depend…

一、计算机网络体系结构(一)计算机网络概述

目录 1.1计算机网络的概念、组成与功能 1.2计算机网络的分类 1.2.1按分布范围分类 1.2.2按传输技术分类 1.2.3按拓扑结构分类 1.2.4按使用者分类 1.2.5按交换技术分类 1.2.6按传输介质分类 1.3计算机网络的主要性能指标 1.1计算机网络的概念、组成与功能 计算机网络的…

PHP单商户视频号对接流程

一、序关联至对应视频号&#xff0c;并在视频号带货直播中使用。 首先&#xff0c;商家需要在微信后台申请自定义版交易组件权限&#xff0c;申请成功后&#xff0c;可以将小程 二、申请开通商户号 等商户号审核之后在操作一下步骤接口调用&#xff08;pro为例&#xff09; 实…

k8s ~ 数据存储、安全认证、DashBoard。

k8s ~ 数据存储。 文章目录k8s ~ 数据存储。8.1 基本存储。8.1.1 EmptyDir。8.1.2 HostPath。8.1.3 NFS。8.2 高级存储。8.2.1 PV。8.2.2 PVC。8.2.3 生命周期。8.3 配置存储。8.3.1 ConfigMap。8.3.2 Secret。9. 安全认证。9.1 访问控制概述。9.2 认证管理9.3 授权管理。9.4 准…

Flink窗口(Flink Window)

上一篇flink watermark讲到Flink 中事件时间和水位线的概念&#xff0c;那它们有什么具体应用呢&#xff1f;当然是做基于时间的处理计算了。其中最常见的场景&#xff0c;就是窗口聚合计算。 之前我们已经了解了 Flink 中基本的聚合操作。在流处理中&#xff0c;我们往…