前言:因为键盘部分是直接与IO端口相连接,不需要通过锁存器锁存数据,所以单独把键盘部分拿出来。
蓝桥杯的单片机开发板上键盘分为两部分:独立键盘和矩阵键盘
原理图如下:
其中独立键盘和矩阵键盘可通过J5上面跳线帽连接方式不同改变。
BTN:独立键盘 KBD:矩阵键盘
通过原理图可以看出S4、S5、S6、S7为独立键盘;S4~S19组合起来做矩阵键盘共16个。
通过原理图获取硬件原理从而去确定软件编程的实现方法,可以看出与这些键盘相连接的IO端口为P30~P35、P42、P44。
将独立键盘和矩阵键盘分开来讲,首先对于独立键盘:跳线连接为BTN模式对应原理图中CON3的23引脚相连,因为3脚接在GND上,所以在独立键盘模式下S4、S5、S6、S7中任何一个按下都会将与其相连接的IO端口电平拉低
S4 | P33 |
S5 | P32 |
S6 | P31 |
S7 | P30 |
所以要验证按键是否按下只需要在程序中判断对应端口是否为低电平,软件代码设计如下:
/*
日期:2023年3月16日
项目:独立键盘
功能:每个独立按键按下,数码管第一位显示对应按下键值(松手后改变)
*/
#include <STC15F2K60S2.H>
#include <INTRINS.H>
#define uchar unsigned char
#define uint unsigned int
//将键盘对应端口位定义,提高简洁性
sbit K7 = P3^0;
sbit K6 = P3^1;
sbit K5 = P3^2;
sbit K4 = P3^3;
uchar t_display[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //段码
uchar T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //位码
uchar Key_num = 0; //键值
uchar Key_flag = 0;
void Select_573(uchar addr,dat)
{
P0=dat;
switch(addr)
{
case 4:P2 = (P2&0X1F)|0X80;break;
case 5:P2 = (P2&0X1F)|0XA0;break;
case 6:P2 = (P2&0X1F)|0XC0;break;
case 7:P2 = (P2&0X1F)|0XE0;break;
}
P2 = P2&0X1F;
}
void Delay10us() //@12.000MHz
{
unsigned char i;
_nop_();
_nop_();
i = 27;
while (--i);
}
void Key_scan()
{
static uchar Key_state = 0; //状态机
switch(Key_state)
{
case 0:
if((K4&&K5&&K6&&K7)==0) //判断是否有按键按下,任一按键按下,K4&&K5&&K6&&K7=0
{
Delay10us(); //消抖 防止误触发
if((K4&&K5&&K6&&K7)==0)
{
if(K4==0) Key_num = 4;//确认键值
if(K5==0) Key_num = 5;//确认键值
if(K6==0) Key_num = 6;//确认键值
if(K7==0) Key_num = 7;//确认键值
Key_state = 1; //确认有按键按下,改变状态机状态
}
}
else Key_state = 0; //如果误触发,恢复无按下状态
break;
case 1:if(K4&&K5&&K6&&K7) //松手检测
{
switch(Key_num)
{
//执行每个按键对应的操作
case 4:Key_flag=4;break;
case 5:Key_flag=5;break;
case 6:Key_flag=6;break;
case 7:Key_flag=7;break;
}
Key_state = 0;
}
break;
}
}
void Dpy_run(dat)
{
Select_573(6,1);
Select_573(7,~t_display[dat]);
}
void main()
{
while(1)
{
Key_scan();
Dpy_run(Key_flag);
}
}
矩阵键盘部分代码设计如下:
/*
日期:2023年3月16日
项目:矩阵键盘
功能:每个按键按下,数码管显示对应按下键值(松手后改变)
*/
#include <STC15F2K60S2.H>
#include <INTRINS.H>
#define uchar unsigned char
#define uint
uchar t_display[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //段码
uchar T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //位码
uchar key_num = 0; //键值
uchar key_flag = 0;
void Delay100us() //@12.000MHz
{
unsigned char i, j;
i = 2;
j = 39;
do
{
while (--j);
} while (--i);
}
void Select_573(uchar addr,dat)
{
P2 = P2&0X1F;
P0=dat;
switch(addr)
{
case 4:P2 = (P2&0X1F)|0X80;break;
case 5:P2 = (P2&0X1F)|0XA0;break;
case 6:P2 = (P2&0X1F)|0XC0;break;
case 7:P2 = (P2&0X1F)|0XE0;break;
}
P2 = P2&0X1F;
}
void Key_scanf() //矩阵键盘
{
static uchar key_state = 0;
uchar hang = 0;
switch(key_state)
{
case 0:P3=0X0F;P44=P42=0;
if(P3!=0X0F)
{
Delay100us();//消抖
if(P3!=0X0F) //扫描行
{
if(P30==0) hang = 1;
if(P31==0) hang = 2;
if(P32==0) hang = 3;
if(P33==0) hang = 4;
switch(hang)
{
case 1:P3=0XF0;P44=P42=1;
if(P44==0) key_num = 7;
if(P42==0) key_num = 11;
if(P35==0) key_num = 15;
if(P34==0) key_num = 19;
break;
case 2:P3=0XF0;P44=P42=1;
if(P44==0) key_num = 6;
if(P42==0) key_num = 10;
if(P35==0) key_num = 14;
if(P34==0) key_num = 18;
break;
case 3:P3=0XF0;P44=P42=1;
if(P44==0) key_num = 5;
if(P42==0) key_num = 9;
if(P35==0) key_num = 13;
if(P34==0) key_num = 17;
break;
case 4:P3=0XF0;P44=P42=1;
if(P44==0) key_num = 4;
if(P42==0) key_num = 8;
if(P35==0) key_num = 12;
if(P34==0) key_num = 16;
break;
}
key_state = 1;
}
else key_state = 0;
}
break;
case 1:P3=0X0F;P44=P42=0; //松手检测
if(P3==0X0F)
{
switch(key_num)
{
case 4:key_flag = 4; break;case 5:key_flag = 5; break;
case 6:key_flag = 6; break;case 7:key_flag = 7; break;
case 8:key_flag = 8; break;case 9:key_flag = 9; break;
case 10:key_flag = 10; break;case 11:key_flag = 11; break;
case 12:key_flag = 12; break;case 13:key_flag = 13; break;
case 14:key_flag = 14; break;case 15:key_flag = 15; break;
case 16:key_flag = 16; break;case 17:key_flag = 17; break;
case 18:key_flag = 18; break;case 19:key_flag = 19; break;
}
key_state = 0;
}
break;
}
}
void Dpy_run(uchar dat)
{
Select_573(7,0xFF);
if(dat>9)
{
Select_573(7,0xFF);
Select_573(6,T_COM[0]);
Select_573(7,~t_display[dat/10]);
Delay100us();
Select_573(6,T_COM[1]);
Select_573(7,~t_display[dat%10]);
Delay100us();
}
else
{
Select_573(6,T_COM[1]);
Select_573(7,~t_display[dat%10]);
Delay100us();
}
}
void main()
{
while(1)
{
Key_scanf();
Dpy_run(key_flag);
}
}
若有代码部分不理解,可在我的主页参见蓝桥杯(单片机)备赛(1)