Asynchronous 按钮不异步工作(8051代码)
这是我目前拥有的代码,应该在按下按钮时检测。如果我创建了一些函数,比如调用同步按钮函数(getkeysync)的firstmenu函数,那么程序就会运行,并返回正确的键。但是,如果我尝试了异步路由(通过getakey),并遵循此示例,在程序启动大约100毫秒后按“右”按钮运行,那么无论我按住它多少次,第二个菜单的选项都会被跳过,然后执行menuthree函数 我知道menuone、menutwo、MenuTree、menufour和menufive函数尚未实现,但这不是我的问题 有没有办法异步解决这个问题?我的意思是,我想在我的菜单中更频繁地使用getakey函数,在用户做出选择之后,我不想让CPU进入一个强制的无止境循环,直到按键被释放 事实上,我希望在轮到用户做出选择时能够处理其他函数(稍后我将创建这些函数)Asynchronous 按钮不异步工作(8051代码),asynchronous,microcontroller,interrupt,interrupt-handling,8051,Asynchronous,Microcontroller,Interrupt,Interrupt Handling,8051,这是我目前拥有的代码,应该在按下按钮时检测。如果我创建了一些函数,比如调用同步按钮函数(getkeysync)的firstmenu函数,那么程序就会运行,并返回正确的键。但是,如果我尝试了异步路由(通过getakey),并遵循此示例,在程序启动大约100毫秒后按“右”按钮运行,那么无论我按住它多少次,第二个菜单的选项都会被跳过,然后执行menuthree函数 我知道menuone、menutwo、MenuTree、menufour和menufive函数尚未实现,但这不是我的问题 有没有办法异步解
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
要处理来自不同来源的多个操作,可以使用状态机。变量定义状态。0可能是初始状态。菜单级别1可以是1000、2000等,子菜单1100。每次调用处理程序时,处理程序都应尽快返回。如果处理需要更多时间,请使用计时器和中断来细分处理时间或使用多个状态 主循环调用按钮和/或传感器处理程序以及菜单处理程序。当用户选择菜单时,状态会发生变化,因此当再次调用菜单时,它知道要做什么,动作和/或再次改变状态
通过这种方式,可以更轻松地跟踪何时发生的情况,保持用户交互异步,并快速响应。+1了解如何最小化代码大小。我将尝试将按钮处理程序放在主例程中,而不是中断,然后看看会发生什么。