一、设计思路:在上期中运用定时器T1每隔10MS,检测一次按键,比较两次按键是否相同,会造成时间延迟,感觉有点不好。这次更改程序,直接通过按键后保存键值,进行两次键值的比较,从而确定是否有按键按下,以及按键是否改变,让单片机做出更快的响应,不知还有没有更好的方法,敬请个位指教谢谢。程序都带有注释,可以直接移植使用。
;电子琴尝试第二种方法,每按一次送一次初值
;P3按键端口
;p2.0--数码管位选
;p0---数码管段选
;p2.4--蜂鸣器FMQ
FMQ bit P2.4
ORG 0000H
AJMP MAIN
ORG 000BH
CPL FMQ
MOV TH0, R3 ;重装初值
MOV TL0, R4
RETI
ORG 0030H
MAIN:
MOV TMOD,#01H
SETB ET0
SETB EA
CLR P2.0
// MOV R2,#00H ;用于记录按键位置
// MOV 40H,#00H ;用于比较两次按键是否有区别
LOOP:ACALL KEYSAN ;按键检测
AJMP LOOP
KEYSAN:
MOV P3,#0FFH ;p3设为输入
JB P3.0,KEY1
MOV R2,#01H
AJMP KEYEND
KEY1: JB P3.1,KEY2
MOV R2,#02H
AJMP KEYEND
KEY2: JB P3.2,KEY3
MOV R2,#03H
AJMP KEYEND
KEY3: JB P3.3,KEY4
MOV R2,#04H
AJMP KEYEND
KEY4: JB P3.4,KEY5
MOV R2,#05H
AJMP KEYEND
KEY5: JB P3.5,KEY6
MOV R2,#06H
AJMP KEYEND
KEY6: JB P3.6,KEY7
MOV R2,#07H
AJMP KEYEND
KEY7: JB P3.7,KEY8
MOV R2,#08H
AJMP KEYEND
;key8表示没有按键按下,或者按键松手,关掉T0,数码不显示
KEY8: ;状态8,表示没有按键按下
MOV R2,#00H ;恢复初始状态
MOV 40H,R2
CLR TR0
MOV P0,#0ffh
sjmp ee ;
KEYEND: ACALL DATAPRO ;有按键按下调用处理数据
ACALL DISP ;有按键按下调用显示程序
ee: RET
DATAPRO:MOV A,R2 ;取按键值
CJNE A,40H,PP1 ;和原来键值进行比较,不相等转PP1,表示按键有变化
AJMP ENDPRO ;如果相等,则不进行数据更新
PP1: MOV 40H,R2 ;重新保存键值,为下一次比较准备
RL A ;A的值加倍,查频率表
MOV B,A ;A的暂存
MOV DPTR,#FREQ ;指向频率表的首地址
MOVC A,@A+DPTR
MOV R3,A ;高八位暂存R3,作为重装初值寄存器
MOV TH0,A
MOV A,B
INC A
MOVC A,@A+DPTR
MOV R4,A ;低八位暂存R4,作为重装初值寄存器
MOV TL0,A
SETB TR0 ;启动T0
ENDPRO: RET
DISP:
MOV A,R2 ;送按键值显示
ADD A,#(TAB-$-3)
MOVC A,@A+PC
MOV P0,A
DISP2: RET
FREQ: DW 0,64580,64684,64777,64820,64898,64968,65030,65058
TAB: DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H
END