输出就是01,第一个空目标是0到4对应的两位都变为01就是0101010101,其它位不变就行,与1不变,与0置0,所以其它位就都是1,十六进制就是F,1101就是D,根据经验要改变的那几位保持0101010101不变,其它位与的时候是1,或的时候是0就行,0001就是1,所以或的D对应的是1,更高位是0,最低的两位一直是5。可以着重记忆黑体字,这样做的原因是与只有置0和不变,或只有置1和不变。
第二个空同理,这次只需要把十六进制的低两位置0就行,所以只用了与。
看到下面注释有个输出行扫描和读取列信号,可知是先扫描行然后再扫描列,
i<<=1表示把左边运算数i的二进制数进行左移1位运算,然后把计算的结果赋值给i,会改变i的值;
i<<1表示把左边运算数i的二进制数进行左移1位运算,不改变i的值。
这里就是第一种,相当于算出来的十进制数乘2。因为要从第一位按键判断是否按下,所以初值i=1,这里的初值要按二进制去理解,就是00000001。
16的二进制是10000,就是第五位,由题可知这是一个5*4的键盘。这个就是从第一位开始扫描,不断左移,一直扫到第五位。
这个就是把初值都置一。
其实在判断条件那里的i要看成二进制去理解,1到16就是00000001到00010000,就是扫描五位,这个句话就是解释了为什么我们按下的那个位置是0而不是1,就比如如果i是1,就是00000001,先取反11111110再和11111111与,与1与就是不变,所以我们按下的那个位置是0,其它位置都是1。
我们把这个output结果放在上面那个宏定义里,这个就代表了输出的地址。
行扫描完了,列信号是输入进来的,所以直接读取就行,那个输入的地址里是有值的。列信号是用到了四个引脚。
其实输入进来这个列信号,它和我们输出的行信号差不多,,它也是有个初值,然后再与一下,得到的数也是按下那位是0,其余位都是1,它与0F相与,相当于不变,如果不等于0F,就相当于temp里面有0,说明读取的列信号是有按键按下的。
然后把之前给output的行信号给key,key左移八位,此时我们的行信号就被挪到了高八位上,第八位用来保存列信号,取与和上面if的道理一样,或那个就是没用到高四位,然后就看这个返回值就知道有没有按键按下了。
可以看到for循环是不断扫描来判断是否有按键按下的,没有按键按下的话就如上图for循环外面的return 0xFFFF。
这里我们以按下3为例讲解,因为按下为0,所以3那行和列对应0。其它位都是1,行信号是占高八位,列信号是占低八位,而且这都是从引脚低位往高位排,所以结果是11111101 11111011,所以结果是0xFDFB。
参考B站up主莫晓明mxm