目錄
源代碼
?main.c
MatrixKey.c
MatrixKey.h
LCD1602.c
?LCD1602.h
?Delay.c
Delay.h
運行效果圖:
第一步:
第二步:
第三步:
第四步:
?代碼解析與教程:
延時函數Delay
?LCD1602
?MatrixKey模塊
源代碼

如上圖將7個文放在Keli5 中即可,然后燒錄在單片機中就行了

燒錄軟件用的是STC-ISP,不知道怎么安裝的可以去看江科大的視頻:
【51單片機入門教程-2020版 程序全程純手打 從零開始入門】https://www.bilibili.com/video/BV1Mb411e7re?p=2&vd_source=ada7b122ae16cc583b4add52ad89fd5e
源代碼:
?main.c
//mian.c#include <STC89C5xRC.H>
#include "Delay.h"
#include "LCD1602.h"
#include "MatrixKey.h"unsigned char KeyNum;
unsigned int Password,Count;void main(){LCD_Init();LCD_ShowString(1,1,"Password:");//上行顯示LCD_ShowNum(2,1,0,4);//下行初始顯示while(1){KeyNum=MatrixKey();if(KeyNum){//檢測是否摁按鍵if(KeyNum<=10){//檢測摁按鍵的按鍵是否小于10,輸入密碼if(Count<4){Password*=10;//密碼左移一位,利用當前數乘10得Password+=KeyNum%10; //將10變成0,并且每次獲得新輸入的數Count++;//配合if條件最大位數為4,限制密碼位數}}LCD_ShowNum(2,1,Password,4);//更新顯示屏}if(KeyNum==11){//按鍵是否等于于11,確認密碼if(Password==301){//在此自定義密碼(可改6666等,這里用的301)LCD_ShowString(1,14," OK");//如果密碼等于6666,顯示OKDelay(2000);//OK顯示2秒LCD_ShowNum(2,1,0,4);//刷新顯示LCD_ShowString(1,1,"zxy I Love You ");LCD_ShowString(1,16,"!");LCD_ShowNum(2,1,520,3);LCD_ShowNum(2,6,1314,4);LCD_ShowString(2,10," mua !");}else{LCD_ShowString(1,14,"ERR");//如果密碼不等于6666,顯示ERRLCD_ShowNum(2,1,0,4);//刷新顯示Password=0;//密碼清零Count=0;//計數清零}}if(KeyNum==12){//清空當前密碼LCD_ShowString(1,14," ");//刷新當前狀態LCD_ShowNum(2,1,0,4);//刷新顯示Password=0;//密碼清零Count=0;//計數清零}}
}
MatrixKey.c
//MatrixKey.c#include <STC89C5xRC.H>
#include "Delay.h"
#include "LCD1602.h"
#include "MatrixKey.h"//矩陣按鍵源代碼unsigned char MatrixKey(){unsigned char KeyNumber=0;//矩陣按鍵第一列P1=0xFF;P13=0;if(P17==0){Delay(20);while(P17==0);//防抖操作Delay(20);KeyNumber=1;}if(P16==0){Delay(20);while(P16==0);Delay(20);KeyNumber=5;}if(P15==0){Delay(20);while(P15==0);Delay(20);KeyNumber=9;}if(P14==0){Delay(20);while(P14==0);Delay(20);KeyNumber=13;}//矩陣按鍵第二列P1=0xFF;P12=0;if(P17==0){Delay(20);while(P17==0);Delay(20);KeyNumber=2;}if(P16==0){Delay(20);while(P16==0);Delay(20);KeyNumber=6;}if(P15==0){Delay(20);while(P15==0);Delay(20);KeyNumber=10;}if(P14==0){Delay(20);while(P14==0);Delay(20);KeyNumber=14;}//矩陣按鍵第三列P1=0xFF;P11=0;if(P17==0){Delay(20);while(P17==0);Delay(20);KeyNumber=3;}if(P16==0){Delay(20);while(P16==0);Delay(20);KeyNumber=7;}if(P15==0){Delay(20);while(P15==0);Delay(20);KeyNumber=11;}if(P14==0){Delay(20);while(P14==0);Delay(20);KeyNumber=15;}//矩陣按鍵第四列P1=0xFF;P10=0;if(P17==0){Delay(20);while(P17==0);Delay(20);KeyNumber=4;}if(P16==0){Delay(20);while(P16==0);Delay(20);KeyNumber=8;}if(P15==0){Delay(20);while(P15==0);Delay(20);KeyNumber=12;}if(P14==0){Delay(20);while(P14==0);Delay(20);KeyNumber=16;}return KeyNumber;
}
MatrixKey.h
//MatrixKey.h#ifndef __MatrixKey_H__
#define __MatrixKey_H__//矩陣按鍵頭文件unsigned char MatrixKey();
#endif
LCD1602.c
//LCD1602.c#include <STC89C5xRC.H>
//LCD1602源代碼//引腳配置:
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0//函數定義:
/*** @brief LCD1602延時函數,12MHz調用可延時1ms* @param 無* @retval 無*/
void LCD_Delay() //@11.0592MHz
{unsigned char i, j;i = 11;j = 190;do{while (--j);} while (--i);
}/*** @brief LCD1602寫命令* @param Command 要寫入的命令* @retval 無*/
void LCD_WriteCommand(unsigned char Command)
{LCD_RS=0;LCD_RW=0;LCD_DataPort=Command;LCD_EN=1;LCD_Delay();LCD_EN=0;LCD_Delay();
}/*** @brief LCD1602寫數據* @param Data 要寫入的數據* @retval 無*/
void LCD_WriteData(unsigned char Data)
{LCD_RS=1;LCD_RW=0;LCD_DataPort=Data;LCD_EN=1;LCD_Delay();LCD_EN=0;LCD_Delay();
}/*** @brief LCD1602設置光標位置* @param Line 行位置,范圍:1~2* @param Column 列位置,范圍:1~16* @retval 無*/
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{if(Line==1){LCD_WriteCommand(0x80|(Column-1));}else if(Line==2){LCD_WriteCommand(0x80|(Column-1+0x40));}
}/*** @brief LCD1602初始化函數* @param 無* @retval 無*/
void LCD_Init()
{LCD_WriteCommand(0x38);//八位數據接口,兩行顯示,5*7點陣LCD_WriteCommand(0x0c);//顯示開,光標關,閃爍關LCD_WriteCommand(0x06);//數據讀寫操作后,光標自動加一,畫面不動LCD_WriteCommand(0x01);//光標復位,清屏
}/*** @brief 在LCD1602指定位置上顯示一個字符* @param Line 行位置,范圍:1~2* @param Column 列位置,范圍:1~16* @param Char 要顯示的字符* @retval 無*/
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{LCD_SetCursor(Line,Column);LCD_WriteData(Char);
}/*** @brief 在LCD1602指定位置開始顯示所給字符串* @param Line 起始行位置,范圍:1~2* @param Column 起始列位置,范圍:1~16* @param String 要顯示的字符串* @retval 無*/
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{unsigned char i;LCD_SetCursor(Line,Column);for(i=0;String[i]!='\0';i++){LCD_WriteData(String[i]);}
}/*** @brief 返回值=X的Y次方*/
int LCD_Pow(int X,int Y)
{unsigned char i;int Result=1;for(i=0;i<Y;i++){Result*=X;}return Result;
}/*** @brief 在LCD1602指定位置開始顯示所給數字* @param Line 起始行位置,范圍:1~2* @param Column 起始列位置,范圍:1~16* @param Number 要顯示的數字,范圍:0~65535* @param Length 要顯示數字的長度,范圍:1~5* @retval 無*/
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{unsigned char i;LCD_SetCursor(Line,Column);for(i=Length;i>0;i--){LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');}
}/*** @brief 在LCD1602指定位置開始以有符號十進制顯示所給數字* @param Line 起始行位置,范圍:1~2* @param Column 起始列位置,范圍:1~16* @param Number 要顯示的數字,范圍:-32768~32767* @param Length 要顯示數字的長度,范圍:1~5* @retval 無*/
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{unsigned char i;unsigned int Number1;LCD_SetCursor(Line,Column);if(Number>=0){LCD_WriteData('+');Number1=Number;}else{LCD_WriteData('-');Number1=-Number;}for(i=Length;i>0;i--){LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');}
}/*** @brief 在LCD1602指定位置開始以十六進制顯示所給數字* @param Line 起始行位置,范圍:1~2* @param Column 起始列位置,范圍:1~16* @param Number 要顯示的數字,范圍:0~0xFFFF* @param Length 要顯示數字的長度,范圍:1~4* @retval 無*/
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{unsigned char i,SingleNumber;LCD_SetCursor(Line,Column);for(i=Length;i>0;i--){SingleNumber=Number/LCD_Pow(16,i-1)%16;if(SingleNumber<10){LCD_WriteData(SingleNumber+'0');}else{LCD_WriteData(SingleNumber-10+'A');}}
}/*** @brief 在LCD1602指定位置開始以二進制顯示所給數字* @param Line 起始行位置,范圍:1~2* @param Column 起始列位置,范圍:1~16* @param Number 要顯示的數字,范圍:0~1111 1111 1111 1111* @param Length 要顯示數字的長度,范圍:1~16* @retval 無*/
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{unsigned char i;LCD_SetCursor(Line,Column);for(i=Length;i>0;i--){LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');}
}
?LCD1602.h
//LCD1602.h#ifndef __LCD1602_H__
#define __LCD1602_H__//LCD1602頭文件
//用戶調用函數:
void LCD_Init();
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);#endif
?Delay.c
//Delay.c#include <STC89C5xRC.H>
#include <INTRINS.H>//延時函數
void Delay(unsigned int xms) //@11.0592MHz
{unsigned char i, j;while(xms){i = 2;j = 199;do{while (--j);} while (--i);xms--;}
}
Delay.h
//Delay.h#ifndef __Delay_H__
#define __Delay_H__//延時函數頭文件
void Delay(unsigned int xms);
#endif
運行效果圖:
第一步:
初始化顯示,按下開關后顯示如下

第二步:
在矩陣按鍵中按S1-S10,對應數字1-9,S10是0,輸入密碼(可以自己修改)

第三步:
輸入完后,按S11(S12是清空當前輸入,S13-S16,暫時沒有綁定按鍵,可自行設置)確定驗證密碼,正確右上角顯示OK(2秒),錯誤顯示ERR
- 注:因為編譯器會將0開頭的數字認為是八進制,因次想要實現0開頭的密碼必須使用字符串來,在本代碼中我將忽略第一個0的情況,例如:0123,輸入123,就可以實現顯示0123時密碼正確


第四步:
密碼正確會,2秒后會跳轉新界面,顯示你表白的內容(可自己更改)

?代碼解析與教程:
延時函數Delay
- 包含源代碼與頭文件,不需要知道怎么實現的會用即可,后續使用,直接將頭文件和源代碼拿過來用即可;例如:Delay(1000)就是延遲1秒(單位毫秒)
?LCD1602
- 包含源代碼與頭文件,不需要知道怎么實現的會用即可,后續使用,直接將頭文件和源代碼拿過來用即可;使用格式:(參考江科大的視頻素材)
- LCD1602相關重要知識:
- LCD1602有兩上下兩行顯示屏,每行各有16個小顯示屏,如上圖中的LCD_ShowString(1,3,"Hello"),第一個參數是第一行還是第二行,第2個參數是對應第幾行的第幾個小顯示屏,最后一個是輸出的東西,同理,到LCD_ShowNum(1,9,123,3)里,前三個和前面一樣,最后一個參數是顯示的位數,不夠就在前面補0,例如輸入1,參數為4,顯示就是0001,輸入23,參數為3,顯示就是023
- 上圖是LCD1602的開發原理模塊圖,由圖可知,P10-P17是控制顯示屏的重點;像矩陣那樣,S1,由P17和P13控制,同理,其他按鍵一樣,由于開發板限制,我們一般使用列遍歷來控制按鍵,例如:S1,S5,S9,S13他們四個共用P13,所以將其為1列,將P13設定為1,P17設定為0,S1就會亮,其他按鍵同理。
?MatrixKey模塊
- 包含源代碼與頭文件,需要知道怎么實現,會用
- 如上LCD1602相關知識所言,將P1=0xFF,就可以實現將所有的IO接口設定為1,這時只需要將上述的原理圖拿出來,就可以控制哪個亮了,如下:
//矩陣按鍵第四列P1=0xFF;P10=0;if(P17==0){Delay(20);while(P17==0);Delay(20);KeyNumber=4;}if(P16==0){Delay(20);while(P16==0);Delay(20);KeyNumber=8;}if(P15==0){Delay(20);while(P15==0);Delay(20);KeyNumber=12;}if(P14==0){Delay(20);while(P14==0);Delay(20);KeyNumber=16;}return KeyNumber;將其他都設置成1之后,又將P10設為0,打開第四列,判斷P17是否按下(看原理圖,也就是第四個按鍵),隨后加上防抖操作(中間那三行),然后按下之后,執行KeyNumber=4;代碼;以此類推即可。
?效果視頻:
(51單片機)矩陣按鍵密碼鎖表白(C語言代碼編撰)(矩陣按鍵
?注:該代碼是本人自己所寫,可能不夠好,不夠簡便,歡迎大家指出我的不足之處。如果遇見看不懂的地方,可以在評論區打出來,進行討論,或者聯系我。上述內容全是我自己理解的,如果你有別的想法,或者認為我的理解不對,歡迎指出!!!如果可以,可以點一個免費的贊支持一下嗎?謝謝各位彥祖亦菲!!!!!

