| 
 下面是我写的EM78P510N的4×5行列键盘扫描程序,20ms循环一次,
 其中:k1,k2,k3,k4为输出,复用4个LED;ka,kb,kc,kd,ke为输入,外部上拉。
 
 拿出来希望大家多扔点砖头过来,以便提高改进。
 
 
 readkey:                ;20ms扫描一次,说明:扫描到的键值没有来得及
 ;发送时又扫描到其他键值时,会被覆盖掉
 bank 0
 bc    port7,led_con    ;扫描前关闭指示灯使能端
 mov    a,port9
 mov    port9_buff,a    ;保存指示灯状态
 nop
 bc    port9,k1        ;扫描第一行
 bs    port9,k2
 bs    port9,k3
 bs    port9,k4
 mov    a,@1
 mov    key_databuff,a    ;先假定为1
 nop
 nop
 nop
 nop
 nop
 nop
 jbs    porta,ka
 jmp    first_read_k_over
 inc    key_databuff
 jbs    porta,kb
 jmp    first_read_k_over
 inc    key_databuff
 jbs    porta,kc
 jmp    first_read_k_over
 inc    key_databuff
 jbs    porta,kd
 jmp    first_read_k_over
 inc    key_databuff
 jbs    porta,ke
 jmp    first_read_k_over
 inc    key_databuff
 ;;;;;;;;;;;;;;;;;;;;;
 bs    port9,k1        ;扫描第二行
 bc    port9,k2
 bs    port9,k3
 bs    port9,k4
 nop
 nop
 nop
 nop
 nop
 nop
 nop
 nop
 jbs    porta,ka
 jmp    first_read_k_over
 inc    key_databuff
 jbs    porta,kb
 jmp    first_read_k_over
 inc    key_databuff
 jbs    porta,kc
 jmp    first_read_k_over
 inc    key_databuff
 jbs    porta,kd
 jmp    first_read_k_over
 inc    key_databuff
 jbs    porta,ke
 jmp    first_read_k_over
 inc    key_databuff
 ;;;;;;;;;;;;;;;;;;;;;
 bs    port9,k1        ;扫描第三行
 bs    port9,k2
 bc    port9,k3
 bs    port9,k4
 nop
 nop
 nop
 nop
 nop
 nop
 nop
 nop
 jbs    porta,ka
 jmp    first_read_k_over
 inc    key_databuff
 jbs    porta,kb
 jmp    first_read_k_over
 inc    key_databuff
 jbs    porta,kc
 jmp    first_read_k_over
 inc    key_databuff
 jbs    porta,kd
 jmp    first_read_k_over
 inc    key_databuff
 jbs    porta,ke
 jmp    first_read_k_over
 inc    key_databuff
 ;;;;;;;;;;;;;;;;;;;;;
 bs    port9,k1        ;扫描第四行
 bs    port9,k2
 bs    port9,k3
 bc    port9,k4
 nop
 nop
 nop
 nop
 nop
 nop
 nop
 nop
 jbs    porta,ka
 jmp    first_read_k_over
 inc    key_databuff
 jbs    porta,kb
 jmp    first_read_k_over
 inc    key_databuff
 jbs    porta,kc
 jmp    first_read_k_over
 inc    key_databuff
 jbs    porta,kd
 jmp    first_read_k_over
 inc    key_databuff
 jbs    porta,ke
 jmp    first_read_k_over
 nokey:
 clr    key_databuff        ;无键
 bc    keyflag,keydown        ;按键按下标志
 bank 2
 clr    key_datalast
 clr    keydown_cnt
 jmp    readkey_out
 
 first_read_k_over:
 bank 0                ;复合键判断
 bs    port9,k1        ;扫描第三行
 bs    port9,k2
 bc    port9,k3
 bs    port9,k4
 nop
 nop
 nop
 nop
 nop
 nop
 nop
 nop
 jbc    porta,ke
 jmp    first_read_k_over_0
 bs    port9,k1        ;扫描第四行
 bs    port9,k2
 bs    port9,k3
 bc    port9,k4
 nop
 nop
 nop
 nop
 nop
 nop
 nop
 nop
 jbc    porta,ke
 jmp    first_read_k_over_0
 mov    a,@21
 mov    key_databuff,a
 jmp    first_read_k_over_1    ;是紧急按钮则直接跳到1,不经过有键按下检查
 first_read_k_over_0:
 jbc    keyflag,keydown
 jmp    readkey_out            ;确定有普通键按下时(已发送)不响应其他按键
 ;------------------------
 mov    a,key_databuff
 jbc    status,z
 jmp    nokey
 sub    a,@21
 jbs    status,c
 jmp    nokey
 ;------------------------检查键值是否在1-21范围内,防止出错
 first_read_k_over_1:
 mov    a,key_databuff
 bank 2
 xor    a,key_datalast
 jbs    status,z
 jmp    key_different            ;键值与前一次不同
 inc    keydown_cnt                ;键值与上一次相同,则计相同次数
 
 mov    a,@4                    ;是否连续有相同按键4次
 sub    a,keydown_cnt
 jbs    status,c
 jmp    readkey_out
 clr keydown_cnt
 bank 0
 ;---------------------------
 bs    keyflag,keydown            ;有键按下状态标志(确定有键)
 
 bs    uart_sendflag2,key_send    ;uart使用请求标志,申请使用uart
 mov    a,key_databuff
 lcall    key_table                    ;键值转换
 mov    key_data_uartsend_buff,a
 ;---------------------------------------------------------
 jmp    readkey_out
 key_different:
 bank 0
 mov    a,key_databuff
 bank 2
 mov    key_datalast,a        ;与上次不同,保存当前键值
 clr    keydown_cnt
 jmp    readkey_out
 readkey_out:
 bank 0
 bc    port9,k1
 bc    port9,k2
 bc    port9,k3
 bc    port9,k4            ;停止行输出
 bs    port7,led_con    ;扫描后打开指示灯使能端
 mov    a,port9_buff
 mov    port9,a            ;恢复指示灯状态
 ret
 |