最近在学习金沙滩宋老师的单片机,说实话学着是比较吃力,但是不后悔!老师交给的绝不是仅仅只是“鱼”。发现自己的学习态度以及严谨程度,真的和一些前辈比起相差甚远。
下面摘自一位名为“商道”的群友的学习总结,共勉~
一、问题复现
关于矩阵按键扫描消抖的解释-教材第8章-矩阵按键扫描例题8.4.5
教材116页第8章-矩阵按键扫描例题8.4.5中,中断函数void interrupttime0() interrupt 1
的扫描及消抖部分代码截取如下:
截取函数代码如下:
//将一行的4个按键值移入缓冲区
keybuf[keyout][0] = (keybuf[keyout][0] << 1) | KEY_IN_1;
keybuf[keyout][1] = (keybuf[keyout][1] << 1) | KEY_IN_2;
keybuf[keyout][2] = (keybuf[keyout][2] << 1) | KEY_IN_3;
keybuf[keyout][3] = (keybuf[keyout][3] << 1) | KEY_IN_4;
//消抖后更新按键状态
for (i=0; i<4; i++) //每行4个按键,所以循环4次
{
if ((keybuf[keyout][i] & 0x0F) == 0x00)
{ //连续4次扫描值为0,即4*4ms内都是按下状态时,可认为按键已稳定的按下
KeySta[keyout][i] = 0;
}
else if ((keybuf[keyout][i] & 0x0F) == 0x0F)
{ //连续4次扫描值为1,即4*4ms内都是弹起状态时,可认为按键已稳定的弹起
KeySta[keyout][i] = 1;
}
}
//执行下一次的扫描输出
keyout++; //输出索引递增
keyout = keyout & 0x03; //索引值加到4即归零
疑问如下:
for循环语句的解释部分是“每行4个按键,所以循环4次”;
if条件语句的解释部分是“//连续4次扫描值为0,即4*4ms内都是按下状态时,可认为按键已稳定的按下”;
- 1、那么for语句的“每行4个按键,所以循环4次”与if语句的“4*4ms”是不是一回事呢?
- 2、“连续4次扫描值为0,即
4*4ms
内都是按下状态时,可认为按键已稳定的按下”。这4行4次扫描时间即4*4ms
,是在同一次中断中发生的吗?
二、解答
2.1、我们先了解一下这个中断函数的运行过程
简单地说就是,函数每隔1ms中断一次,并扫描按键中的1行,扫描完成后返回主函数; 第1次中断时,扫描的是第1行的4个按键1位; 第二次中断时扫描的是第2行的4个按键1位; 依次类推,完成全部按键扫描需要中断4次,共扫描4行16个按键,用时4ms;这是一次(一位)全部按键的扫描循环。 这样的循环要进行4次,才能完成按键的扫描处理(不能称为消抖,感觉不太恰当),用时4*4=16ms。
2.2、这样的话,就不难理解以上两条疑问了。
关于第1条疑问的回答:他们不是同一回事。for语句中“每行4个按键,所以循环4次”, 只是一次中断,扫描的是一行按键(共4个按键),用时1ms; 而if语句中的“4*4ms”是4次循环,共用16次中断来完成。
2.3、举例说明:
假如第4行第4个按键有动作,即keyout=3,i=3,keybuf[keyout][i]=keybuf[3][3], 此时的KEY_IN_4=0,中断函数需要进入第3次中断时才能发现KEY_IN_4的值为0(第一次中断只扫描第一行,第二次中断扫描第二行,第三次中断扫描第三行,第四次中断扫描第四行,这时才能发现第四行的第四个按键有动作), 于是将keybuf[3][3]的最右边的位由1变为0,然后继续扫描下一行(返回第一行,于此完成所有按键的第一位扫描); 在第8次中断扫描时,发现KEY_IN_4的值仍然为0,于是将keybuf[3][3]的右边的第2位由1变为0(此时右边共有2个0了), 然后继续扫描下一行; 在第12次中断扫描时,发现KEY_IN_4的值仍然为0,于是将keybuf[3][3]的右边的第3位由1变为0(此时右边共有3个0了), 然后继续扫描下一行; 在第16次中断扫描时,发现KEY_IN_4的值仍然为0,于是将keybuf[3][3]的右边的第4位由1变为0(此时右边共有4个0了), 此刻就完成了4行4次全部按键扫描的循环了,共用时16ms。 此时的keybuf[3][3]右边四位全部是0,所以判定是按下状态。其他的以此类推。