stm32f103c8t6之4x4矩阵按键

news2024/11/23 20:33:02
基于普中精灵开发板
1、矩阵按键原理

当我们需要使用较多的按键时,单片机的IO口可能不够用,这是就需要使用矩阵按键。

对应IO口如下:

 步骤解析:

1、全部按键都没有按下时,全行IO为低电平(全列对应的IO设置为下拉低电平)。
2、第一行IO口全为高电平,检测对应列的IO口电平,2、3、4行对应IO为电平。
3、第二行IO口全为高电平,检测对应列的IO口电平,1、3、4行对应IO为电平。
4、第三行IO口全为高电平,检测对应列的IO口电平,1、2、4行对应IO为电平。
5、第四行IO口全为高电平,检测对应列的IO口电平,1、2、3行对应IO为电平。

 ---------------------------------------------------------******----------------------------------------------------------------

一、第一行IO口全为高电平,检测对应列的IO口电平,2、3、4行对应的IO为低电平,那么只需要读取列对应的4个IO口电平,就可以判断是第一行第几个按键按下。因为按下时按键连通,则对应的按键的列引脚电平就为高电平(列对应的io为电平)。

注意:行对应的引脚为推挽输出,列对应的引脚为下拉(默认低电平0)

 例如,当第一行第一个按键按下时,KEY_L1对应的IO电平将从0变为1,如下图所示。

 二、第二行IO口全为高电平,检测对应列的IO口电平,1、3、4行对应IO为电平。同样的思路进行编程

三、 按键扫描函数:
u8 KEY_Matrix_Scan(void)
{
    u8 col1,col2,col3,col4;//保存电平状态
	u8 key_value;//保存键值
	
	//1、没有检测到按键按下
	GPIO_SetBits(KEY_MATRIX_H1_PORT,KEY_MATRIX_H1_PIN);
	GPIO_SetBits(KEY_MATRIX_H2_PORT,KEY_MATRIX_H2_PIN);
	GPIO_SetBits(KEY_MATRIX_H3_PORT,KEY_MATRIX_H3_PIN);
	GPIO_SetBits(KEY_MATRIX_H4_PORT,KEY_MATRIX_H4_PIN);	
	//全部都没有按下,返回0
	if((GPIO_ReadInputDataBit(KEY_MATRIX_L1_PORT,KEY_MATRIX_L1_PIN)|
		GPIO_ReadInputDataBit(KEY_MATRIX_L2_PORT,KEY_MATRIX_L2_PIN)|
		GPIO_ReadInputDataBit(KEY_MATRIX_L3_PORT,KEY_MATRIX_L3_PIN)|
	    GPIO_ReadInputDataBit(KEY_MATRIX_L4_PORT,KEY_MATRIX_L4_PIN))==0)
	{
	    return 0;
	}
	//有按下,但没有检测到,同样返回0
	else
	{
	    delay_ms(5);//按键消抖
		if((GPIO_ReadInputDataBit(KEY_MATRIX_L1_PORT,KEY_MATRIX_L1_PIN)|
			GPIO_ReadInputDataBit(KEY_MATRIX_L2_PORT,KEY_MATRIX_L2_PIN)|
			GPIO_ReadInputDataBit(KEY_MATRIX_L3_PORT,KEY_MATRIX_L3_PIN)|
			GPIO_ReadInputDataBit(KEY_MATRIX_L4_PORT,KEY_MATRIX_L4_PIN))==0)
		{
			return 0;
		}
	}
	
	//2、第一行检测
	GPIO_SetBits(KEY_MATRIX_H1_PORT,KEY_MATRIX_H1_PIN);
	GPIO_ResetBits(KEY_MATRIX_H2_PORT,KEY_MATRIX_H2_PIN);
	GPIO_ResetBits(KEY_MATRIX_H3_PORT,KEY_MATRIX_H3_PIN);
	GPIO_ResetBits(KEY_MATRIX_H4_PORT,KEY_MATRIX_H4_PIN);
	//记录电平
	col1=GPIO_ReadInputDataBit(KEY_MATRIX_L1_PORT,KEY_MATRIX_L1_PIN);
	col2=GPIO_ReadInputDataBit(KEY_MATRIX_L2_PORT,KEY_MATRIX_L2_PIN);
	col3=GPIO_ReadInputDataBit(KEY_MATRIX_L3_PORT,KEY_MATRIX_L3_PIN);
	col4=GPIO_ReadInputDataBit(KEY_MATRIX_L4_PORT,KEY_MATRIX_L4_PIN);
	if(col1==1&&col2==0&&col3==0&&col4==0)
	    key_value=1;//第一行第一个按键按下了
	if(col1==0&&col2==1&&col3==0&&col4==0)
	    key_value=2;//第一行第二个按键按下了
	if(col1==0&&col2==0&&col3==1&&col4==0)
	    key_value=3;//第一行第三个按键按下了
	if(col1==0&&col2==0&&col3==0&&col4==1)
	    key_value=4;//第一行第四个按键按下了
	//需判断按键是否松开,当某按键按下时值为1大于0为真,继续等待;当按键松开都没有按下时值为0>0为假,退出等待
	while((GPIO_ReadInputDataBit(KEY_MATRIX_L1_PORT,KEY_MATRIX_L1_PIN)|
			GPIO_ReadInputDataBit(KEY_MATRIX_L2_PORT,KEY_MATRIX_L2_PIN)|
			GPIO_ReadInputDataBit(KEY_MATRIX_L3_PORT,KEY_MATRIX_L3_PIN)|
			GPIO_ReadInputDataBit(KEY_MATRIX_L4_PORT,KEY_MATRIX_L4_PIN))>0);
	
	//3、第二行检测
	GPIO_ResetBits(KEY_MATRIX_H1_PORT,KEY_MATRIX_H1_PIN);
	GPIO_SetBits(KEY_MATRIX_H2_PORT,KEY_MATRIX_H2_PIN);
	GPIO_ResetBits(KEY_MATRIX_H3_PORT,KEY_MATRIX_H3_PIN);
	GPIO_ResetBits(KEY_MATRIX_H4_PORT,KEY_MATRIX_H4_PIN);
	//记录电平
	col1=GPIO_ReadInputDataBit(KEY_MATRIX_L1_PORT,KEY_MATRIX_L1_PIN);
	col2=GPIO_ReadInputDataBit(KEY_MATRIX_L2_PORT,KEY_MATRIX_L2_PIN);
	col3=GPIO_ReadInputDataBit(KEY_MATRIX_L3_PORT,KEY_MATRIX_L3_PIN);
	col4=GPIO_ReadInputDataBit(KEY_MATRIX_L4_PORT,KEY_MATRIX_L4_PIN);
	if(col1==1&&col2==0&&col3==0&&col4==0)
	    key_value=5;//第二行第一个按键按下了
	if(col1==0&&col2==1&&col3==0&&col4==0)
	    key_value=6;//第二行第二个按键按下了
	if(col1==0&&col2==0&&col3==1&&col4==0)
	    key_value=7;//第二行第三个按键按下了
	if(col1==0&&col2==0&&col3==0&&col4==1)
	    key_value=8;//第二行第四个按键按下了
	//需判断按键是否松开,当某按键按下时值为1大于0为真,继续等待;当按键松开都没有按下时值为0>0为假,退出等待
	while((GPIO_ReadInputDataBit(KEY_MATRIX_L1_PORT,KEY_MATRIX_L1_PIN)|
			GPIO_ReadInputDataBit(KEY_MATRIX_L2_PORT,KEY_MATRIX_L2_PIN)|
			GPIO_ReadInputDataBit(KEY_MATRIX_L3_PORT,KEY_MATRIX_L3_PIN)|
			GPIO_ReadInputDataBit(KEY_MATRIX_L4_PORT,KEY_MATRIX_L4_PIN))>0);
	
	//4、第三行检测
	GPIO_ResetBits(KEY_MATRIX_H1_PORT,KEY_MATRIX_H1_PIN);
	GPIO_ResetBits(KEY_MATRIX_H2_PORT,KEY_MATRIX_H2_PIN);
	GPIO_SetBits(KEY_MATRIX_H3_PORT,KEY_MATRIX_H3_PIN);
	GPIO_ResetBits(KEY_MATRIX_H4_PORT,KEY_MATRIX_H4_PIN);
	//记录电平
	col1=GPIO_ReadInputDataBit(KEY_MATRIX_L1_PORT,KEY_MATRIX_L1_PIN);
	col2=GPIO_ReadInputDataBit(KEY_MATRIX_L2_PORT,KEY_MATRIX_L2_PIN);
	col3=GPIO_ReadInputDataBit(KEY_MATRIX_L3_PORT,KEY_MATRIX_L3_PIN);
	col4=GPIO_ReadInputDataBit(KEY_MATRIX_L4_PORT,KEY_MATRIX_L4_PIN);
	if(col1==1&&col2==0&&col3==0&&col4==0)
	    key_value=9;//第三行第一个按键按下了
	if(col1==0&&col2==1&&col3==0&&col4==0)
	    key_value=10;//第三行第二个按键按下了
	if(col1==0&&col2==0&&col3==1&&col4==0)
	    key_value=11;//第三行第三个按键按下了
	if(col1==0&&col2==0&&col3==0&&col4==1)
	    key_value=12;//第三行第四个按键按下了
	//需判断按键是否松开,当某按键按下时值为1大于0为真,继续等待;当按键松开都没有按下时值为0>0为假,退出等待
	while((GPIO_ReadInputDataBit(KEY_MATRIX_L1_PORT,KEY_MATRIX_L1_PIN)|
			GPIO_ReadInputDataBit(KEY_MATRIX_L2_PORT,KEY_MATRIX_L2_PIN)|
			GPIO_ReadInputDataBit(KEY_MATRIX_L3_PORT,KEY_MATRIX_L3_PIN)|
			GPIO_ReadInputDataBit(KEY_MATRIX_L4_PORT,KEY_MATRIX_L4_PIN))>0);
	
	//5、第四行检测
	GPIO_ResetBits(KEY_MATRIX_H1_PORT,KEY_MATRIX_H1_PIN);
	GPIO_ResetBits(KEY_MATRIX_H2_PORT,KEY_MATRIX_H2_PIN);
	GPIO_ResetBits(KEY_MATRIX_H3_PORT,KEY_MATRIX_H3_PIN);
	GPIO_SetBits(KEY_MATRIX_H4_PORT,KEY_MATRIX_H4_PIN);
	//记录电平
	col1=GPIO_ReadInputDataBit(KEY_MATRIX_L1_PORT,KEY_MATRIX_L1_PIN);
	col2=GPIO_ReadInputDataBit(KEY_MATRIX_L2_PORT,KEY_MATRIX_L2_PIN);
	col3=GPIO_ReadInputDataBit(KEY_MATRIX_L3_PORT,KEY_MATRIX_L3_PIN);
	col4=GPIO_ReadInputDataBit(KEY_MATRIX_L4_PORT,KEY_MATRIX_L4_PIN);
	if(col1==1&&col2==0&&col3==0&&col4==0)
	    key_value=13;//第四行第一个按键按下了
	if(col1==0&&col2==1&&col3==0&&col4==0)
	    key_value=14;//第四行第二个按键按下了
	if(col1==0&&col2==0&&col3==1&&col4==0)
	    key_value=15;//第四行第三个按键按下了
	if(col1==0&&col2==0&&col3==0&&col4==1)
	    key_value=16;//第四行第四个按键按下了
	//需判断按键是否松开,当某按键按下时值为1大于0为真,继续等待;当按键松开都没有按下时值为0>0为假,退出等待
	while( (GPIO_ReadInputDataBit(KEY_MATRIX_L1_PORT,KEY_MATRIX_L1_PIN)|
			GPIO_ReadInputDataBit(KEY_MATRIX_L2_PORT,KEY_MATRIX_L2_PIN)|
			GPIO_ReadInputDataBit(KEY_MATRIX_L3_PORT,KEY_MATRIX_L3_PIN)|
			GPIO_ReadInputDataBit(KEY_MATRIX_L4_PORT,KEY_MATRIX_L4_PIN))>0);
	
	return key_value;
}

实验结果:

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

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

相关文章

1060: 无向图的最大度计算

解法&#xff1a; #include<iostream> #include<vector> using namespace std; int arr[100][100]; int main() {int n, max 0;cin >> n;vector<int> sum(n, 0);for (int i 0; i < n; i) {for (int j 0; j < n; j) {cin >> arr[i][j];…

Nginx(简洁版)

基本配置 worker_processes 1; //默认为1&#xff0c;表示开启一个业务进程 events //事件驱动模块&#xff08;&#xff09;{worker_connections 1024; //单个业务进程可接受连接数 } http{include mime.types; // 引入http mime类型&#xff08;在外部已经定义好&#xff0c…

数据链路层(详细版)【02】

接 数据链路层&#xff08;详细版&#xff09;【01】 文章目录 四、以太网MAC层&#xff08;一&#xff09;MAC地址组成&#xff08;1&#xff09;48位MAC地址格式&#xff08;2&#xff09;单播地址 & 多播地址 & 广播地址&#xff08;3&#xff09;全球管理 & 本…

ctfshow web271--web273

web271 laravel5.7反序列化漏洞 define(LARAVEL_START, microtime(true));/* |-------------------------------------------------------------------------- | Register The Auto Loader |-------------------------------------------------------------------------- | |…

OFDM802.11a的FPGA实现(十三)加窗(含verilog和matlab代码)

原文链接&#xff08;相关文章合集&#xff09;&#xff1a;OFDM 802.11a的xilinx FPGA实现 1.前言 添加循环前缀后,对数据还要进行加窗(Windowing)操作。加窗操作可以使OFDM 符号在带宽之外的功率谱密度下降得更快。 2.加窗 对OFDM符号“加窗”意味着令符号周期边缘的幅度…

WHAT - CSS Animationtion 动画系列(二)

目录 一、循环波浪二、关键帧呼应三、关键帧顺接四、利用 transform-origin 做拉伸五、大元素可拆分多个小元素联动六、预留视觉缓冲七、随机感&#xff1a;动画周期设置八、抛物线&#xff1a;两个内外div实现x和y向量运动 今天我们主要学习动画实现要素。 一、循环波浪 利用…

RAG讲解

现有的LLM已经具备了理解、生成、逻辑和记忆能力&#xff0c;RAG(Retrieval Augmented Generation)则是为其套上外挂&#xff0c;使LLM能够访问训练数据来源之外的权威知识库&#xff0c;并生成领域特定的内容&#xff0c;而无须重新训练模型。 RAG的优势 经济高效&#xff1a…

【简单介绍下Sass】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

HTML标签快速入门

文章目录 一、HTML语法规范1.1 基本语法概述1.2 标签关系 二、HTML基本结构标签2.1 第一个HTML网页2.2 基本结构标签总结 三、网页开发工具3.1 文档类型声明标签3.2 lang 语言种类3.3 字符集3.4 总结 四、HTML常用标签4.1 标签语义4.2 标题标签\<h1> - \<h6>&#…

RuvarOA协同办公平台 多处 SQL注入漏洞复现

0x01 产品简介 RuvarOA办公自动化系统是广州市璐华计算机科技有限公司采用组件技术和Web技术相结合,基于Windows平台,构建在大型关系数据库管理系统基础上的,以行政办公为核心,以集成融通业务办公为目标,将网络与无线通讯等信息技术完美结合在一起设计而成的新型办公自动…

NodeMCU ESP8266 操作 SSD1306 OLED显示屏详解(图文并茂)

文章目录 1 模块介绍2 接线介绍3 安装SSD1306驱动库4 源码分析4.1 硬件兼容性4.2 可能存在的问题总结1 模块介绍 我们将在本教程中使用的OLED显示屏是SSD1306型号:单色0.96英寸显示屏,像素为12864,如下图所示。 OLED显示屏不需要背光,这在黑暗环境中会产生非常好的对比度。…

Curator分布式锁

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 分布式锁服务宕机,…

实现二叉树的基本操作

博主主页: 码农派大星. 关注博主带你了解更多数据结构知识 1我们先来模拟创建一个二叉树 public class TestBinaryTreee {static class TreeNode{public char val;public TreeNode left;public TreeNode right;public TreeNode(char val) {this.val val;}}public TreeNode …

Web入门——三栏布局页面

前置知识 内外边距 内边距(padding)&#xff1a; padding是元素边框与其内容之间的空间。也就是说&#xff0c;如果你给一个元素设置了内边距&#xff0c;这个空间会作为元素内容与元素边框之间的缓冲区域。设置内边距会使元素本身变大。例如padding:10px就创建了10像素的空间…

每日OJ题_贪心算法四④_力扣397. 整数替换

目录 力扣397. 整数替换 解析代码 力扣397. 整数替换 397. 整数替换 难度 中等 给定一个正整数 n &#xff0c;你可以做如下操作&#xff1a; 如果 n 是偶数&#xff0c;则用 n / 2替换 n 。如果 n 是奇数&#xff0c;则可以用 n 1或n - 1替换 n 。 返回 n 变为 1 所需…

计算机网络复习-传输层

概念 传输层是进程与进程之间的通信使用端口(Port)来标记不同的网络进程端口(Port)使用16比特位表示(0~65535) UDP协议详解 UDP&#xff1a;用户数据报协议数据报&#xff1a;应用层传输过来的一个完整的数据不合并&#xff0c;不拆分 UDP的头部 UDP特点 UDP是无连接协…

picoCTF-Web Exploitation-Trickster

Description I found a web app that can help process images: PNG images only! 这应该是个上传漏洞了&#xff0c;十几年没用过了&#xff0c;不知道思路是不是一样的&#xff0c;以前的思路是通过上传漏洞想办法上传一个木马&#xff0c;拿到webshell&#xff0c;今天试试看…

【计算机网络】物理层 通信基础、奈氏准则、香农公式 习题2

下列说法中正确的是( )。 A. 信道与通信电路类似&#xff0c;一条可通信的电路往往包含一个信道 B.调制是指把模拟数据转换为数字信号的过程 C. 信息传输速率是指通信信道上每秒传输的码元数 D.在数值上&#xff0c;波特率等于比特率与每符号所含的比特数的比值 信息传输速率&a…

python随机显示四级词汇

python实现一个浮动窗口随机显示四级单词在桌面跑来跑去 实现一个浮动窗体随机显示四级单词在windows桌面置顶移动 tkinter库来创建窗口和显示单词&#xff0c;以及random库来随机选择单词。 使用after方法来定时更新窗口的位置&#xff0c;实现单词窗口的慢慢移动效果 使用…

【Apache Doris】周FAQ集锦:第 3 期

【Apache Doris】周FAQ集锦&#xff1a;第 3 期 SQL问题数据操作问题运维常见问题其它问题关于社区 欢迎查阅本周的 Apache Doris 社区 FAQ 栏目&#xff01; 在这个栏目中&#xff0c;每周将筛选社区反馈的热门问题和话题&#xff0c;重点回答并进行深入探讨。旨在为广大用户和…