AVRでアセンブラーの練習 2007.08.31(金)〜 LessonA01。 LEDの高速点滅。
著作者名: 中野 良知 作成開始: 2007.08.30(木) 更新 : 2007.09.01(土) 更新 : 2009.10.30(金) △1 LessonA01.lzhのダウンロードを追加。
目次 1. 目的 2. フローチャート 3. プログラムソースコード 4. キーワード 4.1. ポート入出力方向設定 4.2. ポート出力 4.3. WDTの禁止 4.4. ループ 4.5. 汎用レジスター 4.6. I/Oレジスター 4.7. 名前付け 4.8. ビットシフト擬似命令 5. hexファイル 6. 動作確認 7. 実験回路 1. 目的 ポートBのビット0に接続したLEDを点滅させます。 2. フローチャート (main) ↓ ポートの初期化 アナログ比較器の電源OFF ウォッチドック動作禁止 ↓ ├────────────┐ ↓ │ ポートBのビット0に1を出力 │ ↓ │ ポートBのビット0に0を出力 │ ↓ │ └────────────┘ 3. プログラムソースコード LZH形式で圧縮してあります。 △1 LessonA01.lzhのダウンロード 下記のリストをコピー&ペーストする場合は、 シフト演算子"<<"を半角記号に変更してください。 ;============================================================= ; タイトル : LessonA01 ; 著者 : 中野 良知 ; 作成開始 : 2007.08.31(金) 作成開始 ; 最新修正 : 2007.08.31(金) ; 動作クロック : CLOCK=1MHz。内蔵RC発振器を使用 ;============================================================= ; インクルード .include "tn2313def.inc" ; ;============================================================= ; 汎用レジスターに名前を定義(変数定義) .def acc = R16 ; アキュムレーター ;============================================================= ; プログラム ;============================================================= .cseg ; CODE SEGMENT .org 0 ; ROMアドレス=0 start: // PORTB 初期化 ldi acc,$00 ; 出力データ out PORTB,acc ; PORTBの全ビットをLowに設定 ldi acc,$FF ; PORTB全ビット出力 out DDRB,acc ; PORTB入出力方向設定 // アナログ比較器初期化 sbi ACSR,ACD ; アナログ比較器電源オフ // ウォッチドッグ(WD)禁止 wdr ; WDタイマリセット in acc,MCUSR ; MCUSR値を取得 andi acc,~(1<<WDRF) ; WDRF=0 out MCUSR,acc ; WD RESETフラグ(WDRF)解除 in acc,WDTCSR ; 現WDTCSR値を取得 ori acc,(1<<WDCE)|(1<<WDE) ; WDCE=WDE=1を設定 out WDTCSR,acc ; WDCEとWDEに書き込み ldi acc,$00 ; WDCE=WDE=0を設定 out WDTCSR,acc ; WD禁止 led_on_off: sbi PORTB,0 ; PORTBのbit0に1を出力 cbi PORTB,0 ; PORTBのbit0に0を出力 rjmp led_on_off ; ループ ;============================================================= ; END ;============================================================= 4. キーワード 4.1. ポート入出力方向設定 ldi acc,$FF ; PORTB全ビット出力 out DDRB,acc ; PORTB入出力方向設定 I/Oレジスターには直接に値を設定できない為、汎用レジスター経由で設定します。 DDRBに設定した値によりポートBの入出力の方向が決まります。 4.2. ポート出力 バイト出力 汎用レジスター経由で出力します。 ldi acc,$00 ; 出力データ out PORTB,acc ; PORTBの全ビットをLowに設定 ビット出力 直接ビットを操作出来ます。 sbi PORTB,0 ; PORTBのbit0に1を出力 cbi PORTB,0 ; PORTBのbit0に0を出力 4.3. WDTの禁止 ウォッチドッグタイマーの動作を禁止し、カウントオーバーフローによる 強制リセットの発生を禁止します。 ATiny2313のデータシートに掲載されているアセンブリコード例を使用しました。 wdr ; WDタイマリセット in acc,MCUSR ; MCUSR値を取得 andi acc,~(1<<WDRF) ; WDRF=0 out MCUSR,acc ; WD RESETフラグ(WDRF)解除 in acc,WDTCSR ; 現WDTCSR値を取得 ori acc,(1<<WDCE)|(1<<WDE) ; WDCE=WDE=1を設定 out WDTCSR,acc ; WDCEとWDEに書き込み ldi acc,$00 ; WDCE=WDE=0を設定 out WDTCSR,acc ; WD禁止 4.4. ループ ジャンプ命令でループの先頭へジャンプします。 led_on_off: sbi PORTB,0 ; PORTBのbit0に1を出力 cbi PORTB,0 ; PORTBのbit0に0を出力 rjmp led_on_off ; ループ 4.5. 汎用レジスター 汎用レジスターは、R0からR31までの32個あります。 R0からR15までの機能には 汎用レジスター間のデータ転送 mov R0,R16 I/Oレジスター間のデータ転送 in R0,PINB; out PORTB,R0; インクリメント、デクリメント inc R0; dec R0; などがあります。 R16からR31までのレジスターには R0からR15までの機能の他に、値を直接設定できます。 ldi R16,$A3 ; R16にA3(16進)を設定 複数ビットの操作が出来ます。 sbr r16,$23 ; 00100011(2進)の値1の各ビットをセットします。 cbr r16,$23 ; 00100011(2進)の値1の各ビットをリセットします。 さらに R26とR27はXレジスタ R28とR29はYレジスタ R30とR31はZレジスタ のワードレジスターとして機能します。 st X+,R0 ; Xレジスターが指定するアドレスのSRAMにR0の値をストア ; した後、Xレジスターをインクリメントします。 4.6. I/Oレジスター ポートレジスター(PORTB,PINB)や、タイマー(TCNT0)その他に多くのI/Oレジスターが あります。 直接ビット操作が出来ます。 sbi PORTB,0 ; PORTBのbit0に1を出力 sbi ACSR,ACD ; アナログ比較器電源オフ 4.7. 名前付け プログラムを分かり易くする為にR16に名前を付けます。 汎用レジスターR16に、accという名前を付けます。 .def acc = R16 ; アキュムレーター ldi acc,$100; アセンブラーはaccをR16に翻訳して、アセンブルします。 4.8. ビットシフト擬似命令 シフト演算子"<<"は半角記号に変更してください。 ori acc,(1<<WDCE)|(1<<WDE) 1<<WDCEは、アセンブラーによって1<<4と翻訳されます。 WDCEの値は、tn2313def.inc に定義されています。 ;***** WDTCSR ***** .equ WDIF = 7 .equ WDIE = 6 .equ WDP3 = 5 .equ WDCE = 4 .equ WDE = 3 .equ WDP2 = 2 .equ WDP1 = 1 .equ WDP0 = 0 .equ WDTOE = 4 1<<4は 00000001(2進)を左に4回ビットシフトして、 00010000(2進)になります 同様に (1<<WDE)は1<<3で 00000001(2進)を左に3回ビットシフトして、 00001000(2進)になります (1<<WDCE)|(1<<WDE) は00010000(2進)と00001000(2進)の論理和を求めます。 00010000(2進) 論理和) 00001000(2進) ------------------------------ 00011000(2進) になります。 ori acc,(1<<WDCE)|(1<<WDE) はacc(R16)と求めた値との論理和を求め、結果をacc(R16)に代入します。 xxxxxxxx(2進) = acc(R16) 論理和) 00001100(2進) = 求めた値 ------------------------------------ xxxx11xx(2進) = acc(R16) 5. hexファイル アセンブラが生成したインテル形式の16進数ファイルです。 :020000020000FC :1000000000E008BB0FEF07BB479AA89504B7077F2E :1000100004BF01B5086101BD00E001BDC09AC098F0 :02002000FDCF12 :00000001FF 項目毎に区切りを入れました。 左から、 T=先頭文字、L=データ長、A=アドレス、R=レコードタイプ、D=データ、 C=チェックサムです。 T L A R D C -+--+----+--+--------------------------------+---- : 02 0000 02 0000 FC : 10 0000 00 00E008BB0FEF07BB479AA89504B7077F 2E : 10 0010 00 04BF01B5086101BD00E001BDC09AC098 F0 : 02 0020 00 FDCF 12 : 00 0000 01 FF データはASCII文字の2文字で1バイトを表します。 チェックサムの判定は、L+A+D+C=0ならはデータエラーはありません。 R:レコードタイプ 00 データ レコード 01 エンド レコード 02 セグメント アドレス レコード 6. 動作確認 2usec 4usec │←─→│←─────→│ ┌───┐ ┌───┐ RB0 ──┘ └───────┘ └─── sbi │ cbi │ rjmp │ sbi │ cbi │ sbi、cbi、rjmpのクロック数は2クロック。 クロック周波数が1MHzで、1命令の実行時間は2usecです。 led_on_off: sbi PORTB,0 2 ; PORTBのbit0に1を出力 cbi PORTB,0 2 ; PORTBのbit0に0を出力 rjmp led_on_off 2 ; ループ ↑ クロック数 7. 実験回路 ATtiny2313 ┌────┐20 │ VCC├────●────────●────●──── +5V │ │ │ │0.1u │ │ │ R10K ┴ /50V │┴│100u/16V │ │1 │ 0.1u/50V ┬ └┬┘ │ -RESET├────●───┤├───●────┘ │ │ │ │ │ LED │ │ │12 ┌─┬┐ │ │ RB0├──┤>│├─R220──● │ │ └─┴┘ │ │ │10 │ │ GND├─────────────●───────── 0V(GND) │ │ └────┘ 0.1u/50VのコンデンサーはVCCとGNDの近くに接続します。
LessonAのTopへ
サイトTopへ
法律条項 この資料により生じたいかなる障害や損害に対し、著者は全てを免責されるものとします。 この資料は、著作権法の下で保護され、入手先、著者、日付、法律条項を含んだ場合にのみ複製が可能です。
inserted by FC2 system