0x10折成二进制是00010000,高四位是列,那么程序就是逐列扫描的了,这是从最低列扫起,用它作为掩码,只留下一位。
P1 = 0xf0; // 发全0行扫描码,这句就是让所有的列先置高,行置低,是初始值,建议你把电路图对着看,可以在脑子里假设一个钮按下的状态再分析程序。
if ((P1&0xf0)!=0xf0) // 若有键按下,这句如果为真,就说明至少有一列中有键按下了,但是它是区别不出来是哪一列的,只能证明有键按下,当然就更分不出来是哪行了。
scancode = 0xfe; //这句是给扫描码置一个初值,0xfe就是二进制的11111110,接着看后边。
while((scancode&0x10)!=0) // 逐行扫描,刚才说过,这个0x10就是二进制的00010000,和扫描码11111110做与之后留下00010000,那么这时如果在最低列中有键按下,表达式就为假了,没有键按下时才会为真,也就是继续扫描。这种方式不能处理多个键按下的情形,会低位优先,因为一旦有键按下了就不再扫后边的了。而此时注意scancode本身中是行的值。
P1 = scancode; // 输出行扫描码,注意扫描码中的值并未改变,是11111110。
if ((P1&0xf0)!=0xf0) // 本行有键按下,这个判断中对P1做与,如果没有键按下,那么P1应该是和scancode中的值一样的,和0xf0做与之后就是留下高四位得到11110000,一旦有按下的键,相应的位会被拉低,肯定就不等于11110000了,比如说11100000,那么表达式就为真了。
tmpcode = (P1&0xf0)|0x0f; //这句将P1与上的值与0x0f做或运算,得到低4位为全1的列扫描码。
return((~scancode)+(~tmpcode)); //由于其它的位都被填了1,每次招描的结果都只有1个0,取反输出就得到了只有一个1的码。
else scancode = (scancode<<1)|0x01; // 行扫描码左移一位,这样就是将scancode中的11111110变成11111100,而且还要或上0x01保持最低位被补1变成11111101,依次后边会变成11111011和11110111,完成四个行的扫描。
重复上述过程完成所有的扫描。
while((scancode&0x10)!=0) // 逐行扫描<就这里特别纳闷,为什么用0x01>
看清楚这里是0x10,不是0x01,如果是0x01,那么这个循环就不用进了,直接跳出。逐行扫描也无从弹起。
跟这句结合在一起看:
else scancode = (scancode<<1)|0x01;
我想你就能明白源程序的用意了,其实就是逐行扫描,直到全部扫描完成为止。
不会