ノーマルモードのTimer2で時間遅延を生成する

p.294
一定の時間が経過するたびにPB6の出力をトグルする。

Timer0と大きく違うのは、印で示した行だけである。目的のI/Oレジスタが拡張I/Oメモリースペースに存在しているので、OUTの代わりにSTSを使う。STSはStore Direct to Data Space。

OUTは2バイト命令、1実行サイクル。
STSは4バイト命令、2実行サイクル。

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

    ; スタックポインタを初期化して、
    INITSTACK

    ; PB6のIOをOUTにして、
    SBI DDRB, 6

    ; PB6からHを出力して、(トグルの初期値なのでLにしても同じ)
    LDI R17, 1 << PB6
    OUT PORTB, R17
    
    ; PB6をトグルするためのマスクビットをセットして、
    LDI R16, 1 << PB6

BEGIN:
    ; 待って、
    RCALL DELAY

    ; PB6の出力をトグルして、
    EOR R17, R16
    OUT PORTB, R17

    ; を無限に繰り返す。
    RJMP BEGIN

;;;;;;; 時間遅延ルーチン ;;;;;;;
DELAY:
    ; Timer2の初期カウント値を設定して、
    LDI R20, 0xF2
    STS TCNT2, R20 ; ★

    ; Timer2をノーマルモードにして、 
    LDI R20, 0
    STS TCCR2A, R20 ; ★

    ; CS00ビットを1 (クロックを1分周)にしてTimer2をスタートする。
    LDI R20, 1 << CS00
    STS TCCR2B, R20 ; ★

AGAIN:
    ; Timer2がオーバーフローするまでとどまって、(すなわちTOV2がセットされたら次の命令をスキップして、)
    ; Skip if Bit in I/O Register is Set
    SBIS TIFR2, TOV2
    RJMP AGAIN

    ; Timer2がオーバーフローしたらTimer2をストップして、
    LDI R20, 0
    STS TCCR2B, R20 ; ★

    ; Timer0のオーバーフローフラグをクリアして、     
    LDI R20, 1 << TOV2
    OUT TIFR2, R20

    ; 時間遅延ルーチンを抜ける。
    RET

f:id:ti-nspire:20200422075028p:plain