AVRマイコン アセンブリ言語入門 ― 8bitタイマその4
さて、今回はいよいよ8bitタイマを使ったLED点滅プログラムを作ってみます。
まずは、レジスタの設定値を決めます。
前回の復習 ー 設定する項目は
- 動作モード:ノーマルモードかCTCモードか等
- プリスケーラの値
- カウント比較値
- 割込み要求の設定
になります。
今回は、200msごとにLEDを点滅させてみます。
この200msを8bitタイマを使って作り出します。
CPUクロックはデフォルトでは1MHzなので、クロック1パルスが1μs、
プリスケーラを1024にしてカウント比較値を196にすると
1μs×1024×196 = 200.704ms
これで行きます。
使用するのはタイマ0、動作モードは以前話したようにCTCモード一択なので、これでレジスタ値が全部決まります。
- 動作モード :CTCモード -> WGM02〜WGM00 = 010
- プリスケーラの値 :1024 -> CS02〜CS00 = 101
- カウント比較値 :196 -> OCR0A = 0b11000100 = 0xC4
前回の表にこれらの値を入れると、それぞれのレジスタ値は以下になります。
TCCR0A = 0b00000010
TCCR0B = 0b00000101
OCR0A = 0b11000100 = 0xC4
さあ準備が出来ました。
プログラムを書いていきます。
/* * LED_Timer.asm * * Created: 2015/09/16 20:56:21 * Author: Takachiho */ ; PortBのBit0に接続したLEDを、 ; Timer0のCTCモードを使って点滅させる ; 約200ms間隔で点滅させる .include "m168pdef.inc" ;************************************************ ; 各種定義 ;************************************************ ;-------------------- ; 汎用レジスタ ;-------------------- .def STACK = R16 ;汎用レジスタR16に'STACK'という名前をつける ;-------------------- ; 割り込みベクタ定義 ;-------------------- .CSEG RJMP MAIN .ORG 0x001C ;8bitタイマ0からの割込みが発生すると ;マイコンはこのアドレスを実行する。 RJMP ICTC0 ;ラベルICTC0へジャンプする。 ;************************************************ ; 割り込みルーチン タイマ0 ;************************************************ ICTC0: ;------- ステータスレジスタの内容を退避 -------- IN STACK, SREG ;------- LED ON/OFF を切り替え ------------------ IN R17, PORTB ;PortBの内容をR17へコピーする LDI R18, 0x01 ;R18へ値0x01 = 0b00000001を代入 EOR R17, R18 ;R17とR18の排他的ORの結果をR17へ OUT PORTB, R17 ;R17の結果をPortBへ代入する ;排他的論理和(エクスクルーシブオア)は、ビット反転に使われる。 ;'1'とのEORをとると、相手が'1'なら'0'へ、'0'なら'1'へ ;反転する。 ;この性質を利用して、LEDが点灯'1’しているなら消灯'0' ;消灯しているなら点灯させる動作を行わせる。 ;------- ステータスレジスタの内容を復帰 -------- OUT SREG, STACK RETI ;************************************************ ; メイン・ルーチン (MAIN) ;************************************************ MAIN: ;------- 全割り込み禁止 ------------------------- CLI ;------- PORT 設定 ----------------------------- LDI R17, 0b11111111 ;ポートBは全て出力に設定 OUT DDRB, R17 LDI R17, 0b00000001 ;bit0以外すべて'0'出力 OUT PORTB, R17 LDI R17, 0b11111111 ;ポートCは全て出力に設定 OUT DDRC, R17 LDI R17, 0b00000000 ;すべて'0'出力 OUT PORTC, R17 LDI R17, 0b11111111 ;ポートDは全て出力に設定 OUT DDRD, R17 LDI R17, 0b00000000 ;すべて'0'出力 OUT PORTD, R17 ;------- 8bitタイマレジスタ設定 --------------- ;------- 動作モード 設定 ------- LDI R17, 0b00000010 ;CTCモードを指定 OUT TCCR0A, R17 ;------- プリスケーラ 設定 ------- LDI R17, 0b00000101 ;プリスケーラ 1024 OUT TCCR0B, R17 ;------- 比較値 セット ------- LDI R17, 0xC4 ;比較値196 = 0xC4に設定 OUT OCR0A, R17 ;------- タイマ割り込み許可 ------- LDS R17, TIMSK0 ;TIMSK0レジスタの値をR17へ SBR R17, (1 << OCIE0A) ;ビット1(OCIE0A)を'1'へセット STS TIMSK0, R17 ;TIMSK0レジスタに値を代入 ;TIMSK0レジスタのビット1(OCIE0A)を'1'へセットすることにより ;カウント値がOCR0Aレジスタ(タイマ/カウンタ0比較レジスタA)の値と ;一致した時、割込みを発生させる。 ;------- 全割り込み許可 ----------------------- SEI MAIN01: RJMP MAIN01
で、実行させました。
大成功!
・・・って、写真じゃ点滅しているところがわからないですね。
あと、プログラムの割込みのあたりが良くわからないかもしれません。
次回は割込み動作の説明をしたいと思います。