【STM32嵌入式系统设计与开发---拓展】——1_10矩阵按键

news2024/9/19 7:28:01

这里写目录标题

  • 1、矩阵按键
  • 2、代码片段分析

1、矩阵按键

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
通过将4x4矩阵按键的每一行依次设为低电平,同时保持其它行为高电平,然后读取所有列的电平状态,可以检测到哪个按键被按下。如果某列变为低电平,说明对应行和列的按键被按下。这样逐行扫描即可确定按键的位置。


2、代码片段分析

/*********************************************************************
 @Function  : 矩阵键盘行列读写操作
 @Parameter : ReadIo  :读输入的IO
							WirteIo :写输出的IO
 @Return    : 行列IO输出状态
**********************************************************************/
uint8_t GPIO_KEY_RW(uint16_t ReadIo,uint16_t WirteIo)
{
  uint16_t Wdata=0,Rdata=0;	
	/* 写操作 */
	KeyBordSetOut(KEY_ALL);               //设置IO
	if(WirteIo==0x0f00)
	   GPIO_SetBits(GPIOE,KEY_LINE);      //写行
	else 
     GPIO_ResetBits(GPIOE,KEY_LIST);    //写列		
     Wdata = GPIO_ReadOutputData(GPIOE);//读输出	
     Wdata &= WirteIo;                  //取有效区域
	
	/* 读操作 */
     KeyBordSetIn(ReadIo);              //设置IO 
     Rdata = GPIO_ReadInputData(GPIOE); //读输入
     Rdata &= ReadIo;                   //取有效区域
	
	/* 状态返回	*/
	   Rdata |= Wdata;                    //合并两次读取的数据
     return (uint8_t)(Rdata>>8);        //移位返回
}

初始化:

Wdata 和 Rdata 初始化为 0。
写操作:

检查 WirteIo 是否为 0x0f00(二进制:0000111100000000):
如果是,则设置 GPIOE 中对应 KEY_LINE 的位(具体位取决于 KEY_LINE 的定义)。
如果不是,则复位 GPIOE 中对应 KEY_LIST 的位(具体位取决于 KEY_LIST 的定义)。
读取 GPIOE 的输出数据到 Wdata。
Wdata 与 WirteIo 进行与操作,保留有效区域的数据。
读操作:

使用 ReadIo 设置IO方向。
读取 GPIOE 的输入数据到 Rdata。
Rdata 与 ReadIo 进行与操作,保留有效区域的数据。
状态返回:

将 Wdata 和 Rdata 进行或操作,合并两次读取的数据。
返回 Rdata 右移8位后的值。
假设按下第一个按键
假设按下的是第一个按键,具体的步骤如下:

初始化:

Wdata = 0
Rdata = 0
写操作:

WirteIo == 0x0f00 假设为真,则设置 GPIOE 对应 KEY_LINE 的位。
读取 GPIOE 输出数据:
假设 GPIOE 输出数据为 0000111100000000(二进制)。
Wdata &= WirteIo:
Wdata = 0000111100000000 & 0000111100000000 = 0000111100000000
读操作:

设置IO方向,具体操作取决于 KeyBordSetIn 函数。
读取 GPIOE 输入数据:
假设按下第一个按键时,GPIOE 输入数据为 0000000100000000(二进制)。
Rdata &= ReadIo:
Rdata = 0000000100000000 & ReadIo(假设 ReadIo 为 0000000100000000),结果 Rdata = 0000000100000000
状态返回:

Rdata |= Wdata:
Rdata = 0000000100000000 | 0000111100000000 = 0000111100000000
返回值:
将 Rdata 右移8位后返回:Rdata >> 8 = 00001111
所以函数返回值为 0x0F(二进制:00001111)


/*********************************************************************
 @Function  : 矩阵键盘键值扫描
 @Parameter : N/A
 @Return    : 键值
**********************************************************************/
uint8_t KeyBoardScan(void)
{
	uint8_t KeyValue=0,Key=0;
	uint8_t a = 0;
	/* 检测键盘是否有按键按下,0x0f表示所有列都未按下 */
	if(GPIO_KEY_RW(KEY_LIST,KEY_LINE)!=0x0f)
	{
			/* 测试列状态 */
		  Key = GPIO_KEY_RW(KEY_LIST,KEY_LINE); // 读取列的状态

			/* 判断列状态并映射为按键值 */
			switch(Key)
			{
				case(0x1F):    // 第一列所有行都按下
						KeyValue = 1; // 对应键值为1
						break;
				case(0x2F):    // 第二列所有行都按下
						KeyValue = 2; // 对应键值为2
						break;
				case(0x4F):    // 第三列所有行都按下
						KeyValue = 3; // 对应键值为3
						break;
				case(0x8F):    // 第四列所有行都按下
						KeyValue = 4; // 对应键值为4
						break;
			}
			
			/* 测试行状态 */
			Key = GPIO_KEY_RW(KEY_LINE,KEY_LIST); // 读取行的状态
		
			/* 判断行状态并映射为按键值 */
			switch(Key)
			{
				case(0x0E):    // 第一行所有列都按下
						KeyValue = KeyValue; // 保持当前列的键值不变
						break;
				case(0x0D):    // 第二行所有列都按下
						KeyValue = KeyValue + 4; // 当前列的键值加4,对应第二行
						break;
				case(0x0B):    // 第三行所有列都按下
						KeyValue = KeyValue + 8; // 当前列的键值加8,对应第三行
						break;
				case(0x07):    // 第四行所有列都按下
						KeyValue = KeyValue + 12; // 当前列的键值加12,对应第四行
						break;
			}

			
			/* 按键松手检测 */
		  while((a < 50) && (Key != 0x00)) // 循环检测按键是否松手,最多检测50次
			{
					delay_ms(5);                          // 延时5毫秒
					Key = GPIO_KEY_RW(KEY_LINE,KEY_LIST); // 再次读取行的状态
					a += 1;                               // 计数器加1
			}
	}
	
	/* 返回键值 */
	return KeyValue;
}

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

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

相关文章

day2 单机并发缓存

文章目录 1 sync.Mutex2 支持并发读写3 主体结构 Group3.1 回调 Getter3.2 Group 的定义3.3 Group 的 Get 方法 4 测试 本文代码地址&#xff1a; https://gitee.com/lymgoforIT/gee-cache/tree/master/day2-single-node 本文是7天用Go从零实现分布式缓存GeeCache的第二篇。 …

go 实现websocket以及详细设计流程过程,确保通俗易懂

websocket简介&#xff1a; WebSocket 是一种网络传输协议&#xff0c;可在单个 TCP 连接上进行全双工通信&#xff0c;位于 OSI 模型的应用层。WebSocket 协议在 2011 年由 IETF 标准化为 RFC 6455&#xff0c;后由 RFC 7936 补充规范。 WebSocket 使得客户端和服务器之间的数…

昇思学习打卡-21-生成式/Diffusion扩散模型

文章目录 Diffusion扩散模型介绍模型推理结果 Diffusion扩散模型介绍 关于扩散模型&#xff08;Diffusion Models&#xff09;有很多种理解&#xff0c;除了本文介绍的离散时间视角外&#xff0c;还有连续时间视角、概率分布转换视角、马尔可夫链视角、能量函数视角、数据增强…

《样式设计003:布局-自定义view模块》

描述&#xff1a;在开发小程序过程中&#xff0c;发现一些不错的案例&#xff0c;平时使用也比较多&#xff0c;稍微总结了下经验&#xff0c;以下内容可以直接复制使用&#xff0c;希望对大家有所帮助&#xff0c;废话不多说直接上干货&#xff01; 一、布局-自定义view模块 …

el-popover嵌套select弹窗点击实现自定义关闭

需求 el-popover弹窗内嵌套下拉选择框&#xff0c;点击el-popover弹出外部区域需关闭弹窗&#xff0c;点击查询、重置需关闭弹窗&#xff0c; 实现 根据需求要自定义弹窗的关闭和显示&#xff0c;首先想到的是visible属性&#xff0c;在实现过程中经过反复的测验&#xff0…

服务级别协议SLA与运营水平协议OLA

使用美团或饿了么在线订餐时&#xff0c;您将体验到即时的送餐提醒服务。首先&#xff0c;选择您想要的食品。系统会根据餐厅与您的位置、所选食品的种类&#xff0c;以及下单的具体时间&#xff0c;计算预计的等待时间和送餐费用&#xff0c;并将这些信息与您共享。这种信息的…

剖析SGI-STL二级空间配置器

概述 SGI-STL与C标准库提供的STL一样&#xff0c;都通过空间配置器allocator来申请或释放容器的空间。空间配置器的作用可以参考&#xff1a;浅谈C空间配置器allocator及其重要性 // C标准库的vector template < class T, class Alloc allocator<T> > class vec…

混淆专题一——简单AA,JJ,JSFuck混淆处理办法

以AA混淆为例 网址&#xff1a;Scrape | NBA 想要获取球员的信息&#xff0c;但找不到包。 刷新页面&#xff0c;main.js中找到混淆的代码&#xff0c;这串混淆代码就是球员信息。 如何处理&#xff1a; 复制下来&#xff0c;去除最后的笑脸 (_)&#xff0c;然后在控制台打…

启智集装箱箱号识别技术,更高效快捷

在当今这个信息技术高速发展的时代&#xff0c;集装箱箱号识别技术在全球物流领域扮演着至关重要的角色。随着物流行业的不断壮大和复杂化&#xff0c;对集装箱箱号识别的准确性、效率性和便捷性提出了更高的要求。启智集装箱箱号识别技术应运而生&#xff0c;以其高效快捷的特…

python-快速上手爬虫

目录 前言 爬虫需谨慎&#xff0c;切勿从入门到入狱&#xff01; 一点小小的准备工作 直接上手爬取网页 1.获取UA伪装 2.获取url 3.发送请求 4.获取数据并保存 总结 前言 爬虫需谨慎&#xff0c;切勿从入门到入狱&#xff01; 一点小小的准备工作 对pip进行换源&#xf…

【EI检索】第二届机器视觉、图像处理与影像技术国际会议(MVIPIT 2024)

一、会议信息 大会官网&#xff1a;www.mvipit.org 官方邮箱&#xff1a;mvipit163.com 会议出版&#xff1a;IEEE CPS 出版 会议检索&#xff1a;EI & Scopus 检索 会议地点&#xff1a;河北张家口 会议时间&#xff1a;2024 年 9 月 13 日-9 月 15 日 二、征稿主题…

vue3前端开发-小兔鲜项目-面包屑导航的渲染

vue3前端开发-小兔鲜项目-面包屑导航的渲染&#xff01;今天来完成&#xff0c;一级分类页面顶部&#xff0c;面包屑导航的渲染。 1&#xff1a;完善好一级页面内的基础模块代码。 <script setup> import {getCategoryAPI} from /apis/category import {ref,onMounted} …

【知识蒸馏】YOLO object detection 逻辑蒸馏

YOLO检测蒸馏 和分类和分割蒸馏的差异&#xff1a; 由于YOLOv3检测框的位置输出为正无穷到负无穷的连续值&#xff0c;和上面将的分类离散kdloss不同&#xff0c;而且由于yolo是基于anchor的one stage模型&#xff0c;head out中99%都是背景预测。 Object detection at 200 F…

【论文阅读笔记】Hierarchical Neural Coding for Controllable CAD Model Generation

摘要 作者提出了一种CAD的创新生成模型&#xff0c;该模型将CAD模型的高级设计概念表示为从全局部件排列到局部曲线几何的三层神经代码的层级树&#xff0c;并且通过指定目标设计的代码树来控制CAD模型的生成或完成。具体而言&#xff0c;一种带有“掩码跳过连接”的向量量化变…

【BUG】已解决:To update, run: python.exe -m pip install --upgrade pip

To update, run: python.exe -m pip install --upgrade pip 目录 To update, run: python.exe -m pip install --upgrade pip 【常见模块错误】 解决办法&#xff1a; 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&…

「MQTT over QUIC」与「MQTT over TCP」与 「TCP 」通信测试报告

一、结论 在实车5G测试中「MQTT Over QUIC」整体表现优于「TCP」&#xff0c;可在系统架构升级时采用MQTT Over QUIC替换原有的TCP通讯&#xff1b;从实现原理上基于QUIC比基于TCP在弱网、网络抖动导致频繁重连场景延迟更低。 二、测试方案 网络类型&#xff1a;实车5G、实车…

FPGA-计数器

前言 之前一直说整理点FPGA控制器应用的内容&#xff0c;今天就从计数器这个在时序逻辑中比较重要的内容开始总结一下&#xff0c;主要通过还是通过让一个LED闪烁这个简单例子来理解。 寄存器 了解计数器之前先来认识一下寄存器。寄存器是时序逻辑设计的基础。时序逻辑能够避…

Android C++系列:Linux信号(三)

可重入函数 不含全局变量和静态变量是可重入函数的一个要素可重入函数见man 7 signal在信号捕捉函数里应使用可重入函数在信号捕捉函数里禁止调用不可重入函数例如:strtok就是一个不可重入函数,因为strtok内部维护了一个内部静态指针,保存上一 次切割到的位置,如果信号的捕捉…

android Invalid keystore format

签名的时候提示:Invalid keystore format. 点击info查看更多日志 再点击一次 stactrace 查看更多提示 提示&#xff1a;javaio异常 基本是jdk版本的问题&#xff0c;高jdk版本打的key&#xff0c;在低版本jdk开发环境上无法使用。 查看自己的key信息 keytool -list -v -keys…

Redis实现用户会话

1.分布式会话 (1)什么是会话 会话Session代表的是客户端与服务器的一次交互过程&#xff0c;这个过程可以是连续也可以是时断时续的。曾经的Servlet时代&#xff08;jsp&#xff09;&#xff0c;一旦用户与服务端交互&#xff0c;服务器tomcat就会为用户创建一个session&#…