标题: 51单片机矩阵键盘有行代码不明白 [打印本页]

作者: nanshancc    时间: 2022-5-19 21:17
标题: 51单片机矩阵键盘有行代码不明白
就是标准红色的那两行,我不明白的是第一行已经赋值给KEY_MATRIX_PORT了,那第二行里面的条件肯定是进不去的啊,头疼了一个下午,不知道是怎么回事,求指点



/*******************************************************************************
* 函 数 名       : key_matrix_ranks_scan
* 函数功能                 : 使用行列式扫描方法,检测矩阵按键是否按下,按下则返回对应键值
* 输    入       : 无
* 输    出             : key_value:1-16,对应S1-S16键,
                                   0:按键未按下
*******************************************************************************/
u8 key_matrix_ranks_scan(void)
{
        u8 key_value=0;

        KEY_MATRIX_PORT=0xf7;//给第一列赋值0,其余全为1
        if(KEY_MATRIX_PORT!=0xf7)//判断第一列按键是否按下
        {
                delay_10us(1000);//消抖
                switch(KEY_MATRIX_PORT)//保存第一列按键按下后的键值        
                {
                        case 0x77: key_value=1;break;
                        case 0xb7: key_value=5;break;
                        case 0xd7: key_value=9;break;
                        case 0xe7: key_value=13;break;
                }
        }
        while(KEY_MATRIX_PORT!=0xf7);//等待按键松开        
        
        KEY_MATRIX_PORT=0xfb;//给第二列赋值0,其余全为1
        if(KEY_MATRIX_PORT!=0xfb)//判断第二列按键是否按下
        {
                delay_10us(1000);//消抖
                switch(KEY_MATRIX_PORT)//保存第二列按键按下后的键值        
                {
                        case 0x7b: key_value=2;break;
                        case 0xbb: key_value=6;break;
                        case 0xdb: key_value=10;break;
                        case 0xeb: key_value=14;break;
                }
        }
        while(KEY_MATRIX_PORT!=0xfb);//等待按键松开        
        
        KEY_MATRIX_PORT=0xfd;//给第三列赋值0,其余全为1
        if(KEY_MATRIX_PORT!=0xfd)//判断第三列按键是否按下
        {
                delay_10us(1000);//消抖
                switch(KEY_MATRIX_PORT)//保存第三列按键按下后的键值        
                {
                        case 0x7d: key_value=3;break;
                        case 0xbd: key_value=7;break;
                        case 0xdd: key_value=11;break;
                        case 0xed: key_value=15;break;
                }
        }
        while(KEY_MATRIX_PORT!=0xfd);//等待按键松开        
        
        KEY_MATRIX_PORT=0xfe;//给第四列赋值0,其余全为1
        if(KEY_MATRIX_PORT!=0xfe)//判断第四列按键是否按下
        {
                delay_10us(1000);//消抖
                switch(KEY_MATRIX_PORT)//保存第四列按键按下后的键值        
                {
                        case 0x7e: key_value=4;break;
                        case 0xbe: key_value=8;break;
                        case 0xde: key_value=12;break;
                        case 0xee: key_value=16;break;
                }
        }
        while(KEY_MATRIX_PORT!=0xfe);//等待按键松开
        
        return key_value;               
}


作者: lkc8210    时间: 2022-5-19 21:17
nanshancc 发表于 2022-5-20 10:09
s14按下,P17就是0,P1就是 0111 1110=7E

我不太明白的地方是不管怎么按键,程序不都是循环扫描顺序执 ...

那你可能还没弄懂准双向IO口的运作
准双向IO口赋1时会设为高阻+弱上拉
准双向IO口赋0时会设为开漏接地
并在任何时侯都可以读取IO口的电平
即是说对IO口赋值不单是设高低电平
同还改变了IO口的结构

P1=0xF7;
S17按下(或者S17在P1=0xF7;前已被按下)
P17的弱上拉不足以为持高电平
到 if(KEY_MATRIX_PORT!=0xf7)时
读取到KEY_MATRIX_PORT的值是0x77
KEY_MATRIX_PORT!=0xf7成立
作者: lkc8210    时间: 2022-5-19 23:10

这是一个矩阵键盘
当P1 = 0xFE时只有P10为低
如果这时S14按下P17的电平是什么?
P1的值又是多少?是否还是0xFE?


作者: 人人学会单片机    时间: 2022-5-20 07:59

主函数不断地扫描这个函数即可完成矩阵键盘的扫描,你的代码太长了点

作者: man1234567    时间: 2022-5-20 08:23
只搞个片断无法回答;只要程序运行能得到想要的结果就没问题。
比如那个看似无解的,如果存在中断且可以重新赋值的就呵呵呵。
可仔细研读一下网文或图书上关于矩阵键盘的叙述,会扫描就好。
作者: yzwzfyz    时间: 2022-5-20 09:05
按下任何一键,都会使某两个IO口短路在一起,即等值!
例如:S14按下后:P17=P10。你要掌握一个关键点,就是1服从于0。这也是扫描键盘的原理!!!
1、让P14-P17=1111,理论上你再回读也应该是1111,如果不是0,如0110,则必是P14T和P17被接0了。
在这张图上,只有下列情况出现P14T和P17才能为0:
以P14=0解说。
S2-5中必至少有一个按下了,且按下的键的另一端是0。
这时,如果事先你让P10=0,则S2按下了。如果P13=0,则S5按下了。
这就是为何要让P10、P11、P12、P13依次为0的目的,如果有两个同时为0(P10和P13),就分不出是哪个键按下了(S2?S4?)。
如你所说:
P1=FE,即P10-17=01111111,这时P10=0。
这时,S2按下,读值为:01110111
S2S6S10S14,全部按下:01110000。
明白了吗?
回头再细想想,扫键的原理就清楚了。


作者: 君工创    时间: 2022-5-20 09:06
while(KEY_MATRIX_PORT!=0xf7);//等待按键松开。这是进入下一行的条件。
作者: nanshancc    时间: 2022-5-20 10:09
lkc8210 发表于 2022-5-19 23:10
这是一个矩阵键盘
当P1 = 0xFE时只有P10为低
如果这时S14按下P17的电平是什么?

s14按下,P17就是0,P1就是 0111 1110=7E

我不太明白的地方是不管怎么按键,程序不都是循环扫描顺序执行的吗

KEY_MATRIX_PORT=0xf7;//给第一列赋值0,其余全为1
        if(KEY_MATRIX_PORT!=0xf7)//判断第一列按键是否按下
        {
难道说如果有按键按下了,不会去执行第一句的赋值语句,直接就进入if判断语句了?
按键按下了,赋值语句没起作用?

我的意思就是不管怎么按键,但是在代码里面都进行了重新的赋值,那样按键好像就没起到作用(也不会进入while)。。
作者: 君莫笑1    时间: 2022-5-20 10:09
应该是按键按下的时候KEY_MATRIX_PORT的值会变化,进入判断
作者: hzhehe    时间: 2022-5-20 11:08
nanshancc 发表于 2022-5-20 10:09
s14按下,P17就是0,P1就是 0111 1110=7E

我不太明白的地方是不管怎么按键,程序不都是循环扫描顺序执 ...

既然是顺序执行那就得按程序先后顺序来。你这个程序明显是先赋值后判断,cpu是顺序执行,对应的键值按照判断应该也是唯一的,也不存在误判的问题。对于随时可能触发的按键,赋值语句在你开始供电的到你第一次按下按键的时候已经被执行了几百乃至几万次了,也不存在赋值语句没有执行的问题,而且你按下按键的时候,不论怎么赋值,这个硬件位置的值始终会被拉低,对应到程序上也是始终处于!0xf7。即使你重新赋值,硬件位的电压已经被拉低,那他也不会保持在0xf7状态了。




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1