AVRでアセンブラ
AVR用GCCのインラインアセンブラを使っても良いですが, ここではAtmelからダウンロードしてきたアセンブラを使います.
AVRアセンブラ
文法は標準的なアセンブラです. アセンブリ言語でプログラミングしている人ならすぐに書き始められるでしょう.
マイコンの用途を考えるとタイミングにシビアな場合も多いので, やっぱりアセンブラでの開発は避けられないと思います. 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番地にジャンプするので, 割り込みを使わない場合は頭からプログラムを書いても大丈夫かもしれません.
リセット以外の割り込みアドレスはディバイス毎に違うようです.
便利な命令
SBI,CBI
指定したIOレジスタの任意のビットをセットしたりリセットしたりできます.
sbi P,n ; Pのnビット目をセット(1にする)
cbi P,n ; Pのnビット目をリセット(0にする)
汎用レジスタに対してはSBR,CBRで複数ビットを操作できますが, 基本的にはANDIやORIで出来るので,あまり需要は無いかも.
SBRS,SBRC
指定したレジスタの任意のビットの状態によって,次の1命令をスキップします.
意外と一命令だけを条件によって実行させたり,させなかったりしたい場合は多いと思います. わざわざ比較して分岐しなくて良いし,新たにラベルを作らなくて良いので重宝します.
sbrs Rd,n ; Rdレジスタのnビット目が1ならば1命令スキップ
sbrc Rd,n ; Rdレジスタのnビット目が0ならば1命令スキップ
IOレジスタに対して同じことが出来る,SBIS,SBICもあります.
SWAP
任意ビットのシフトやローテーションが無いのは不便ですが, 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倍するのを忘れないようにしましょう. (私は忘れて何で変なデータが読み込まれるのか少し悩みました…)
おわりに
このアセンブラってローカルラベルは使えないのかな…? まだ良く分かってません.
この文書の履歴
- 2005-10-28 公開