在arduino uno,timer0配置上进行AVR组装?

时间:2016-05-27 18:44:34

标签: assembly timer avr

我正在考虑使用标准的bootloader(avra + avrdude)在Arduino UNO板上摆弄AVR系列的汇编编程中的寄存器。

我遇到Timer0问题。我把这个问题简化为一个应该

的简短程序
  • 打开红色LED(在B5 =引脚13上)
  • 将timer0配置为普通模式,预分频1024
  • 将计数器设为0
  • 进入循环,当计数器超过200
  • 时逃脱
  • 然后将绿色指示灯打开(在B4上)。

症状:绿色指示灯从不打开。如果其他值超过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

1 个答案:

答案 0 :(得分:1)

问题是常量:DDRBPORTBTCCR0BTCNT0等评估为给定的 I / O地址 SFR(可以将in/outTCCR0B一起使

解决方案是将TCNT0lds/stsin/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 datasheetthis 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的注册摘要。

您可能需要安装avraavr-objdump -b ihex -m avr5 -D *.hex才能使用此命令。