タイマー0 / CTCモード / 途中でコンペア値をロードし直す / 割り込みを使う

pp.479-480

前回と同じようなことを今度は割り込みを使っておこなう。

下のプログラムは、コンペアマッチするたびに0,1,2,4,8,16,32,64の順番でコンペア値をロードし直す。
f:id:ti-nspire:20200717114100p:plain:w600

; スタックポインタの初期化マクロ
.MACRO INITSTACK
    LDI R16, HIGH(RAMEND)
    OUT SPH, R16
    LDI R16, LOW(RAMEND)
    OUT SPL, R16
.ENDMACRO

.ORG 0x0
    RJMP MAIN

.ORG OC0Aaddr ; 0x1C
    RJMP TIMER0_COMPA

WAVE_TABLE:
    .DB 0,1,2,4,8,16,32,64

MAIN:
    INITSTACK

    SBI DDRD, PD6

    ; リセット直後から最初のパルスのrising edgeまでの長さを設定する。
    LDI R20, 69
    OUT OCR0A, R20

BEGIN:
    ; コンペアマッチA時にトグル。CTCモード。
    LDI R20, (1 << COM0A0) | (1 << WGM01)
    OUT TCCR0A, R20
    
    ; 1024分周してカウント。
    LDI R20, (1 << CS02) | (1 << CS00)
    OUT TCCR0B, R20

    ; コンペアマッチA割り込みを有効化。
    LDI R20, 1 << OCIE0A
    STS TIMSK0, R20

    SEI

HERE:
    RJMP HERE

TIMER0_COMPA:
    DEC R29
    BRPL L1                    ; BRPLはBranch if Plus。
    LDI R30, (WAVE_TABLE << 1) ; R30はZL。
    LDI R29, 7

L1:
    LPM R28, Z+    ; LPMはLoad Program Memory。
    OUT OCR0A, R28 ; WAVE_TABLEの値を順番にコンペア値Aとしてロードし直す。
    RETI