蓝桥杯(单片机)备赛(2)

文章详细介绍了蓝桥杯单片机开发板上的独立键盘和矩阵键盘的硬件连接原理,包括IO端口的使用以及按键与端口的连接关系。在软件实现部分,提供了独立键盘和矩阵键盘的扫描和检测代码,用于识别按键按下并处理相应的操作。代码中包含了消抖处理和状态机设计,确保了按键检测的稳定性和准确性。
摘要由CSDN通过智能技术生成

前言:因为键盘部分是直接与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端口电平拉低

连接关系
S4P33
S5P32
S6P31
S7P30

 所以要验证按键是否按下只需要在程序中判断对应端口是否为低电平,软件代码设计如下:

/*
日期: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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值