单片机基础知识 07

news2025/1/18 4:43:12

一. 键盘检测

键盘分为编码键盘非编码键盘

编码键盘 :键盘上闭合键的识别由专用的硬件编码器实现,并产生键编码号或者键值,如计算机键盘。

非编码键盘:靠软件编程来识别。

在单片机组成的各种系统中,用的较多的是非编码键盘。编码键盘又分为独立键盘行列式键盘矩阵式键盘)。

1. 独立键盘

单片机系统中常见的几种按键:弹性按键,贴片按键,自锁按键

编写单片机的键盘检测程序时,一般在检测按下时加入去抖延时,检测松手时就不用加了。
在这里插入图片描述
案例1:用数码管的前两位显示一个十进制数,变化范围为00-59,开始时显示00,每按下S2键1次,数值加1;每按下S3键1次,数值减1;每按下S4键1次数值归零;按下S5键1次,利用定时器功能使数值开始自动每秒加1,再次按下S5键,数值停止自动加1,保持显示原数。

#include <reg52.h>
#define  uchar unsigned char
#define uint unsigned int

sbit key1 = P3^4;
sbit key2 = P3^5;
sbit key3 = P3^6;
sbit key4 = P3^7;
sbit dula = P2^6;  //U1锁存器的锁存端
sbit wela = P2^7;  //U2锁存器的锁存端

uchar code table[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

void delayms(uint);
uchar numt0, num;

/***数码管显示函数***/
void display(uchar numdis)
{
	uchar shi,ge;
	shi = numdis/10;
	he = numdis%10;
	
	dula = 1;
	P0 = table[shi]; //送十位段选数据
	dula = 0;
	P0 = 0xff;/*送位选数据前关闭所有显示,
		防止打开位选锁存时原来段选数据通过位选锁存器造成混乱*/
	wela = 1;
	P0 = 0xfe; //送位选数据
	wela = 0;
	delayms(5); 

	dula = 1;
	P0 = table[ge]; //送个位段选数据
	dula = 0;
	P0 = 0xff;
	wela = 1;
	P0 = 0xfd;
	wela = 0;
	delayms(5);	
}

/***延时函数***/
void delayms(uint xms)
{
	uint i ,j;
	for(i= xms; i>0 ; i--)
	{
		for(j =110;i>0;j--);
	}
}

/***初始化函数***/
void init()
{
	TMOD = 0x01; //设置定时器0为工作方式1
	TH0 = (65536-45872)/256; //装初值50ms一次中断
	TL0 = (65536-45872)%256; 
	EA = 1; //开总中断
	ET0 = 1; //开定时器0中断
} 

/***键盘扫描函数***/
void keyscan()
{
	if(0 == key1)
	{
		delayms(10);
		if(0 == key1)
		{
			num++;
			if(60 == num)
			{
				num = 0
			}
			while(!key1); //等待按键释放
		}
	}

	if(0 == key2)
	{
		delayms(10);
		if(0 == key2)
		{
			if(0 == num)
			{
				num = 60
			}
			num--;
			while(!key2); 
		}
	}

	if(0 == key3)
	{
		delayms(10);
		if(0 == key3)
		{
			num = 0;
			while(!key3);
		}
	}

	if(0 == key4)
	{
		delayms(10);
		if(0 == key4)
		{
			while(!key4); 
			TR0 = ~TR0;  //启动或者停止定时器0
		}
	}
}

void main()
{
	init();
	while(1)
	{
		keyscan();
		display(num);
	}
}

/***定时器中断函数***/
void T0_time() interrupt 1
{
	TH0 = (65536-45872)/256; //重装初值
	TL0 = (65536-45872)%256; 
	numt0++;
	if(20 == numt0)
	{
		numt0 = 0;
		num++; 
		if(60 == num)
		{
			num = 0;
		}	
	}
}

2. 矩阵键盘

独立键盘有一端固定为低电平,单片机写程序检测时比较方便。而矩阵键盘两端都与单片机I/O口相连,因此在检测时需人为通过单片机I/O口送出低电平。

检测时,先送一列为低电平,其余几列全为高电平(此时我们确定了列数),然后立即轮流检测一次各行是否有低电平,若检测到某一行为低电平(这时我们又确定了行数),则我们可以确定当前被按下的键是哪一行哪一列的。用同样的方法轮流送各列一次低电平,再轮流检测一次各行是否变为低电平,这样即可检测完所有的按键,当有按键被按下时便可判断出按下的键是哪一个键。

案例2:实验板上电时,数码管不显示,顺序按下矩阵键盘后,在数码管上依次显示0-F,6个数码管同时静态显示即可。
其中,矩阵键盘的4行分别与单片机的P3.0-P3.3相连,4列分别与P3.4-P3.7相连。

#include <reg52.h>
#define  uchar unsigned char
#define uint unsigned int

sbit dula = P2^6;  //U1锁存器的锁存端
sbit wela = P2^7;  //U2锁存器的锁存端

uchar code table[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

/***延时函数***/
void delayms(uint xms)
{
	uint i ,j;
	for(i= xms; i>0 ; i--)
	{
		for(j =110;i>0;j--);
	}
}

/***数码管显示函数***/
void display(uchar num)
{
	P0 = table[num]; //显示函数只送段选数据
	dula = 1;
	dula = 0; 
}

/***矩阵键盘扫描函数***/
void matrixkeyscan()
{
	 uchar temp,key;

	//第一行
	 P3 = 0xfe;
	 temp = P3;
	 temp = temp & 0xf0;  //用于判断temp高4位是否有0
	 if(0xf0 != temp)  /*temp的高4位数据实际上就是矩阵键盘的
				 4个列线,若temp不等于0xf0,说明有键被按下*/
	 {
		delayms(10); //延时去抖
		temp = P3;
		temp = temp & 0xf0;
		if(0xf0 != temp)
		{
			temp =P3;
			switch(temp)
			{
				case 0xee:
					key = 0;
					break;
			    case 0xde:
			    	key = 1;
			    	break;
			    case 0xbe:
			    	key =2;
			    	break;
			    case 0x7e:
			    	key = 3;
			    	break;
			}
			while(temp!=0xf0) //等待按键释放
			{
				temp = P3;
				temp = temp & 0xf0;
			}
			display(key); //显示
		}
	 }
		
	 //第2行
	 P3 = 0xfd;
	 temp = P3;
	 temp = temp & 0xf0;
	 if(0xf0 != temp)
	 {
		delayms(10);
		temp = P3;
		temp = temp & 0xf0;
		if(0xf0 != temp)
		{
			temp =P3;
			switch(temp)
			{
				case 0xed:
					key = 4;
					break;
			    case 0xdd:
			    	key = 5;
			    	break;
			    case 0xbd:
			    	key =6;
			    	break;
			    case 0x7d:
			    	key = 7;
			    	break;
			}
			while(temp!=0xf0) //等待按键释放
			{
				temp = P3;
				temp = temp & 0xf0;
			}
			display(key); //显示
		}
	 }

	//第3行
	 P3 = 0xfb;
	 temp = P3;
	 temp = temp & 0xf0;
	 if(0xf0 != temp)
	 {
		delayms(10);
		temp = P3;
		temp = temp & 0xf0;
		if(0xf0 != temp)
		{
			temp =P3;
			switch(temp)
			{
				case 0xeb:
					key = 8;
					break;
			    case 0xdb:
			    	key = 9;
			    	break;
			    case 0xbb:
			    	key = 10;
			    	break;
			    case 0x7b:
			    	key = 11;
			    	break;
			}
			while(temp!=0xf0) //等待按键释放
			{
				temp = P3;
				temp = temp & 0xf0;
			}
			display(key); //显示
		}
	 }

	//第4行
	P3 = 0xf7;
	 temp = P3;
	 temp = temp & 0xf0;
	 if(0xf0 != temp)
	 {
		delayms(10);
		temp = P3;
		temp = temp & 0xf0;
		if(0xf0 != temp)
		{
			temp =P3;
			switch(temp)
			{
				case 0xe7:
					key = 12;
					break;
			    case 0xd7:
			    	key = 13;
			    	break;
			    case 0xb7:
			    	key =14;
			    	break;
			    case 0x77:
			    	key = 15;
			    	break;
			}
			while(temp!=0xf0) //等待按键释放
			{
				temp = P3;
				temp = temp & 0xf0;
			}
			display(key); //显示
		}
	 }	
}

void main()
{
	P0 = 0; //关闭所有数码管段选
	dula = 1;
	dula = 0;
	P0 = 0xc0; //位选中所有数码管
	wela = 1;
	wela = 0;

	while(1)
	{
      matrixkeyscan(); //不停调用键盘扫描程序
	}
}

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

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

相关文章

Echarts-知识图谱

Echarts-知识图谱 demo地址 打开CodePen 效果 思路 1. 生成根节点 2. 根据子节点距离与根节点的角度关系&#xff0c;生成子节点坐标&#xff0c;进而生成子节点 3. 从子节点上按角度生成对应的子节点 4. 递归将根节点与每一层级子节点连线核心代码 定义节点配置 functio…

将 Notepad++ 添加到右键菜单

目录 方式一&#xff1a;添加注册表&#xff08;手动&#xff09; 方式二&#xff1a;添加注册表&#xff08;一键添加&#xff09; 有时安装了notepad后&#xff0c;在txt文件上右键&#xff0c;在弹出的菜单栏中没有【通过 Notepad 打开】&#xff0c;如下&#xff1a; 这…

5. Django 探究CBV视图

5. 探究CBV视图 Web开发是一项无聊而且单调的工作, 特别是在视图功能编写方面更为显著. 为了减少这种痛苦, Django植入了视图类这一功能, 该功能封装了视图开发常用的代码, 无须编写大量代码即可快速完成数据视图的开发, 这种以类的形式实现响应与请求处理称为CBV(Class Base…

OSPF综合大实验

1、R4为ISP&#xff0c;其上只配置IP地址&#xff1b;R4与其他所直连设备间均使用公有IP&#xff1b; 2、R3-R5、R6、R7为MGRE环境&#xff0c;R3为中心站点&#xff1b; 3、整个OSPF环境IP基于172.16.0.0/16划分&#xff1b;除了R12有两个环回&#xff0c;其他路由器均有一个环…

Reka Core, Flash, and Edge: A Series of Powerful Multimodal Language Models

Reka Core, Flash, and Edge: A Series of Powerful Multimodal Language Models 相关链接&#xff1a;arxiv 关键字&#xff1a;Multimodal Language Models、Reka Core、Reka Flash、Reka Edge、State-of-the-Art 摘要 我们介绍了 Reka Core、Flash 和 Edge&#xff0c;这是…

VOJ islands打炉石传说 题解 二进制枚举

islands打炉石传说 代码 #include <bits/stdc.h> using namespace std; typedef long long ll; struct node {int cost, d, w; }; int main() {ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int n; // n张牌cin >> n;vector<node> v(n);for (int i 0; …

【深度学习实战(9)】三种保存和加载模型的方式

一、state_dict方式&#xff08;推荐&#xff09; torch.save(model.state_dict(), PATH)model YourModel() model.load_state_dict(torch.load(PATH)) model.eval()记住一定要使用model.eval()来固定dropout和归一化层&#xff0c;否则每次推理会生成不同的结果。 二、整个…

校园小情书微信小程序源码/社区小程序前后端开源/校园表白墙交友小程序

校园小情书前端代码&#xff0c;好玩的表白墙、树洞、校园论坛&#xff0c;可独立部署&#xff0c;也可以使用我部署的后台服务&#xff0c;毕业设计的好项目。 搭建教程&#xff1a; 一、注册管理后台 1、登录小情书站点进行注册&#xff1a;https://你的域名 2、注册成功…

Mathtype用法记录

常用写法 公式编号 给公式插入编号的方法 手动修改公式编号为指定值 例如编号(8.3.1)修改为(8.3.7)&#xff0c;即章、节号不变&#xff0c;公式序号改为7。 可修改编号的域代码&#xff0c;比如(8.3.1)的域代码为&#xff1a; { { MACROBUTTON MTPlaceRef \* MERGEFORMAT…

Redis 缓存预热、预热数据选取策略、缓存保温、性能边界

缓存预热 热点数据预热&#xff1a;根据业务分析或统计数据&#xff0c;确定热点数据&#xff08;经常被访问的数据&#xff09;&#xff0c;并将其提前加载到Redis缓存中。可以根据访问频率、访问量或其他业务指标来确定热点数据。定时预热&#xff1a;可以设置定时任务&…

Python兼职:只需要一台电脑宅在家,轻松实现月入过万!

Python兼职副业 Python是一种简单易学、高效强大的编程语言&#xff0c;正变成越来越多人选择的热门技能。不论你是否有编程基础&#xff0c;在学习Python的道路上&#xff0c;坚持每天投入2小时&#xff0c;你将看到巨大的回报。 学习Python不仅可以为你提供更多就业机会&am…

6.GodotCanvasItem、Node2D及自定义节点

CanvasItem节点 CanvasItem节点&#xff0c;CanvasItem -> Node&#xff0c;所以CanvasItem继承了Node的所有功能Canvas是画布的意思&#xff0c;所以CanvasItem代表了就是可以被绘制的节点&#xff0c;可以设置可视化界面和材质的颜色所有的2D节点和GUI节点都继承于CanvasI…

使用docker配置CCM-SLAM

一.Docker环境配置 1.拉取Docker镜像 sudo docker pull ubuntu:18.04拉取的为ununtu18版本镜像&#xff0c;环境十分干净&#xff0c;可以通过以下命令查看容器列表 sudo docker images 如果想删除多余的docker image&#xff0c;可以使用指令 sudo docker rmi -f <id&g…

openplc Linux 使用modbus RTU 从机通讯

1.Linux 环境下&#xff0c;openplc 默认使用的是modbus tcp协议通信。 想要使用串口 modbus rtu 通讯可以通过在runtime中添加SlaveDevices从机设备 2.添加设备&#xff0c;分配地址。 左边添加串口配置&#xff0c;右边是需要通讯的地址&#xff0c;从机地址都是从100开始&am…

了解光纤的最大损耗

在电信和数据传输领域&#xff0c;保持最佳的网络性能和可靠性至关重要。 影响网络完整性的关键因素之一是光纤中的信号丢失。信号损耗&#xff0c;也称为衰减损耗或光纤衰减&#xff0c;测量光缆输入和输出之间的光损耗量。本文将深入探讨光纤中的主要损耗&#xff0c;并指导您…

【python】计算水仙花数

【python】计算水仙花数 "水仙花数"是指一个3位数&#xff0c;它的三个位上的数字的3次幂之和等于它本身。例如&#xff0c;"153"就是一个水仙花数&#xff0c;因为1^3 5^3 3^3 153。以下是一个Python代码示例&#xff0c;用于计算并打印出所有的三位数…

抹机王的使用教程以及常见问题

首先请确保你已经正常安装了XPosed/EDXP/LSP框架并已激活抹机王模块&#xff0c;其中XP和EDXP模块均只需要框架内激活抹机王并重启即可&#xff0c;LSPosed注意作用域需要勾选上自己想要修改的APP&#xff08;如果你还是一意孤行只勾选系统框架那改机完全没用就是你自己的想法了…

性能测试-数据库优化二(SQL的优化、数据库拆表、分表分区,读写分离、redis、数据库监控)

数据库优化 explain select 重点&#xff1a; type类型&#xff0c;rows行数&#xff0c;extra SQL的优化 在写on语句时&#xff0c;将数据量小的表放左边&#xff0c;大表写右边where后面的条件尽可能用索引字段&#xff0c;复合索引时&#xff0c;最好按复合索引顺序写wh…

LeetCode 57—— 插入区间

阅读目录 1. 题目2. 解题思路3. 代码实现 1. 题目 2. 解题思路 第一步&#xff0c;我们先寻找新区间和原始区间列表的重叠部分。 假设新区间为 [ x 1 , x 2 ] [x_1, x_2] [x1​,x2​]&#xff0c;原始区间列表中的其中一个区间为 [ y 1 , y 2 ] [y_1, y_2] [y1​,y2​]&…

C++学习 <day1-C++介绍基础>

一、什么是C 1. C介绍 C由程序员控制生命周期&#xff08;性能提升&#xff09;&#xff1b;C数据存储等方式由硬件决定&#xff08;性能提升&#xff09;&#xff1b; C11 引入了 type_traits/range&#xff1b; C17 删除了 auto_ptr&#xff1b; 二、C开发环境&相关工…