AVR用GCCのインラインアセンブラを使っても良いですが, ここではAtmelからダウンロードしてきたアセンブラを使います.
文法は標準的なアセンブラです. アセンブリ言語でプログラミングしている人ならすぐに書き始められるでしょう.
マイコンの用途を考えるとタイミングにシビアな場合も多いので, やっぱりアセンブラでの開発は避けられないと思います. AVRでは殆どの命令が1クロック(または2クロック)で実行されるので, 処理のクロック数を数えるのが簡単です.
プログラムの先頭は割り込みベクタです. 割り込みが起こると割り込みに応じたアドレスにジャンプしてきます.
AT90S2313の場合
()ADDR Name 説明 0 RESET リセット時 1 INT0 INT0 2 INT1 INT1 3 TIMER1 CAPT1 Timer1 キャプチャ発生 4 TIMER1 COMP1 Timer1 コンペア一致 5 TIMER1 OVFO Timer1 がオーバーフローした時 6 TIMER0 OVFO Timer0 がオーバーフローした時 7 UART,RX URAT受信完了 8 UART,UDRE URAT送信バッファ空き 9 UART,TX URAT送信完了 10 ANA_COMP アナログコンパレータ遷移
()使わない割り込みはretiで埋めて, 使う割り込みはrjmpで処理したいルーチンに飛ばすのが普通みたいです.
リセット時に0番地にジャンプするので, 割り込みを使わない場合は頭からプログラムを書いても大丈夫かもしれません.
リセット以外の割り込みアドレスはディバイス毎に違うようです.
指定したIOレジスタの任意のビットをセットしたりリセットしたりできます.
sbi P,n ; Pのnビット目をセット(1にする) cbi P,n ; Pのnビット目をリセット(0にする)
汎用レジスタに対してはSBR,CBRで複数ビットを操作できますが, 基本的にはANDIやORIで出来るので,あまり需要は無いかも.
指定したレジスタの任意のビットの状態によって,次の1命令をスキップします.
意外と一命令だけを条件によって実行させたり,させなかったりしたい場合は多いと思います. わざわざ比較して分岐しなくて良いし,新たにラベルを作らなくて良いので重宝します.
sbrs Rd,n ; Rdレジスタのnビット目が1ならば1命令スキップ sbrc Rd,n ; Rdレジスタのnビット目が0ならば1命令スキップ
IOレジスタに対して同じことが出来る,SBIS,SBICもあります.
任意ビットのシフトやローテーションが無いのは不便ですが, SWAPで上下ニブルが交換できるので,大分マシになります.
SRAMは貴重な資源ですので,静的なデータは出来る限りプログラム領域に置きましょう. 「lpm」でプログラム領域1バイト読み込むことが出来ます. 2313系ではオペランドをとらないLPM命令しか使えないようなので, データはr0レジスタに読み込まれます.
; read data (6 clocks) ldi ZL,low(DATA*2) ldi ZH,high(DATA*2) add ZL,p ; pバイト目に移動 lpm ; r0=(Z) out PORTB,r0 ; PORTBに出力 ret ;*************************************************************************** ;* データ DATA: .DB 1,2,3,4,5,6,7,8,9,10
ラベルのアドレスはワード(2Byte)単位なので,2倍するのを忘れないようにしましょう. (私は忘れて何で変なデータが読み込まれるのか少し悩みました…)
このアセンブラってローカルラベルは使えないのかな…? まだ良く分かってません.