蓝桥杯—— 独立按键扫描 矩阵键盘扫描


 独立按键部分


void BTN()//

{
    uchar dat=P3^0xff;
    Trg=dat&(dat^Cont);
    Cont=dat;
}

因为初始状态 P3=0xff,所以dat =0x00,Trg=0x00 ,因为0与上任何数都是0,Cont=0

假设S4按下P3的状态是0xf7,此时 dat =0x08 ,Trg=0x08,Cont=0x08

如果长按,则 dat =0x08 ,Trg=0x00,Cont=0x08

所以我们可以每10ms就去读一次是否触发,相当于是消抖了。

unsigned char flag;//定义全局变量

void Timer0_Init(void)		//1毫秒@11.0592MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xCD;		//设置定时初始值
	TH0 = 0xD4;		//设置定时初始值
    EA=1;
    ET0=1;
	TR0 = 1;		//定时器0开始计时
}
void Timer0() interrupt 1
{
    static unsigned char flag_cnt;
    flag_cnt++;
    if(flag_cnt==10)
    {        
        flag=1;
        flag_cnt=0;
    }
}
if(flag)
{
    BTN();
    flag=0;
    if(Trg&0x01)//S7
    {
    
    }
    else if(Trg&0x02)//S6
    {

    }
    else if(Trg&0x04)//S5
    {

    }
    else if(Trg&0x08)//S4
    {

    }
}

 矩阵键盘部分


 在开头定义按键值定义成4*4的矩阵。

uchar code keymap[4][4]={{7,11,15,19},{6,10,14,18},{5,9,13,17},{4,8,12,16}};


uchar Trg=0,Cont=0,flag=0,dat=0,keyvalue=0,key=0;
void KBD()
{
		uchar row=0,cloumn=0,i,j;
		P3=0x0f;P44=0;P42=0;
		row=P3&0x0f;
		P3=0xf0;P44=1;P42=1;
		if(P44 == 0)			cloumn = 0x70;
		else if(P42 == 0)		cloumn = 0xb0;
		else					cloumn = P3 & 0xf0;
		dat=~(cloumn|row);
		Trg=dat&(dat^Cont);
		Cont=dat;
		
		if(Trg)
		{
			for(i = 0; i < 4; i++)
				for(j = 0; j < 4; j++)
					if(Trg == (0x80 >> j | 0x01 << i))
					{
						keyvalue = keymap[i][j];
						key=keyvalue;
						break;
					}
			
		}
}

 

 分析:当紫色位置按键被按下时,进入检测的代码时会有以下步骤:

1. 列赋0,行都赋1 即P44、P42、P36、P35为低电平 ,P30-P33都是高电平

2.将P3和0X0F进行“与” 操作,得到具体哪一行被按下

3.列赋1,行都赋0 ,即P44、P42、P36、P35为高电平 ,P30-P33都是低电平

4.判断是哪列被按下, 将值赋给cloumn

三行判断式分析:
第一次:
        row =(0000 1101) &(0000 1111) =0000 1101
        cloumn = 0xb0
        dat = ~(row|cloumn)=~( (1011 0000)| 0000 1101) = 0100 0010 = 0x72
        Trg = (0x72) & (0x72^0x00) = 0x72   (异或符号^)
        Cont = dat =0x72 
第二次(紫色按钮还处于按下状态):
        row =(0000 1101) &(0000 1111) =0000 1101
        cloumn = 0xb0
        dat = ~(row|cloumn)=~( (1011 0000)| 0000 1101) = 0100 0010 = 0x72
        Trg = (0x72) & (0x72^0x72) =0x00
        Cont = dat =0x72

所以这个三行判断式可以检测长按和短按,通过十毫秒的检测 “延时” ,可以达到检测准确的效果。


void Timer0_Init(void)		//1毫秒@11.0592MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xCD;		//设置定时初始值
	TH0 = 0xD4;		//设置定时初始值
    EA=1;
    ET0=1;
	TR0 = 1;		//定时器0开始计时
}
void Timer0() interrupt 1
{
    static unsigned char flag_cnt;
    flag_cnt++;
    if(flag_cnt==10)
    {        
        flag=1;
        flag_cnt=0;
    }
}

 使用模板如下 

if(flag)
{
	KBD();
	flag=0;
	if(key==4) //S4
	{
		key=0;
	}
	else if(key==5) //S5
	{
		key=0;
	}
	else if(key==9) //S9
	{
		key=0;
	}
	else if(key==8) //S8
	{
		key=0;
	}
}

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值