AVRでアセンブラーの練習 2007.09.05(水)〜 LessonA04。 ステッピングモータを回す。
著作者名: 中野 良知 作成開始: 2007.09.04(火) 更新 : 2009.08.02(日) △1 誤記訂正 intr_time:→intr_time0:
目次 1. 目的 2. フローチャート 3. プログラムソースコード 4. キーワード 4.1. データテーブル 4.2. ROMデータポインター(Zレジスター) 4.3. ステップパルス 5. 動作確認 6. 実験回路 1. 目的 ステッピングモータの1-2相駆動信号を発生します。 ステップパルスデータをROMデータテーブルに設定。 Zレジスターで間接指定してROMデータを読み出します。 2. フローチャート (main) ↓ ポートの初期化 アナログ比較器の電源OFF ウォッチドック動作禁止 タイマー0初期化。1msec毎にオーバーフロー割込み Zレジスター初期化 ↓ ├────────────┐ ↓ No │ <t1msに変化あり>─────→┤ ↓Yes │ Zレジスターの間接指定で │ ステップパルスデータを取得 │ ↓ │ ステップパルスデータ出力 │ ↓ │ Zレジスターインクリメント │ ↓ No │ <データ一巡>───────→┤ ↓Yes │ Zレジスター初期化 │ ↓ │ └────────────┘ (タイマー0割込み) ↓ ステータスレジスター退避 ↓ acc退避 ↓ タイマー0カウンター設定 ↓ 1msecカウンターインクリメント ↓ acc復帰 ↓ ステータスレジスター復帰 ↓ (終了) 3. プログラムソースコード 全角のシフト記号"<<"は半角記号に変更してください。 ;============================================================= ; タイトル : LessonA04 ; 著者 : 中野 良知 ; 作成開始 : 2007.09.04(火) 作成開始 ; 最新修正 : 2007.09.04(火) ; 動作クロック : CLOCK=1MHz。内蔵RC発振器を使用 ;============================================================= ; インクルード .include "tn2313def.inc" ; ;============================================================= ; 定数定義 ;============================================================= ; タイマカウント .equ T1MSEC = 256 - 125 ; CLOCK=1MHz、Pre Scale=1/8、1msec .equ PRE_SCALE = $02 ; 1/8。タイマスタート .equ TINIT = 256 - 10 ; ;============================================================= ; 汎用レジスターに名前を定義(変数定義) .def sreg_save = R0 ; SREG保存用 .def tim_save = R1 ; タイマカウンタ保存用 .def acc = R16 ; アキュムレーター .def t1ms = R17 ; 1msecタイマカウンタ ;============================================================= ; SRAM定義 ;============================================================= ; スタック .equ STACK_INIT = $00DF ; スタック初期値 .dseg ; データセグメント=SRAM .org STACK_INIT ; stack_top: .byte 1 ; 昇順で使用。ダミーの1バイトを確保 ;============================================================= ; プログラム ;============================================================= .cseg ; CODE SEGMENT ;============================================================= ; リセットスタートベクター ;============================================================= .org 0 ; リセットスタートベクタ start: rjmp main ; mainへ ;============================================================= ; タイマ0オーバーフロー割込みベクター ;============================================================= .org 6 ; タイマ/カウンタ0オバーフロベクタ rjmp intr_time0 ; intr_time0へ △1 ;============================================================= ; メイン ;============================================================= main: // スタックポインター初期化 ldi acc,low(STACK_INIT) ; out spl,acc ; スタックポインター下位設定 // 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禁止 // Timer/Counter 0 初期化 // TCCR0A=0x00 ; 標準動作 in acc,TIMSK ; タイマ割込みマスクレジスタ取得 sbr acc,(1<<TOIE0) ; オーバーフロー割込み許可ビットセット out TIMSK,acc ; タイマ0 オーバーフロー割込み許可 ldi acc,T1MSEC ; 1msecカウント値 out TCNT0,acc ; タイマ0カウンタ設定 ldi acc,PRE_SCALE ; プリスケール値。1/8。8usec。 out TCCR0B,acc ; タイマ0スタート。プリスケール設定 clr t1ms ; 1msecカウンタ初期化 // ステップパルスデータポインター初期化 ldi ZL,low(step_pulse<<1) ; ldi ZH,high(step_pulse<<1) ; sei ; 全割込み許可 step_pulse_out: cp t1ms,tim_save ; t1msに変化? breq step_pulse_out ; No mov tim_save,t1ms ; Yes。1msecカウンタ値を保存 lpm acc,Z+ ; ROMからステップパルスデータ取得 out PORTB,acc ; ステップパルス出力 // ステップパルスデータポインターの一巡チェック cpi ZL,low(step_pulse_end<<1) ; データポインタ下位一致? brne step_pulse_out ; No cpi ZH,high(step_pulse_end<<1) ; Yes。データポインタ上位一致? brne step_pulse_out ; No ldi ZL,low(step_pulse<<1) ; データポインター下位初期化 ldi ZH,high(step_pulse<<1) ; データポインター上位初期化 rjmp step_pulse_out ; ループ ;============================================================= ; ステップパルスデータ ;============================================================= step_pulse: .db 1, 1 + 4, 4, 4 + 2, 2, 2 + 8, 8, 8 + 1; step_pulse_end: ;============================================================= ; タイマ0割込み ;============================================================= intr_time0: in sreg_save,SREG ; ステータスを退避 push acc ; acc退避 ldi acc,T1MSEC ; 1msecカウント値 out TCNT0,acc ; タイマ0カウンタ設定 inc t1ms ; 1msecカウント pop acc ; acc復帰 out SREG,sreg_save ; ステータスを復帰 reti ; ;============================================================= ;============================================================= ; END ;============================================================= 4. キーワード 4.1. データテーブル ステッピングモータを1-2相駆動で制御するためのステップパルスデータを格納した テーブルです。 step_pulse: .db 1, 1 + 4, 4, 4 + 2, 2, 2 + 8, 8, 8 + 1; step_pulse_end: を配列に書きなおすと ┌─┬─┬─┬─┬─┬─┬─┬─┐ │ 1│ 5│ 4│ 6│ 2│10│ 8│ 9│ └─┴─┴─┴─┴─┴─┴─┴─┘ ですが、ROMにはワード(2バイト)単位で、 ROMデータ ROMアドレス 上位 下位 ラベル名 ├──┼──┤ $002F │ 5 │ 1 │ step_pulse: ├──┼──┤ $0030 │ 6 │ 4 │ ├──┼──┤ $0031 │ 10 │ 2 │ ├──┼──┤ $0032 │ 9 │ 8 │ ├──┼──┤ $0033 │ │ │ step_pulse_end: ├──┼──┤ の様に割り付けられます。 4.2. ROMデータポインター(Zレジスター) Zレジスターを間接指定のポインターとして使用し、LPM命令でROM領域のデータを 汎用レジスターに転送します。 Zレジスターには、ROMデータテーブルの先頭番地の値を左に1回シフトして設定しま す。 // ステップパルスデータポインター初期化 ldi ZL,low(step_pulse<<1) ; ldi ZH,high(step_pulse<<1) ; step_pulseのアドレスが$002Fの時、ZLには$5Eが設定され、ZHには$00が設定されま す。 step_pulse:のアドレス$002Fの2進表記 ┌─┬─┬─┬─┼─┬─┬─┬─┼─┬─┬─┬─┼─┬─┬─┬─┐ │ 0│ 0│ 0│ 0│ 0│ 0│ 0│ 0│ 0│ 0│ 1│ 0│ 1│ 1│ 1│ 1│ └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘ $002Fを左に1回ビットシフトした後のZ=$005Eの2進表記 ┌─┬─┬─┬─┼─┬─┬─┬─┼─┬─┬─┬─┼─┬─┬─┬─┐ │ 0│ 0│ 0│ 0│ 0│ 0│ 0│ 0│ 0│ 1│ 0│ 1│ 1│ 1│ 1│ 0│ └─┴─┴─┼─┴─┴─┴─┼─┴─┴─┴─┼─┴─┴─┴─┼─┘ ├─────────────────────────────┤↓ ROMアドレス=$002F │ │ ZレジスターのLSBの値でROMデータの下位と上位を指定します。 │ ┌──┬───────────────────┘ ↓1 ↓0 ROMデータ ROMアドレス 上位 下位 ラベル名 ├──┼──┤ $002F │ 5 │ 1 │ step_pulse: ├──┼──┤ $0030 │ 6 │ 4 │ ├──┼──┤ $0031 │ 10 │ 2 │ ├──┼──┤ $0032 │ 9 │ 8 │ ├──┼──┤ $0033 │ │ │ step_pulse_end: ├──┼──┤ lpm acc,Z+ ; ステップパルスデータ取得 でacc(R16)にテーブルのデータが転送され、その後Zレジスターがインクリメント されます。 Z=$005Eの2進表記 ┌─┬─┬─┬─┼─┬─┬─┬─┼─┬─┬─┬─┼─┬─┬─┬─┐ │ 0│ 0│ 0│ 0│ 0│ 0│ 0│ 0│ 0│ 1│ 0│ 1│ 1│ 1│ 1│ 0│ └─┴─┴─┼─┴─┴─┴─┼─┴─┴─┴─┼─┴─┴─┴─┼─┘ ├─────────────────────────────┤│ ROMアドレス=$002F │ ↓ ROM $002F番地の下位バイトが 指定されます。 インクリメントして Z=$005Fの2進表記 ┌─┬─┬─┬─┼─┬─┬─┬─┼─┬─┬─┬─┼─┬─┬─┬─┐ │ 0│ 0│ 0│ 0│ 0│ 0│ 0│ 0│ 0│ 1│ 0│ 1│ 1│ 1│ 1│ 1│ └─┴─┴─┼─┴─┴─┴─┼─┴─┴─┴─┼─┴─┴─┴─┼─┘ ├─────────────────────────────┤│ ROMアドレス=$002F │ ↓ ROM $002F番地の上位バイトが 指定されます。 更に lpm acc,Z+ ; ステップパルスデータ取得 を実行すると、Zレジスターの値は$0060になります。 $0060の2進表記 ┌─┬─┬─┬─┼─┬─┬─┬─┼─┬─┬─┬─┼─┬─┬─┬─┐ │ 0│ 0│ 0│ 0│ 0│ 0│ 0│ 0│ 0│ 1│ 1│ 0│ 0│ 0│ 0│ 0│ └─┴─┴─┼─┴─┴─┴─┼─┴─┴─┴─┼─┴─┴─┴─┼─┘ ├─────────────────────────────┤│ ROMアドレス=$0030 │ ↓ ROM $0030番地の下位バイトが 指定されます。 4.3. ステップパルス 1-2相駆動のステップパルスを出力します。 PORTBの各ビットに、ステッピングモータのそれぞれの相を割り当てます。 PB0= A相 PB1=-A相 PB2= B相 PB3=-B相 各相のタイミングチャートは動作確認を参照して下さい。 5. 動作確認 ┌─────┐ ┌── A相 ──────┘ └─────────┘ ┐ ┌─────┐ B相 └─────────┘ └──────── ────┐ ┌─────┐ -A相 └─────────┘ └──── ┌─────┐ ┌─────┐ -B相 ──┘ └─────────┘ └ →├─┤← 0.96msec →├─────┤← 2.96msec 6. 実験回路 ATtiny2313 ┌────┐20 │ VCC├──────●──────●────●──── +5V │ │ R1│ C2│0.1u │ C3 │ │ R10K C1 ┴ /50V │┴│100u/16V │ │1 │ 0.1u/50V ┬ └┬┘ │ -RESET├──────●─┤├───●────●──── 0V(GND) │ │ │ │ │10 │ │ GND├─────────────● ステッピングモータ │ │ D1┌─┬┐│ 200ステップ/回転 │ │ ┌┤>│├│──┐ ┌────┐ │ │ 2SK2782 │└─┴┘│ │ │ │ │ │ D┌───●────│────┤A相 │ │ │12 G┌┴┐S │ │ │ │ │ PB0├───┤ ├───────● │ │ │ │ │ └─┘ D2┌─┬┐│ │ │A_COMMON├──┐ │ │ ┌┤>│├│──● │ │ │ │ │ 2SK2782 │└─┴┘│ │ │ │ │ │ │ D┌───●────│────┤-A相 │ │ │ │13 G┌┴┐S │ │ │ │ │ │ PB1├───┤ ├───────● │ │ │ │+5V/6A │ │ └─┘ D3┌─┬┐│ │ │ │ ●── │ │ ┌┤>│├│──● │ │ │ │ │ 2SK2782 │└─┴┘│ │ │ │ │ │ │ D┌───●────│────┤B相 │ │ │ │14 G┌┴┐S │ │ │ │ │ │ PB2├───┤ ├───────● │ │ │ │ │ │ └─┘ D4┌─┬┐│ │ │B_COMMON├──● │ │ ┌┤>│├│──● │ │ │ │ │ 2SK2782 │└─┴┘│ │ │ │ │ │ │ D┌───●────│────┤-B相 │ │ │ │15 G┌┴┐S │ │ │ │ │ │ PB3├───┤ ├───────● │ └────┘ │ │ │ └─┘ │ └─────────┘ │ │ │ └────┘ ┴ GND D1-D4は200V/1A以上の整流用ダイオードを使用します。 C2(0.1u/50V)は、VCCとGNDの近くに接続します。
LessonAのTopへ
サイトのTopへ
法律条項 この資料により生じたいかなる障害や損害に対し、著者は全てを免責されるものとします。 この資料は、著作権法の下で保護され、入手先、著者、日付、法律条項を含んだ場合にのみ複製が可能です。
inserted by FC2 system