這是一個3行4列矩陣掃描鍵盤(也可以加一行變成4*4鍵盤)用stc12控制,12864顯示
先判斷是否有鍵按下,消抖后仍按下則逐行置0,當有一鍵按下,該列的高電平會被該行的0電平同化為0電平,這樣8個口里就有兩個低電平
就可以表示一個對應鍵值附件
如圖所示,例0xf0(11110000)表示3行全0,4列全1(最后一個0無用,因為是三行),當變為0x77(01110111)表示第4列第三行的鍵被按下(最后一個1無用)這個0x77在代碼里就是鍵值0;
既然每一個io電平變化代表不同鍵值,就利用switch函數把可能出現的io電平列出來并給予鍵值,方便以后直接拿
取得鍵值后,就可以拿來顯示
1顯示1,2顯示2,10顯示0,以此類推
當顯示值大于10后,可以把11,12當作功能鍵
鍵盤應用
比如這次是查找元器件的功能
取回鍵值后,0123456789可以顯示,那11表示確認查找,12表示刪除重查
然后把查找器件設置成數組當庫存,取到的鍵值結合后于庫存比較,一樣就查找成功顯示出來,沒有就重查
制作出來的實物圖如下:
鍵盤掃描實物.jpg (3.26 MB, 下載次數: 52)
下載附件
查找實物圖
2021-8-4 14:58 上傳
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
51hei截圖20210804141549.png (118.96 KB, 下載次數: 53)
下載附件
protuse仿真圖
2021-8-4 14:56 上傳
以下是軟件程序
1。單個讀鍵
unsigned int a[4]={0xfe,0xfd,0xfb,0xf7};
unsigned char Readkey()//讀出單個鍵值
{ unsigned int i,y; keyport=0xf0;//11110000
delay(10);
i=keyport;
if(i != 0xf0)//判斷有無鍵按下
{
delay(30);
if(i != 0xf0)
{
Delay10ms();
Delay10ms();
Delay10ms();
while(i != 0xf0)
{
Delay10ms();
i=0;
while(i<=3)//判斷何健按下
{
Delay10ms();
Delay10ms();
Delay10ms();
Delay10ms();
keyport=a[ i];[ i]
delay(10);
x=keyport;
if(x != a[ i])[ i]
{
y=x;
return (y);
}
i++;
x=0;
}
}
}
}
return (0xff);
}
unsigned char keyzhi(void)
{
switch(Readkey())
{
case 0xe7:n= 1 ;break;//11100111
case 0xd7:n= 2 ;break;//11010111
case 0xb7:n=3 ;break;//10110111
case 0xeb:n= 4 ;break;
case 0xdb:n= 5 ;break;
case 0xbb:n= 6 ;break;
case 0xed:n= 7 ;break;
case 0xdd:n= 8 ;break;
case 0xbd:n= 9 ;break;
case 0x77:n=10 ;break;//0
case 0x7b:n= 11;break;//確認
case 0x7d:n= 12;break;//重啟
case 0xff:return 0x11;break;
}
//return n;
if(P3!=0XF0)
{
Delay10ms();
Delay10ms();
if(P3&0xf0==0XF0)
{
return n;
}
}
}這個程序可以拿來讀3*4鍵盤的值,也可以加一行表示4*4鍵盤
2,查找元器件程序
#include "reg52.h"
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define keyport P3
#define LCD12864_DA_PORT P0
sbit LCD12864_RS_PORT=P2^5;
sbit LCD12864_RW_PORT=P2^6;
sbit LCD12864_E_PORT =P2^7;
unsigned long code BUF1[]={910,910,151,151,301,402,762,913,683,473,472,000,000,105,123,682,431,000,510,151,515,513,000,000,221,912,000,361,390,010,100,201,154,030,504,305,302,560,822,682,241,561,512,101,471,202,000,000,204,392,392,333,474,683,121,101,050,010,700,433,685,515,152,270,510,202,202,513,010,103,152,000,391,000,132,431,822,510,303,123,512,513,511,681,103,501,000,470,361,000,151,153,273,202,560,510,391,222,602,203,274,224,220,471,361,391,155,201,204,104,474,204,100,502,102,205,503,502,000,210,120,334,331,684,105,271,221,103,010,431,500,105,511,121,102,102,101,000,391};
unsigned long code BUF2[]={101,101,102,102,103,103,104,104,105,106,106,202,202,203,203,204,204,205,205,206,208,208,209,209,210,210,211,212,212,301,302,302,303,303,304,304,305,305,306,306,307,307,308,308,309,309,310,310,311,311,312,312,402,402,403,403,404,404,405,405,406,406,407,407,409,409,410,410,411,411,501,501,502,502,503,503,504,504,505,505,506,506,601,601,602,602,603,603,604,604,605,605,606,606,701,701,702,702,703,703,704,704,705,705,706,706,801,801,802,802,803,803,804,805,805,806,806,901,901,902,902,903,903,904,904,905,905,1001,1001,1002,1002,1003,1003,1004,1004,1005,1005,1006,1006};//先行后列
unsigned int BUF[4];
void LCD12864_WaitIdle();
void LCD12864_COM_Write( unsigned char com_da);
void LCD12864_NoWaitIdle_COM_Write(unsigned char com_da);
void LCD12864_Data_Write(unsigned char da);
void lcd_delay_ms(unsigned char x);
void LCD12864_Reset();
void LCD12864_write_word(unsigned char *s);
void LCD12864_HAIZI_SET();
void Delay10ms();
void display();
unsigned char check();
unsigned char Readkey();
unsigned int x,nn,dat;
unsigned int a[4]={0xfe,0xfd,0xfb,0xf7};//11111110,11111101
unsigned char keyzhi(void);
int n=0;
int m=0;
uchar ii;
uchar iii=1;
unsigned int input,kk;
uchar num;
//////////////////////////////////////////
void main()
{
LCD12864_Reset(); //初始化液晶
LCD12864_HAIZI_SET(); //普通模式
LCD12864_COM_Write(0x80); //指針設置到第一行
LCD12864_write_word("輸入:");
LCD12864_COM_Write(0x90); //指針設置到第一行
LCD12864_write_word("行:");
LCD12864_COM_Write(0x94); //指針設置到第一行
LCD12864_write_word("列:");
LCD12864_COM_Write(0x88); //指針設置到第三行
LCD12864_write_word("220 記作 221");
// LCD12864_COM_Write(0x98); //指針設置到第四行
// LCD12864_write_word("200k 記作 204");
while(1)
{
display();
}
}
/////////////********************///////////1602
///////////////////////////////////
void delay(unsigned int c)
{
while(c != 0)
{
c--;
}
}
void LCD12864_WaitIdle()
{
unsigned char i;
LCD12864_DA_PORT = 0xff;
LCD12864_RS_PORT = 0;
LCD12864_RW_PORT = 1;
LCD12864_E_PORT = 1;
while((LCD12864_DA_PORT&0x80)==1); /*等待BF 不為1*/
LCD12864_E_PORT = 0;
for(i=0;i<50;i++);
}
void LCD12864_HAIZI_SET()
{
LCD12864_COM_Write(0x30);
lcd_delay_ms(10);
LCD12864_COM_Write(0x30);
lcd_delay_ms(10);
}
//********************************************************************
//檢測忙信號寫入命令字 com_da 為待寫入的命令字
//********************************************************************
void LCD12864_COM_Write( unsigned char com_da)
{
LCD12864_WaitIdle();
LCD12864_RS_PORT = 0;
LCD12864_RW_PORT = 0;
LCD12864_DA_PORT = com_da;
LCD12864_E_PORT = 1;
LCD12864_E_PORT = 0;
}
//********************************************************************
//不檢測忙信號寫入命令字 com_da 為待寫入的命令字
//********************************************************************
void LCD12864_NoWaitIdle_COM_Write(unsigned char com_da)
{
LCD12864_RS_PORT = 0;
LCD12864_RW_PORT = 0;
LCD12864_DA_PORT = com_da;
LCD12864_E_PORT = 1;
LCD12864_E_PORT = 0;
}
//********************************************************************
//數據寫入 da 為待寫入的8位數據
//********************************************************************
void LCD12864_Data_Write(unsigned char da)
{
LCD12864_WaitIdle(); /*檢測忙信號*/
LCD12864_RS_PORT = 1;
LCD12864_RW_PORT = 0;
LCD12864_DA_PORT = da;
LCD12864_E_PORT = 1;
LCD12864_E_PORT = 0;
}
//*************************************************************************************
//寫連續字符函數
//*************************************************************************************
void LCD12864_write_word(unsigned char *s)
{
while(*s>0)
{
LCD12864_Data_Write(*s);
s++;
}
}
//********************************************************************
//1MS為單位的延時程序,不準確
//********************************************************************
void lcd_delay_ms(unsigned char x)
{
unsigned int j;
while(x--){
for(j=0;j<1250;j++)
{;}
}
}
void Delay10ms() //@11.0592MHz
{
unsigned char i, j;
i = 108;
j = 145;
do
{
while (--j);
} while (--i);
}
//********************************************************************
//LCD12864初始化
//********************************************************************
void LCD12864_Reset()
{
lcd_delay_ms(100); /*適當延時待LCD自動復位完成*/
LCD12864_NoWaitIdle_COM_Write(0x30); /*使用8位并口通訊*/
lcd_delay_ms(10);
LCD12864_COM_Write(0x30); /*使用8位并口通訊*/
lcd_delay_ms(10);
LCD12864_COM_Write(0x0c); /*顯示開及光標設置*/
lcd_delay_ms(10);
LCD12864_COM_Write(0x01); /*顯示清屏*/
lcd_delay_ms(30);
LCD12864_COM_Write(0x06); /*DDRAM的地址計數器(AC)加1*/
lcd_delay_ms(30);
}
//*******************************//
///////////////////////////////////
unsigned char check()//把鍵值匹配
{
uchar i;
for(i=0;i<500;i++)//開頭設置的數組
{
if(BUF1[ i]==input)//輸入值和數組的某一值對應[ i]
{
return(i);break;
//return(i);break;
}
}
//return(i);
}
void display()//顯示鍵值和位置
{
dat=keyzhi();
if(dat<=10)
{
LCD12864_COM_Write(0x80+3+nn);
LCD12864_Data_Write(dat%10+0X30);
nn++;
if(nn==3)
{
nn=0;
}
BUF[m]=dat;
m++;
if(m==3)
{
m=0;
}
input=(BUF[0])%10*100+(BUF[1]%10)*10+(BUF[2]%10);
}
if(dat==11)
{
ii=check();
LCD12864_COM_Write(0x90+2);
LCD12864_Data_Write(BUF2[ii]/1000+0x30);//千位
LCD12864_Data_Write((BUF2[ii]%1000)/100+0x30);//百位
LCD12864_COM_Write(0X90+6);
LCD12864_Data_Write((BUF2[ii]%100)/10+0x30);//十位
LCD12864_Data_Write((BUF2[ii]%100)%10+0x30);//個位
BUF[0]=0;
BUF[1]=0;
BUF[2]=0;
}
if(dat==12)//刪除鍵
{
LCD12864_Reset(); //初始化液晶
LCD12864_HAIZI_SET(); //普通模式
LCD12864_COM_Write(0x80); //指針設置到第一行
LCD12864_write_word("輸入:");
LCD12864_COM_Write(0x90); //指針設置到第二行
LCD12864_write_word("行:");
LCD12864_COM_Write(0x94); //指針設置到第二行
LCD12864_write_word("列:");
LCD12864_COM_Write(0x88); //指針設置到第三行
LCD12864_write_word("220 記作 221");
// LCD12864_COM_Write(0x98); //指針設置到第四行
// LCD12864_write_word("200k 記作 204");
BUF[0]=0;
BUF[1]=0;
BUF[2]=0;
nn=0;
m=0;
}
if(dat==0XFF)
{
}
}
unsigned char Readkey()//讀出單個鍵值
{
unsigned int i,y;
keyport=0xf0;//11110000
delay(10);
i=keyport;
if(i != 0xf0)//判斷有無鍵按下
{
delay(30);
if(i != 0xf0)
{
Delay10ms();
Delay10ms();
Delay10ms();
while(i != 0xf0)
{
Delay10ms();
i=0;
while(i<=3)//判斷何健按下
{
Delay10ms();
Delay10ms();
Delay10ms();
Delay10ms();
keyport=a[ i];[ i]
delay(10);
x=keyport;
if(x != a[ i])[ i]
{
y=x;
return (y);
}
i++;
x=0;
}
}
}
}
return (0xff);
}
unsigned char keyzhi(void)
{
switch(Readkey())
{
case 0xe7:n= 1 ;break;//11100111
case 0xd7:n= 2 ;break;//11010111
case 0xb7:n=3 ;break;//10110111
case 0xeb:n= 4 ;break;
case 0xdb:n= 5 ;break;
case 0xbb:n= 6 ;break;
case 0xed:n= 7 ;break;
case 0xdd:n= 8 ;break;
case 0xbd:n= 9 ;break;
case 0x77:n=10 ;break;//0
case 0x7b:n= 11;break;//確認
case 0x7d:n= 12;break;//重啟
case 0xff:return 0x11;break;
}
//return n;
if(P3!=0XF0)
{
Delay10ms();
Delay10ms();
if(P3&0xf0==0XF0)
{
return n;
}
}
}
這里BUF1[],BUF2[],是電阻標稱,電阻位置,這個程序可以查找電阻的位置并顯示
附件里有protuse原理圖,c文件,hex文件,實物圖,親測有效
如有問題,歡迎評論指正
51hei.png (3.44 KB, 下載次數: 55)
下載附件
2021-8-4 15:29 上傳
由于Proteus7.5版本里面沒有stc12的芯片所以我用的at89c51來代替的
Proteus7.5版本的仿真圖(DSN文件)和C語言代碼51hei附件下載:
按鍵掃描.zip
(3.15 MB, 下載次數: 23)
2021-8-4 14:55 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|