這是我當前有的代碼,當按下按鈕時應該檢測到這些代碼。如果我創建函數,比如我調用同步按鈕函數(getkeysync)的firstmenu函數,那麼程序將工作並返回正確的密鑰。但是,如果我嘗試了異步路由(通過getakey)並遵循此示例,並在程序啓動後約100毫秒按「右鍵」運行它,那麼無論我按住多少鍵,第二個菜單的選項被跳過,然後執行menuthree功能。按鈕不是異步工作的(8051代碼)
我明白menuone,menutwo,menuthree,menufour和menufive函數尚未實現,但那不是我的問題。
有沒有辦法可以異步解決這個問題?我的意思是,我想在我的菜單中更頻繁地使用getakey函數,並且在用戶做出選擇之後,我不想讓CPU進入強制無限循環,直到密鑰被釋放。
事實上,我希望能夠處理其他功能(稍後將創建),而輪到用戶做出選擇。
KCENTER equ 3 ;this value is returned if both left and right keys are pressed at once.
KLEFT equ 2 ;left key pressed value
KRIGHT equ 1 ;right key pressed value
KCENTERH equ 7 ;both left and right keys held down
mov TL1,#0h ;reset timer reload values
mov TH1,#0h
mov TMOD,#22h ;Timer=0-255
mov SP,#055h ;set stack
setb ET1 ;enable timer interrupt
setb EA ;enable all interrupts
clr TF1 ;clear overflow flag
setb TR1 ;start timer
firstmenu:
lcall printfirstmenu ;function (not shown) to display first menu
lcall getfkey ;stall until key is pressed
cjne R6,#KCENTER,centerb
ljmp menufour ;go to menufour if center is pressed
centerb:
cjne R6,#KLEFT,leftb
ljmp menufive ;go to menufive if left is pressed
leftb:
cjne R6,#KRIGHT,rightb
ljmp somemenu ;go to somemenu if right is pressed (this works)
rightb:
somemenu:
clr KEYDET ;clear detection
lcall printamenu ;function (not shown) to display a menu
menu2:
lcall getakey ;try to get key without stalling. Return 0 if no key.
cjne R6,#KCENTERH,nohold
;center key held down
subb A,#33h ;compare hold time to time it takes to execute 51 interrupts
jc timelow ;if time is high enough...
ljmp othermenu ;then go to previous menu
timelow:
clr C ;clear carry. If center hold doesn't work, then no other key counts.
nohold:
jnc menu2 ;if no static key is pressed, jump back.
cjne R6,#KCENTER,centerk
ljmp menuone ;go to menuone if center is pressed
centerk:
cjne R6,#KLEFT,leftk
ljmp menutwo ;go to menutwo if center is pressed
leftk:
cjne R6,#KRIGHT,rightk
ljmp menuthree ;go to menuthree if right is pressed (but this always executes without waiting for user input!)
rightk:
ljmp menu2
InterruptHandler:
clr EA ;turn interrupts off
clr TR1 ;turn timer off
clr TF1 ;clear timer overflow
push ACC ;save A
push PSW ;save PSW
lcall prockey ;run key function
mov TL1,#0h ;reset reload counters
mov TH1,#0h
pop PSW ;restore PSW
pop ACC ;restore A
setb EA ;turn interrupts on
setb TR1 ;turn timer on
reti ;exit interrupt
;function getkeysync forces stall until key is returned.
;all key values are stored in R6.
getkeysync:
clr KEYDET
getkeysync2:
lcall getakey
jnc getkeysync2
ret
;Get values and return immediately (async function)
getakey:
mov R6,GOTKEY
mov C,KEYDET
mov A,KEYMD
ret
;process key interrupt
;LKEY and RKEY are independant hardware keys with inverted values.
;values: 0=pressed, 1=not pressed
;the KEYS variable stores bit information of captured keys
prockey:
mov C,LKEY
cpl C
mov KEYS.1,C ;2nd LSB of KEYS is LKEY true value
mov C,RKEY
cpl C
mov KEYS.0,C ;LSB of KEYS is RKEY true value
mov A,KEYS
anl A,#3h ;Possible values for A: 0=nothing pressed, 1=Right, 2=left, 3=both.
jz gotnokey
;key detected as pressed.
clr KEYDET
mov KEYTEMP,#0h
inc KEYHOLD ;increment hold counter once per interrupt call
mov A,KEYHOLD ;if counter goes past 255 then assume key press is valid.
jnz keyend
;here, the key is alwats held down for 255 interrupt calls 255 times
;and can safely assume the user hit the key (and not debounce)
setb KEYS.2 ;set flag
mov KEYHOLD,#0FFh ;set to FF so this section executes continuously until key is let go.
mov KEYTEMP,KEYS ;copy key value with flag to a temporary variable
inc KEYMD
mov A,KEYMD ;increase mega delay counter (keymd) to detect long key presses
jnz keyend
mov KEYMD,#0FFh
ljmp keyend
gotnokey:
;here the system thinks key wasn't pressed
mov KEYMD,#0h ;reset extended counter
dec KEYHOLD ;lower short key hold counter
mov A,KEYHOLD
inc A
jnz keyend
;once hold counter is below zero, reset to zero and detect key
mov KEYHOLD,#0h
jnb KEYTEMP.2,keyend
;here, keypress is valid
clr KEYTEMP.2 ;so invalidate the bit
clr KEYS.2 ;in both variables
setb KEYDET ;and set key detection flag
keyend:
;this gets executed at the end of prockey
mov A,KEYTEMP ;get saved key
anl A,#7h ;only accept lower 3 bits
mov GOTKEY,A ;and set output key variable to it
jnb KEYDET,noreskey
mov KEYTEMP,#0h ;clear temporary key if key is detected
noreskey:
ret
+1思考一種方法來最小化代碼大小。我將嘗試將按鈕處理程序放在主例程中而不是中斷,並查看會發生什麼。 – Mike