我的程序在装配上有问题。该程序应执行以下操作:
说“欢迎”>等一下>说“按2到(Str_roll_1)滚(Str_roll_2)”>如果按下2,开始滚动骰子,直到键释放>显示值并存储它>回到“按2滚”>重复
但由于某种原因,我无法理解,代码几乎跳过了"roll_dice“部分,在一个循环中显示”滚动“>”值“>”滚动“>”值: 0“>.以此类推
我用的是arduino leonardo电路板如果有什么帮助的话。我不知道这是不是足够的信息,但如果你需要更多的信息,只需问。谢谢:)
代码的主要部分:(我希望我没有包含的子程序非常清楚)
main:
PRINTSTRING Str_welcome
RCALL delay_1_s
RCALL lcd_clear_display
PRINTSTRING Str_roll_1
LDI RVAL, 0xC0
RCALL lcd_write_instr
PRINTSTRING Str_roll_2
loop:
CALL read_keyboard
LDI R25, 0x04
CP R25, RVAL
BREQ two
RJMP loop
two:
RCALL lcd_clear_display
PRINTSTRING Str_rolling
RCALL delay_1_s
RCALL roll_dice
RCALL store_stat
RCALL lcd_clear_display
PRINTSTRING Str_value
SUBI R24, -48
RCALL lcd_write_chr
RCALL delay_1_s
RJMP cont
cont:
RCALL lcd_clear_display
PRINTSTRING Str_roll_1
LDI RVAL, 0xC0
RCALL lcd_write_instr
PRINTSTRING Str_roll_2
RJMP loop
roll_dice:
LDI R16, 6
test:
NOP
NOP
RCALL read_keyboard
CPI RVAL, 0x04
BREQ roll
RET
roll:
DEC R16
BREQ roll_dice
RJMP test键盘文件/
map_table: .DB "147*2580369#"
read_keyboard:
LDI R18, 0 ; reset counter
LDI ZH, high(map_table <<1) ;Initialize Z pointer
LDI ZL, low(map_table <<1)
ADD ZL, RVAL ;Add index
LDI RVAL, 0x00
ADC ZH, RVAL ;Add 0 to catch Carry, if present
LPM RVAL, Z
scan_key:
MOV R19, R18
LSL R19
LSL R19
LSL R19
LSL R19
OUT PORTB, R19 ; set column and row在此处插入22条NOP线
SBIC PINE, 6
RJMP return_key_val
INC R18
CPI R18, 12
BRNE scan_key
LDI R18, NO_KEY ; no key was pressed!
return_key_val:
MOV RVAL, R18
RET发布于 2018-01-09 18:17:45
很可能你的问题不是软件,而是硬件。我敢打赌,如果你把示波器放在钥匙上,你就会看到它有触点反弹。开关会暂时关闭,但在成为稳定值之前,会重新打开和重新关闭几次。
这意味着,由于您离开您的延迟循环在第一次反弹发生,它似乎从来没有发生(虽然它做了非常简短)。如果您调用read_keyboard,如果键2处于活动状态,则打开一个引脚(或调试LED),如果键2处于非活动状态,则关闭它,您将看到稍后的键2正在工作,但是当它改变状态时,您将不会看到快速闪点。接触反弹通常是毫秒级,但在非常糟糕的开关上可能会更长。
通常,最好的解决方案是持续监视定时器中按钮的状态,并且只在引脚确定后更新全局状态变量。然后,您的主要代码将只查看经过适当过滤和稳定的状态。也有一些硬件方法可以做到这一点,所以您选择的确切解决方案取决于整个系统的设计。
发布于 2018-01-09 16:43:14
通过这样的操作,我发现开发过程并不那么复杂,因为组装可以很容易地演变成意大利面代码。
; ============================================================================================
; This pair of complimentary routines controls function of watchdog timer.
; ENTER: R24 = Bits 5 & 2:0 deliniate prescaler value WDP3:0 (11-2 pg 55)
; --------------------------------------------------------------------------------------------
.equ WDT_Change_Enable = (1 << WDCE) | (1 << WDE)
WDT_Enable:
in R20, SREG ; So I flag bit 7 will be returned in original state.
; During this process, we do not want interrupts or an inadvertant timeout of WDT.
cli ; Disable interrupts
wdr ; To be sure we have at least 16ms to setup
WDT_Set:
lds R25, WDTCSR ; 11.9.2 pg 54 Control Register
sbr R25, WDT_Change_Enable
sts WDTCSR, R25 ; Begin timmed sequence
sts WDTCSR, R24 ; Write desired parameters
; A change to watchdog can happen anywhere, so if global interrupts are already
; disabled, we do not want to change the flags state.
out SREG, R20 ; In order to not modify "I" flag.
ret
; ---------------------------------------------------------------------------------------------
WDT_Disable:
in R20, SREG ; See comments @ WDT_Enable
cli
wdr
; See note a bottom of page 52 ATMEL 8271I-AVR-10/2014
in R25, MCUSR ; 7.3.1 pg 11
cbr R25, WDRF ; Clear watchdog reset bit
out MCUSR, R25
; Reset watchdog enable, but retain prescaler.
lds R24, WDTCSR
cbr R24, RSET ; Clear bit so watchdog will be disabled.
rjmp WDT_Set这做了两件事。(1)它强化了一个概念,因为一旦您编写了注释,再次检查代码将做什么,(2)其他阅读者不必猜测任何部分正在做什么以及为什么要做。
Jester写道:
对我来说没有任何意义。
我很肯定,他并不是在暗示你的代码是荒谬的,相反,对你来说直观的并不是我们的直觉。我敢打赌,如果你花更多的时间来记录,问题就会突然出现在你身上,如果不是,那么对于那些你寻求帮助的人来说,理解你的逻辑就会容易得多。
你可能是对的,但我也发现,假设你没有包括的东西没有问题,那么就太冒失了。
https://stackoverflow.com/questions/48169208
复制相似问题