嵌入式进阶——矩阵键盘
🎬 秋野酱:《个人主页》
🔥 个人专栏:《Java专栏》《Python专栏》
⛺️心若有所向往,何惧道阻且长
文章目录
- 矩阵按键
- 原理图
- 按键状态检测
- 单行按键状态检测
- 多行按键状态检测
- 状态记录
- 状态优化
- 循环优化
矩阵按键
矩阵键盘是一种常见的数字输入设备,由多行多列的按键组成。每个按键都有一个唯一的行列坐标,通过行列坐标可以确定按键的编号,从而实现对数字或字母的输入。
原理图
矩阵键盘的基本结构包括按键、行引脚和列引脚。按键一般是机械按键或触摸按键,行引脚和列引脚分别与矩阵键盘的行和列相连,用于检测按键的输入状态。
按键状态检测
单个按键状态检测
● 输出端的电平
● 输入端的状态
● 按键抬起
通过按键抬起时的状态,我们分析输入端的电平信号,来确定抬起时输入端的默认电平状态。
通过按键按下时的状态,我们分析输入端的电平信号,来确定按下时输入端的默认电平状态。
通过分析确认,默认输出端和输入端都是高电平;
● 当输出端输出低电平时,输入端为高电平,则开关为抬起状态;
● 当输出端输出低电平时,输入端为低电平,则开关为按下状态;
单行按键状态检测
通过逐一检测输入端的状态,来判断按键是否按下。
多行按键状态检测
首先,将第一行输出低电平,其余行设置为高电平。目的是为了只测试第一行的按键状态。
然后,将第二行输出低电平,其余行设置为高电平。目的是为了只测试第二行的按键状态。
接着,将第三行输出低电平,其余行设置为高电平。目的是为了只测试第三行的按键状态。
最后,将第四行输出低电平,其余行设置为高电平。目的是为了只测试第四行的按键状态。
状态记录
通过自定义状态来记录按键状态
// 记录16个按键状态,0为按下,1为抬起
u16 key_state = 0xFFFF;......void scan() {
// 初始都是 高电平ROW_COL_RESET();NOP1();// ROW1// 给 row1 低电平,读取COL1的值ROW1 = 0;NOP1();// 当前是UP,当之前是DOWN,则为UP// 当前是DOWN,当之前是UP,则为DOWN if(COL1 != (key_state & 0x01) >> 0) {if(COL1) {// 修改当前状态为UPkey_state |= 0x01;printf("K1 Up\r\n");} else {// 修改当前状态为DOWNkey_state &= ~0x01;printf("K1 Down\r\n");}}......
}
状态优化
通过define优化一些数值的操作,方便在后续看代码时方便理解,提高代码的阅读性。
// 记录16个按键状态,0为按下,1为抬起
u16 key_state = 0xFFFF;#define KEY_UP 1
#define KEY_DOWN 0
// 第n个按键的状态
#define KEY_STATE(n) ((key_state & (1 << n)) >> n)
#define SET_KEY_UP(n) (key_state |= (1 << n))
#define SET_KEY_DOWN(n) (key_state &= ~(1 << n))#define ROW_COL_RESET() {ROW1=1,ROW2=1,ROW3=1,ROW4=1;COL1=1,COL2=1,COL3=1,COL4=1;}......void scan() {// 初始都是 高电平ROW_COL_RESET();NOP1();// ROW1// 给 row1 低电平,读取COL1的值ROW1 = 0;NOP1();// 当前是UP,当之前是DOWN,则为UP// 当前是DOWN,当之前是UP,则为DOWNif(COL1 != KEY_STATE(0)) {if(COL1) {// 修改当前状态为UPSET_KEY_UP(0);printf("K1 Up\r\n");} else {// 修改当前状态为DOWNSET_KEY_DOWN(0);printf("K1 Down\r\n");}}......
}
循环优化
操作的按键众多,通过循环的方式来操控每一个按键,减少代码量,方便维护。
#define ROW 4
#define COL 4// 记录16个按键状态,0为按下,1为抬起
u16 key_state = 0xFFFF;#define KEY_UP 1
#define KEY_DOWN 0
// 第n个按键的状态
#define KEY_STATE(r, c) ((key_state & (1 << (r * ROW + c))) >> (r * ROW + c))
#define SET_KEY_UP(r, c) (key_state |= (1 << (r * ROW + c)))
#define SET_KEY_DOWN(r, c) (key_state &= ~(1 << (r * ROW + c)))#define ROW_COL_RESET() {ROW1=1,ROW2=1,ROW3=1,ROW4=1;COL1=1,COL2=1,COL3=1,COL4=1;}void scan() {u8 i, j;for(i = 0; i < ROW; i++) {// 初始都是 高电平ROW_COL_RESET();NOP1();ROW_ON(i);for(j = 0; j < COL; j++) {// 当前是UP,当之前是DOWN,则为UP// 当前是DOWN,当之前是UP,则为DOWNif(COL_STATE(j) != KEY_STATE(i, j)) {if(COL_STATE(j)) {// 修改当前状态为UPSET_KEY_UP(i, j);printf("(%d, %d) Up\r\n", (int)i, (int)j);} else {// 修改当前状态为DOWNSET_KEY_DOWN(i, j);printf("(%d, %d) Down\r\n", (int)i, (int)j);}}}}
}
相关文章:

嵌入式进阶——矩阵键盘
🎬 秋野酱:《个人主页》 🔥 个人专栏:《Java专栏》《Python专栏》 ⛺️心若有所向往,何惧道阻且长 文章目录 矩阵按键原理图按键状态检测单行按键状态检测多行按键状态检测 状态记录状态优化循环优化 矩阵按键 矩阵键盘是一种常见的数字输入…...
请说出vue.cli项目中src目录每个文件夹和文件的用法
在Vue CLI项目中,src目录是存放项目源码及需要引用的资源文件的主要位置。以下是src目录下常见文件夹和文件的用法: components 用途:存放可重用的Vue组件。这些组件通常用于在多个页面或布局中共享UI和功能。特点:组件应该是模块…...
【MySQL精通之路】InnoDB磁盘I/O和文件空间管理(11)
主博客: 【MySQL精通之路】InnoDB存储引擎-CSDN博客 目录 1.InnoDB磁盘I/O 1.1 预读 1.2 双写缓冲区 2.文件空间管理 2.1 Pages, Extents, Segments, and Tablespaces(很重要) 2.2 配置保留文件段页面的百分比 2.3 页与表行的关系 …...

基于springboot+html的二手交易平台(附源码)
基于springboothtml的二手交易平台 介绍部分界面截图如下联系我 介绍 本系统是基于springboothtml的二手交易平台,数据库为mysql,可用于毕设或学习,附数据库 部分界面截图如下 联系我 VX:Zzllh_...

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-24.3,4 SPI驱动实验-I.MX6U SPI 寄存器
前言: 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM(MX6U)裸机篇”视频的学习笔记,在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…...
【Pandas】数据处理方法
1.数据拆分 pandas.Series.str.extract() Series.str.extract(pat, flags0, expandTrue)[source]extract(提取) 参数 pat: 带分组的正则表达式。 flag: re模块中的标志,例如re.IGNORECASE,修改正则表达式匹配的大小写、空格等 expand: 默认为True&…...

【ArcGIS For JS】前端geojson渲染行政区划图层并加标签
原理 通过DataV工具 生成行政区的geojson(得到各区的面元素数据), 随后使用手动绘制featureLayer与Label,并加载到地图。 //vue3加载geojson数据public/geojson/pt.json,在MapView渲染上加载geojson数据 type是"MultiPolygon"fetc…...
Spring AOP原理详解:动态代理与实际应用
1. Spring AOP概述 1.1 什么是AOP AOP(Aspect-Oriented Programming,面向切面编程)是一种编程范式,旨在将横切关注点(Cross-Cutting Concerns)从业务逻辑中分离出来。横切关注点是指那些分散在应用程序多…...
死锁的四个必要条件
死锁的四个必要条件如下: 互斥条件(Mutual Exclusion):资源是独占的,即在同一时间内一个资源只能被一个进程或线程所使用,其他进程或线程无法访问该资源。 请求与保持条件(Hold and Wait&#…...

源网络地址转换SNAT
左上角的是访问互联网发送的数据包,第一个是访问,第二个是网页传回来的 3、4项是源端口号和目的端口号(3是随机的(1024-65535),那个是http的网页服务端口就是80) 那么往回传数据的时候源和目的…...
【算法】平衡二叉搜索树的左旋和右旋
树旋转是一种维护平衡树结构的重要操作,主要用于平衡二叉搜索树(如AVL树和红黑树)。树旋转分为左旋和右旋。 1. 树旋转的定义 左旋 (Left Rotation) 左旋操作将节点及其右子树进行调整,使其右子树的左子节点成为根节点…...

介绍Django Ninja框架
文章目录 安装快速开始特性详解自动文档生成定义请求和响应模型异步支持中间件支持测试客户端 结论 Django Ninja是一个基于Python的快速API开发框架,它结合了Django和FastAPI的优点,提供了简单易用的方式来构建高性能的Web API。 安装 使用以下命令安…...
使用uniapp内置组件checkbox-group所遇到的问题
checkbox-group属性说明 属性名类型默认值说明changeEventHandle <checkbox-group> 中选项发生改变触发change事件 detail { value:[选中的checkbox的value的数组] } 问题代码 <checkbox-group change"handleEVent()"><view style&qu…...

嵌入式学习记录5.23(超时检测、抓包分析)
目录 一.自带超时参数的函数 1.1 select函数 1.2 poll函数的自带超时检测参数 二、不带超时检测参数的函数 三、通过信号完成时间的设置 四、更新下载源 五、wireshark使用 5.1. 安装 5.2. wireshark 抓包 5.2.1 wireshark与对应的OSI七层模型 编辑5.2.2 包头分析 …...

Linux|如何在 awk 中使用流控制语句
引言 当您从 Awk 系列一开始回顾我们迄今为止介绍的所有 Awk 示例时,您会注意到各个示例中的所有命令都是按顺序执行的,即一个接一个。但在某些情况下,我们可能希望根据某些条件运行一些文本过滤操作,这就是流程控制语句的方法。 …...

OceanBase数据库诊断调优,与高可用架构——【DBA从入门到实践】第八期
在学习了《DBA从入门到实践》的前几期课程后,大家对OceanBase的安装部署、日常运维、数据迁移以及业务开发等方面应当已经有了全面的认识。若在实际应用中遇到任何疑问或挑战,欢迎您在OceanBase社区问答论坛中交流、讨论。此次,《DBA从入门到…...

LLVM技术在GaussDB等数据库中的应用
目录 LLVM和数据库 LLVM适用场景 LLVM对所有类型的SQL都会有收益吗? LLVM在OLTP中就一定没有收益吗? GaussDB中的LLVM 1. LLVM在华为应用于数据库的时间线 2. GaussDB LLVM实现简析 3. GaussDB LLVM支持加速的场景 支持LLVM的表达式:…...

【SQL学习进阶】从入门到高级应用(三)
文章目录 ✨条件查询✨条件查询语法格式✨等于、不等于✨等于 ✨不等于 <> 或 ! ✨大于、大于等于、小于、小于等于✨大于 >✨大于等于 >✨小于 <✨小于等于 < ✨and✨or✨and和or的优先级问题✨between...and... 🌈你好呀!我是 山顶风…...

迷你手持小风扇哪个品牌续航强?五款强续航迷你手持小风扇推荐!
夏天就俩字儿:热和空调!太阳大得让人想躲,一出汗,感觉全身毛孔都在喊“太热啦”!这时空调简直是救命恩人啊,热得只想赖在屋里不出来。但出门总得面对大太阳,一出门就哗哗流汗。所以,…...

SpringBoot 微服务中怎么获取用户信息 token
SpringBoot 微服务中怎么获取用户信息 token 当我们写了一个A接口,这个接口需要调用B接口,但是B接口需要包含请求头内容,比如需要用户信息、用户id等内容,由于不在同一个线程中,使用ThreadLocal去获取数据是无法获取的…...

MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...

R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...

Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
日常一水C
多态 言简意赅:就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过,当子类和父类的函数名相同时,会隐藏父类的同名函数转而调用子类的同名函数,如果要调用父类的同名函数,那么就需要对父类进行引用&#…...
土建施工员考试:建筑施工技术重点知识有哪些?
《管理实务》是土建施工员考试中侧重实操应用与管理能力的科目,核心考查施工组织、质量安全、进度成本等现场管理要点。以下是结合考试大纲与高频考点整理的重点内容,附学习方向和应试技巧: 一、施工组织与进度管理 核心目标: 规…...
用js实现常见排序算法
以下是几种常见排序算法的 JS实现,包括选择排序、冒泡排序、插入排序、快速排序和归并排序,以及每种算法的特点和复杂度分析 1. 选择排序(Selection Sort) 核心思想:每次从未排序部分选择最小元素,与未排…...

运行vue项目报错 errors and 0 warnings potentially fixable with the `--fix` option.
报错 找到package.json文件 找到这个修改成 "lint": "eslint --fix --ext .js,.vue src" 为elsint有配置结尾换行符,最后运行:npm run lint --fix...