【51單片機】5. 矩陣鍵盤與矩陣鍵盤密碼鎖Demo

1. 矩陣鍵盤原理

在這里插入圖片描述

通過矩陣連接的模式,原本需要16個引腳連接的按鈕只需要8個引腳就能連接好,減少了I/O口的占用。

矩陣按鈕是通過掃描來讀取狀態的。

2. 掃描的概念

輸出掃描示例:數碼管掃描

原理:顯示第1位→顯示第2位→顯示第2位→…,快速重復此過程實現所有數碼管同時顯示的效果

輸入掃描示例:矩陣鍵盤掃描

原理:讀取第1行(列)→讀取第2行(列)→讀取第3行(列)→…,快速循環此過程,最終實現所有按鍵同時檢測的效果

這種循環掃描的優勢在于節省I/O口

3. Templates的定義

Template實際上就是雙擊出來指定的內容,比如平時寫.h文件的時候,總是需要反復寫如下開頭結尾:

#ifndef __XXX_H__
#define __XXX_H__#endif

會比較麻煩,通過Template可以將這部分代碼定義存儲,再使用的時候雙擊即可,定義Template步驟如下:

第一步:點擊下方的【Templates】→【右鍵】→【Configure Templates】

在這里插入圖片描述

第二步:新建,起一個好識別的名字,寫入常用的部分作為Text

在這里插入圖片描述

第三步:在希望光標落入的地方打一個|,最終Text部分輸入如下:

#ifndef __|_H__
#define#endif

在文件中雙擊,就會出現如圖所示的結果:

在這里插入圖片描述

4. 矩陣鍵盤掃描方式1

建立了MatrixKeyboard.cMatrixKeyboard.h,里面寫掃描的代碼

需要先理解矩陣鍵盤的按鍵按下是怎么被掃描到的,我這里直接復制了deepseek的回答:

在矩陣鍵盤中,檢測按鈕被按下的正確原理是:

  1. 行線(輸出端)需要主動置低
  2. 列線(輸入端)被按鍵下拉為低
  3. 檢測時需滿足:行線輸出低電平 + 列線檢測到低電平

基于此,我們需要給行線置低(根據上面的電路圖圖示,行線分別是P17,P16,P15,P14),同時檢測列線(P13,P12,P11,P10)。

我在MatrixKeyboard.c中自己寫了一個不帶消抖的按行掃描:

#include <REGX52.H>
#include "Delay.h"// 按行掃描
unsigned char MatrixKeyboardScan()
{unsigned char keyNum = 0;P1 = 0xFF;P1_7 = 0;if (P1_3 == 0) keyNum = 1;if (P1_2 == 0) keyNum = 2;if (P1_1 == 0) keyNum = 3;if (P1_0 == 0) keyNum = 4;P1 = 0xFF;P1_6 = 0;if (P1_3 == 0) keyNum = 5;if (P1_2 == 0) keyNum = 6;if (P1_1 == 0) keyNum = 7;if (P1_0 == 0) keyNum = 8;P1 = 0xFF;P1_5 = 0;if (P1_3 == 0) keyNum = 9;if (P1_2 == 0) keyNum = 10;if (P1_1 == 0) keyNum = 11;if (P1_0 == 0) keyNum = 12;P1 = 0xFF;P1_4 = 0;if (P1_3 == 0) keyNum = 13;if (P1_2 == 0) keyNum = 14;if (P1_1 == 0) keyNum = 15;if (P1_0 == 0) keyNum = 16;return keyNum;
}

MartixKeyboard.h如下:

#ifndef __MATRIXKEYBOARD_H__
#define __MATRIXKEYBOARD_H__unsigned char MatrixKeyboardScan();#endif

為了驗證不帶消抖按行掃描存在的問題,我寫了如下一段主函數:

#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "MatrixKeyboard.h"void main()
{unsigned int myCount = 0;unsigned char keyboardNum = 0;LCD_Init();// LCD_ShowNum(2,1,keyboardNum,2);while (1){keyboardNum = MatrixKeyboardScan();if (keyboardNum){myCount++;LCD_ShowNum(1,1,keyboardNum,2);LCD_ShowNum(2,1,myCount,3);}}
}

此時,LCD第一行顯示按下的按鍵,第二行顯示受抖動電壓影響,LCD_ShowNum語句執行的次數:

在這里插入圖片描述

可以看到,不穩的電壓起碼抖動了11次,從而11次執行了LCD_ShowNum語句,為此,消抖語句的存在還是很必要的,故修改如下:

#include <REGX52.H>
#include "Delay.h"// 按行掃描
unsigned char MatrixKeyboardScan()
{unsigned char keyNum = 0;P1 = 0xFF;P1_7 = 0;if (P1_3 == 0) {Delay(20); while(P1_3 == 0) ; Delay(20); keyNum = 1;}if (P1_2 == 0) {Delay(20); while(P1_2 == 0) ; Delay(20); keyNum = 2;}if (P1_1 == 0) {Delay(20); while(P1_1 == 0) ; Delay(20); keyNum = 3;}if (P1_0 == 0) {Delay(20); while(P1_0 == 0) ; Delay(20); keyNum = 4;}P1 = 0xFF;P1_6 = 0;if (P1_3 == 0) {Delay(20); while(P1_3 == 0) ; Delay(20); keyNum = 5;}if (P1_2 == 0) {Delay(20); while(P1_2 == 0) ; Delay(20); keyNum = 6;}if (P1_1 == 0) {Delay(20); while(P1_1 == 0) ; Delay(20); keyNum = 7;}if (P1_0 == 0) {Delay(20); while(P1_0 == 0) ; Delay(20); keyNum = 8;}P1 = 0xFF;P1_5 = 0;if (P1_3 == 0) {Delay(20); while(P1_3 == 0) ; Delay(20); keyNum = 9;}if (P1_2 == 0) {Delay(20); while(P1_2 == 0) ; Delay(20); keyNum = 10;}if (P1_1 == 0) {Delay(20); while(P1_1 == 0) ; Delay(20); keyNum = 11;}if (P1_0 == 0) {Delay(20); while(P1_0 == 0) ; Delay(20); keyNum = 12;}P1 = 0xFF;P1_4 = 0;if (P1_3 == 0) {Delay(20); while(P1_3 == 0) ; Delay(20); keyNum = 13;}if (P1_2 == 0) {Delay(20); while(P1_2 == 0) ; Delay(20); keyNum = 14;}if (P1_1 == 0) {Delay(20); while(P1_1 == 0) ; Delay(20); keyNum = 15;}if (P1_0 == 0) {Delay(20); while(P1_0 == 0) ; Delay(20); keyNum = 16;}return keyNum;
}

修改后的執行結果如下,可以看到按下一次按鈕,相應的代碼只會執行一次:

在這里插入圖片描述

5. 矩陣掃描方式2

先掃出按鍵的列,再掃出按鍵的行

#include <REGX52.H>
#include "Delay.h"// 先找列再找行
unsigned char MatrixKeyboardScan()
{// 先掃出按下按鍵所處列unsigned char keyNum = 0;P1 = 0x0F;switch(P1){case (0x07): keyNum = 1; break;case (0x0B): keyNum = 2; break;case (0x0D): keyNum = 3; break;case (0x0E): keyNum = 4; break;}// 再掃出按下按鍵所處行P1 = 0xF0;switch(P1){case (0x70): keyNum += 0; break;case (0xB0): keyNum += 4; break;case (0xD0): keyNum += 8; break;case (0xE0): keyNum += 12; break;}return keyNum;
}

原理很簡單,當第一步將P1置為0x0F時,通過判斷低位處于什么樣的狀態,就可以知道按下的是哪一列的按鈕:

在這里插入圖片描述

同理,第二步將P1置為0xF0時,判斷高位處于什么樣的狀態,就可以判斷出按下按鈕的所處行。

因為在第一步假設按下按鈕位于第1行,分別置了1、2、3、4;則第二行僅需根據行數,加上具體相隔的按鈕值即可。

但是我不太清楚消抖應該加在哪,我自己試了一下會很奇怪,所以這里的代碼只是簡單寫了一下,僅供參考,可能會出現抖動問題。

6. 主函數代碼

#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "MatrixKeyboard.h"void main()
{unsigned char keyboardNum = 0;LCD_Init();LCD_ShowString(1,1,"Press:");LCD_ShowNum(2,1,keyboardNum,2);while (1){keyboardNum = MatrixKeyboardScan();if (keyboardNum){LCD_ShowNum(2,1,keyboardNum,2);}}
}

結果如下:

在這里插入圖片描述

7. 矩陣鍵盤密碼鎖

需求是由用戶輸入密碼,單片機檢測是否正確,正確則輸出“OK”,反之輸出“ERR”,除此之外,還需要有“刪除(回退一格)”和“取消(輸入密碼全部清空)”功能。

我的代碼實現如下,S1-S9代表數字1-9,S10是回退一格,S11是取消,S12是確認:

#include "Delay.h"
#include "LCD1602.h"
#include "MatrixKeyboard.h"void main()
{unsigned int password = 0;unsigned int truePassword = 1234;unsigned int passwordNum = 0;LCD_Init();LCD_ShowString(1,1,"Password:");LCD_ShowNum(2,1,password,4);password = password / 10;while(1){unsigned int currNum = MatrixKeyboardScan();if (currNum){// 非法輸入不允許,直接忽略if (currNum == 13 || currNum == 14 || currNum == 15 || currNum == 16) continue;// 功能鍵:10刪除,11取消,12確認檢查密碼// 刪除操作if (currNum == 10 && passwordNum <= 4){password /= 10; // 回退一位LCD_ShowNum(2,1,password,4); // 刷新密碼passwordNum--; // 位數-1continue;}// 取消操作else if (currNum == 11){passwordNum = 0;password = 0;LCD_ShowNum(2,1,password,4);continue;}// 確認操作else if (currNum == 12){if (password == truePassword) // 密碼正確顯示OK,程序結束{LCD_ShowString(1,15,"OK");}					else // 密碼錯誤顯示ERR,password重置為0{LCD_ShowString(1,14,"ERR");passwordNum = 0;password = 0;LCD_ShowNum(2,1,password,4);}continue;}// 功能鍵以外的數字鍵處理if (passwordNum == 0){LCD_ShowString(1,14,"   ");if (currNum == 13) currNum = 0; // 用13作為數字0,允許用戶輸入0password = currNum;LCD_ShowNum(2,1,password,4);passwordNum++;}else if (passwordNum < 4){if (currNum == 13) currNum = 0; // 用13作為數字0,允許用戶輸入0password = password * 10 + currNum;LCD_ShowNum(2,1,password,4);passwordNum++;}}}
}

效果如下:

密碼鎖Demo

輸入密碼:
在這里插入圖片描述
輸入密碼后按一下S10(回退一格):
在這里插入圖片描述
按取消(密碼置0):
在這里插入圖片描述

輸入錯誤密碼按確定(密碼清0,顯示ERR):
在這里插入圖片描述
輸入正確密碼按確定:
在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/84730.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/84730.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/84730.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Android Studio jetpack compose折疊日歷日期選擇器【折疊日歷】

今天寫一個日期選擇器&#xff0c;大家根據自己需求改代碼&#xff0c;記得點贊支持&#xff0c;謝謝&#xff5e; 這是進入的默認狀態 折疊狀態選中本周其他日期狀態 切換上下周狀態 展開日歷狀態 切換上下月狀態 選中狀態 代碼如下&#xff1a; import android.content.C…

馭碼CodeRider 2.0全棧開發實戰指南:從零構建現代化電商平臺

馭碼CodeRider 2.0全棧開發實戰指南:從零構建現代化電商平臺 一、CodeRider 2.0:重新定義全棧智能開發 1.1 革命性升級亮點 #mermaid-svg-AKjytNB4hD95UZtF {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-AKjyt…

大模型智能體AutoGen面試題及參考答案

目錄 AutoGen 的核心是什么? Agent 在 AutoGen 中承擔什么角色? AutoGen 是如何定義 AssistantAgent、UserProxyAgent 等代理類型的? 什么是 GroupChat(組對話)模式? AutoGen 的 system message 在框架中扮演什么作用? 如何通過 Agent 實現自然語言處理? AutoGen…

深度學習筆記26-天氣預測(Tensorflow)

&#x1f368; 本文為&#x1f517;365天深度學習訓練營中的學習記錄博客&#x1f356; 原作者&#xff1a;K同學啊 一、前期準備 1.數據導入 import numpy as np import pandas as pd import warnings import seaborn as sns import matplotlib.pyplot as plt warnings.filt…

day54 python對抗生成網絡

目錄 一、GAN對抗生成網絡思想 二、實踐過程 1. 數據準備 2. 構建生成器和判別器 3. 訓練過程 4. 生成結果與可視化 三、學習總結 一、GAN對抗生成網絡思想 GAN的核心思想非常有趣且富有對抗性。它由兩部分組成&#xff1a;生成器&#xff08;Generator&#xff09;和判…

龍虎榜——20250613

上證指數放量下跌收陰線&#xff0c;個股下跌超4000只&#xff0c;受外圍消息影響情緒總體較差。 深證指數放量下跌&#xff0c;收陰線&#xff0c;6月總體外圍風險較高&#xff0c;轉下跌走勢的概率較大&#xff0c;注意風險。 2025年6月13日龍虎榜行業方向分析 1. 石油石化&…

Linux常用命令加強版替代品

Linux常用命令加強版替代品 還在日復一日地使用 ls、grep、cd 這些“上古”命令嗎&#xff1f;是時候給你的終端來一次大升級了&#xff01;本文將為你介紹一系列強大、高效且設計現代的Linux命令行工具&#xff0c;它們將徹底改變你的工作流&#xff0c;讓你愛上在終端里操作…

Hadoop 003 — JAVA操作MapReduce入門案例

MapReduce入門案例-分詞統計 文章目錄 MapReduce入門案例-分詞統計1.xml依賴2.編寫MapReduce處理邏輯3.上傳統計文件到HDFS3.配置MapReduce作業并測試4.執行結果 1.xml依賴 <dependency><groupId>org.apache.hadoop</groupId><artifactId>hadoop-commo…

Python打卡第53天

浙大疏錦行 作業&#xff1a; 對于心臟病數據集&#xff0c;對于病人這個不平衡的樣本用GAN來學習并生成病人樣本&#xff0c;觀察不用GAN和用GAN的F1分數差異。 import pandas as pd import numpy as np import torch import torch.nn as nn import torch.optim as optim from…

力扣-279.完全平方數

題目描述 給你一個整數 n &#xff0c;返回 和為 n 的完全平方數的最少數量 。 完全平方數 是一個整數&#xff0c;其值等于另一個整數的平方&#xff1b;換句話說&#xff0c;其值等于一個整數自乘的積。例如&#xff0c;1、4、9 和 16 都是完全平方數&#xff0c;而 3 和 1…

前端構建工具Webapck、Vite——>前沿字節開源Rspack詳解——2023D2大會

Rspack 以下是針對主流構建工具&#xff08;Webpack、Vite、Rollup、esbuild&#xff09;的核心不足分析&#xff0c;以及 Rspack 如何基于這些痛點進行針對性改進 的深度解析&#xff1a; 一、主流構建工具的不足 1. Webpack&#xff1a;性能與生態的失衡 核心問題 冷啟動慢…

輸入法,開頭輸入這U I V 三個字母會不顯示 任何中文

1. 漢語拼音規則的限制 漢語拼音中不存在以“V”“U”“I”為聲母的情況&#xff1a; 漢語拼音的聲母是輔音&#xff0c;而“V”“U”“I”在漢語拼音中都是元音&#xff08;或韻母的一部分&#xff09;。漢語拼音的聲母系統中沒有“V”“U”“I”作為聲母的音節。例如&#xf…

Linux文件權限詳解:從入門到精通

前言 權限是什么&#xff1f; 本質&#xff1a;無非就是能做和不能做什么。 為什么要有權限呢&#xff1f; 目的&#xff1a;為了控制用戶行為&#xff0c;防止發生錯誤。 1.權限的理解 在學習下面知識之前要先知道的一點是&#xff1a;linux下一切皆文件&#xff0c;對li…

在多云環境透析連接ngx_stream_proxy_protocol_vendor_module

1、模塊定位與價值 多云接入&#xff1a;在同一 Nginx 實例前端接入來自多云平臺的私有鏈路時&#xff0c;能區分 AWS、GCP、Azure 特有的連接 ID。安全審計&#xff1a;自動記錄云平臺側的 Endpoint/VPC ID&#xff0c;有助于聯調和安全事件追蹤。路由分流&#xff1a;基于不…

力扣:基本計算器

基本計算器: 224. 基本計算器 - 力扣&#xff08;LeetCode&#xff09; 本體思路為&#xff0c;將中綴表達式轉為后綴表達式&#xff0c;通過后綴表達式進行運算。 中綴表達式: 我們日常生活中熟知的表達式如12-30 就是一個中綴表達式。 后綴表達式: 150. 逆波蘭表達式求值 - …

《AI日報 · 0613|ChatGPT支持導出、Manus免費開放、GCP全球宕機》

AI 資訊 1?? OpenAI ChatGPT Canvas新增多格式導出功能 OpenAI終于為ChatGPT Canvas推出了用戶期待已久的導出功能。現在,用戶可以將創作內容導出為多種格式:文檔類支持PDF、docx和markdown格式,代碼文件則可直接保存為對應擴展名的源文件(如.py、.js、.sql等)。這一功…

C++中的零拷貝技術

一、C中零拷貝技術的核心概念 零拷貝&#xff08;Zero-copy&#xff09;是一種重要的優化技術&#xff0c;旨在減少數據在內存中的不必要復制&#xff0c;從而提高程序性能、降低內存使用并減少CPU消耗。在C中&#xff0c;零拷貝技術通過多種方式實現&#xff0c;包括引用語義…

RT_Thread內核源碼分析(五)——內存管理@小堆內存管理算法

目錄 1、內存堆控制 1.1 內存堆控制器 1.2 內存塊節點 1.3 內存堆管理 2、內存堆初始化 2.1 初始化接口 2.2 初始化示例 2.3 源碼分析 3、內存堆操作 3.1 內存塊申請 3.1.1 相關接口 3.1.2 原理分析 3.1.3 示例分析 3.1.4 代碼分析 3.2 內存塊伸縮 3.2.1 相關…

MyBatis-Plus 混合使用 XML 和注解

mybatisplus代碼生成器&#xff1a; 版本匹配是個比較麻煩的問題&#xff0c;這是我的配置&#xff1a; <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.2</version>…

基于ssm的教學質量評估系統

博主介紹&#xff1a;java高級開發&#xff0c;從事互聯網行業六年&#xff0c;熟悉各種主流語言&#xff0c;精通java、python、php、爬蟲、web開發&#xff0c;已經做了六年的畢業設計程序開發&#xff0c;開發過上千套畢業設計程序&#xff0c;沒有什么華麗的語言&#xff0…