我正在考虑使用标准的bootloader(avra + avrdude)在Arduino UNO板上摆弄AVR系列的汇编编程中的寄存器。
我遇到Timer0问题。我把这个问题简化为一个应该
的简短程序症状:绿色指示灯从不打开。如果其他值超过200,则在随机持续时间(秒)后开启。
以下是代码:
.include "./m328Pdef.inc"
.EQU ROUGE = 0b0100000 ; red
.EQU VERT = 0b0010000 ; green
main:
ldi r16,ROUGE+VERT ; pins activated
out DDRB,r16
ldi r16,ROUGE ; red on
out portB,r16
;; configure timer
lds r16,TCCR0B
andi r16,0b11111000
ori r16,0b00000101 ; prescale 1024
sts TCCR0B,r16
ldi r16,0 ; count is 0
sts TCNT0,r16
loop:
lds r16,TCNT0
cpi r16,100
brlo loop
ldi r16,VERT ; green on
out PortB,r16
z:
nop
rjmp z
相同的程序似乎与Timer1及其相关寄存器一起正常工作。
怎么了?一些干扰引导加载程序?
编辑hex文件:
:020000020000FC
:1000000000E304B900E205B900912500087F05600E
:100010000093250000E0009326000091260004369E
:0A002000E0F300E105B90000FECF97
:00000001FF
编译者:avra bug0.asm
上传:
avrdude -q -V -D -p atmega328p -C /etc/avrdude.conf \
-c arduino -b 115200 -P /dev/ttyACM0 \
-U flash:w:bug0.hex:i
答案 0 :(得分:1)
问题是常量:DDRB
,PORTB
,TCCR0B
,TCNT0
等评估为给定的 I / O地址 SFR(可以将in/out
与TCCR0B
一起使
解决方案是将TCNT0
与lds/sts
和in/out
一起使用 - 没关系,因为这些寄存器属于 I / O寄存器(相反)到扩展I / O寄存器,必须使用它们的数据空间地址访问):
TCCR0B
或将此I / O地址转换为数据空间地址:
TCNT0
有关为什么必须将 .include "./m328Pdef.inc"
.EQU ROUGE = 0b0100000 ; red
.EQU VERT = 0b0010000 ; green
main:
ldi r16,ROUGE+VERT ; pins activated
out DDRB,r16
ldi r16,ROUGE ; red on
out portB,r16
;; configure timer
in r16,TCCR0B
andi r16,0b11111000
ori r16,0b00000101 ; prescale 1024
out TCCR0B,r16
ldi r16,0 ; count is 0
out TCNT0,r16
loop:
in r16,TCNT0
cpi r16,100
brlo loop
ldi r16,VERT ; green on
out PortB,r16
z:
nop
rjmp z
添加到这些常量的信息,请参见第19页的章节8.3 SRAM数据存储器(尤其是图中的m328p datasheet和this bug report。
为什么原始代码适用于timer1?
Timer1寄存器位于扩展I / O空间中, .include "./m328Pdef.inc"
.EQU ROUGE = 0b0100000 ; red
.EQU VERT = 0b0010000 ; green
main:
ldi r16,ROUGE+VERT ; pins activated
out DDRB,r16
ldi r16,ROUGE ; red on
out portB,r16
;; configure timer
lds r16,TCCR0B+0x20
andi r16,0b11111000
ori r16,0b00000101 ; prescale 1024
sts TCCR0B+0x20,r16
ldi r16,0 ; count is 0
sts TCNT0+0x20,r16
loop:
lds r16,TCNT0+0x20
cpi r16,100
brlo loop
ldi r16,VERT ; green on
out PortB,r16
z:
nop
rjmp z
可能用扩展I / O空间地址替换它们的名称(因为它们甚至没有I / O空间地址)。
为什么原始代码在timer0中表现不稳定?
可以将0x20
写为avra
,读取浮动引脚的状态(或多或少)随机结果。
要查看代码lds r16,TCNT0
对我使用命令lds r16,PINC+0x20
做了什么,它会显示实际写入微控制器的内容。
对于SFR地址,请参阅第36章the aforementioned atmega328p datasheet的注册摘要。
您可能需要安装avra
或avr-objdump -b ihex -m avr5 -D *.hex
才能使用此命令。