Atmega32a汇编程序 - SRAM和定时器

时间:2014-04-05 09:58:41

标签: assembly avr

我正在学习汇编程序AVR并发现它令人困惑,下面这个简单的程序使用两个定时器,TIMER1用于使“OC1”以特定频率振动(CTC并切换OC1),TIMER0用于启动中断在一定的时间间隔内,此中断从SRAM加载字节并修改OCR1AL以更改频率。 (播放旋律)只有在特定的TIMER1间隔时,一切正常,当我将OCR0更改为更长或更短的间隔时,某些音符缺失,任何想法为什么?另一个问题是存储到存储器的最后一个音符没有被中断作为第一个加载,我必须存储一个额外的(空或任何值)以匹配st Z +和ld -Z。我做错了什么?感谢

使用的芯片是Atmega32a

/*
 * Melody.asm
 *
 *  Created: 03/04/14 8:17:54 PM
 *   Author: Michal
 */ 

    .equ MelodyStartAddr = 0x0301
    .equ NoteC1 = 0xEF // C
    .equ NoteD1 = 0xD4 // D
    .equ NoteE1 = 0xBD // E
    .equ NoteF1 = 0xB3 // F - 5 698 Hz
    .equ NoteG1 = 0x9F // G
    .equ NoteA1 = 0x8E // A
    .equ NoteH1 = 0x7E // H
    .equ NoteC2 = 0x77 // C

.def Temp = r16
.def TempH = r17
.def Zero = r0
.def Max = r1

//.cseg
.org 0x000
    rjmp Start1
.org 0x014 
    jmp ChangeNote


Start1:
    sei

        ldi Temp, HIGH(RAMEND)
        out SPH, Temp
        ldi Temp, LOW(RAMEND)
        out SPL, Temp

        ldi Temp, 0b11111111            // 
        out DDRD, Temp

        ldi YH, HIGH(MelodyStartAddr)
        ldi YL, LOW(MelodyStartAddr)

        ldi Temp, 0x00      // END
        st Z+, Temp

        ldi Temp, NoteE1
        st Z+, Temp
        ldi Temp, NoteE1
        st Z+, Temp

        ldi Temp, NoteE1
        st Z+, Temp
        ldi Temp, NoteE1
        st Z+, Temp

        ldi Temp, NoteF1
        st Z+, Temp
        ldi Temp, NoteF1
        st Z+, Temp
        ldi Temp, NoteG1

        ldi Temp, NoteG1
        st Z+, Temp
        ldi Temp, NoteG1
        st Z+, Temp
        ldi Temp, NoteA1
        st Z+, Temp

        ldi Temp, NoteG1
        st Z+, Temp
        ldi Temp, NoteG1
        st Z+, Temp
        ldi Temp, NoteG1
        st Z+, Temp
        ldi Temp, NoteF1
        st Z+, Temp
        ldi Temp, NoteA1
        st Z+, Temp

        ldi Temp, NoteF1
        st Z+, Temp
        ldi Temp, NoteF1
        st Z+, Temp
        ldi Temp, NoteF1
        st Z+, Temp
        ldi Temp, NoteF1
        st Z+, Temp
        ldi Temp, NoteF1
        st Z+, Temp
        ldi Temp, NoteF1
        st Z+, Temp
        ldi Temp, NoteG1
        st Z+, Temp
        ldi Temp, NoteA1
        st Z+, Temp
        ldi Temp, NoteA1
        st Z+, Temp
        ldi Temp, NoteC2
        st Z+, Temp
        ldi Temp, NoteA1
        st Z+, Temp
        ldi Temp, NoteA1
        st Z+, Temp
        ldi Temp, NoteA1
        st Z+, Temp
        ldi Temp, NoteC2
        st Z+, Temp
        ldi Temp, NoteC2
        st Z+, Temp
        ldi Temp, NoteC2
        st Z+, Temp

        ldi Temp, NoteC2        // This is the extra Note that is not loaded in the interrupt 
        st Z+, Temp


        // ************* TIMER 1 ***********************    

        ldi Temp, 0b01000000 //  toggle oc1
        out TCCR1A, Temp

        ldi Temp, 0b00001010 //  WGM11, prescaler x8
        out TCCR1B, Temp

        ldi Temp, 0x00
        out OCR1AH, Temp

        //********** TIMER 0*******************************
        ldi Temp, 0b00011101            // 0b00011011 x64
        OUT TCCR0, Temp

        ldi Temp, 0xea              // Speed Works with 0xef, but not with 0xaf or 0xff or 0xea, any idea ?
        out OCR0, Temp

        ldi Temp, 0b00000010
        OUT TIMSK, Temp

Loop: 
nop
    rjmp Loop


ChangeNote:
        push Temp
        in Temp, SREG
        push Temp

        ldi Temp, 0x00
        out OCR1AH, Temp
        ld Temp, -Z
        cpi Temp, 0x00
        breq StopPlaying

        out OCR1AL, temp

        pop Temp
        out SREG, Temp
        pop Temp

    reti

StopPlaying:
    ldi Temp, 0x00
    out TIMSK, Temp
    ldi Temp, 0b00000000 //  toggle oc1
    out TCCR1A, Temp
ret


Delay:
    clr R1
    ldi TempH, 0xaf
    mov R2, TempH
    DelayLoop:
    dec R1
    brne DelayLoop
    clr R1
    dec R2
    brne DelayLoop

ret

2 个答案:

答案 0 :(得分:0)

为什么要将内存缓冲区的偏移量加载到Y寄存器,然后使用Z寄存器来存储和加载旋律?

ldi YH, HIGH(MelodyStartAddr)
ldi YL, LOW(MelodyStartAddr)
...
st Z+, Temp
...
ld Temp, -Z

答案 1 :(得分:0)

在对您的代码进行合理彻底检查后,我也无法看到计时器ISR的问题。应该真的有效。如果它在模拟器中工作,则可能存在某种硬件问题。

旁注:你没有初始化OCR1AL(尽管在重置后它应该为0)。

至于你的第二个问题:

  

我必须存储一个额外的(空的或任何值)以匹配st Z +   用ld -Z

你不应该这样做。

st Z+, Temp
ld Temp, -Z

将存储Temp并立即检索存储的值。 Z+是"后递增",这意味着Temp存储到Z然后 Z递增。 -Z是"预先减少",其中Z递减,然后从现在指向的位置Z检索值。