■ AVRASMの命令セット ■
|
AVRはRISCマイコンの割に命令数が多いです。私の場合PICからの以降に若干手間がかかりました。慣れてしまえばこちらのほうが全然楽です。レジスタが結構多いので、ちょっとした処理ならSRAMを使わずとも済んでしまうのも便利です。
私が良く使う命令を(自分が忘れないように(^^;))書いておきます。
・主な転送系命令
MOV : 汎用レジスタ間転送
LDI : 汎用レジスタに即値の取得
LDS : SRAMからの取得
STS : SRAMへの設定
IN : I/Oレジスタからの入力
OUT : I/Oレジスタへの出力
PUSH : 汎用レジスタの退避
POP : 汎用レジスタからへの復帰
・主なビット操作系命令
SBI : I/Oレジスタへビットセット
CBI : I/Oレジスタへビットクリア
LSL : 論理的左シフト
LSR : 論理的左シフト
・主な算術操作系命令
ADD : 汎用レジスタの加算
ADIW : 即値のワード長加算
SUB : 汎用レジスタの減算
SUBI : 即値の減算
AND,OR,EOR : 汎用レジスタの積,和,排他的論理和
ANDI,ORI : 即値の積,和
COM : 1の補数(論理反転)
INC,DEC : インクリメント、デクリメント
TST : 汎用レジスタのゼロとマイナスの検査
・主な分岐関連命令
RJMP : ジャンプ
RCALL : サブルーチンコール
RET : サブルーチン復帰
RETI : 割り込み復帰
CPSE : レジスタ間比較(一致で次の行をスキップ)
CPI : 汎用レジスタと即値の比較
SBRC,SBRS : 汎用レジスタのビットクリア(0),ビットセット(1)でスキップ
SBIC,SBIS : I/Oレジスタのビットクリア(0),ビットセット(1)でスキップ
BRNE,BREQ : ステータスレジスタの比較結果が不一致で分岐,一致で分岐
BRCS,BRCC : キャリーフラグがセット(1),クリア(0)で分岐
・その他
NOP : 何もしない
SEI : 全割り込みを許可
CLI : 全割り込みを禁止
|
■ ポートの設定 ■
|
安価かつポピュラーなAVRとして、AT90S-2313を使ってみます。2313は、8bit I/O ポートのPORTBと、7bit I/O ポートのPORTDの、計15本のI/Oポートを備えています。
最初にI/Oポートを使用するために、各I/Oポート毎に入出力のどちらかに設定します。例としてPORTBに関して設定する場合、ポート方向レジスタ(DDRB)に各ビット毎に入力(0)、出力(1)を書き込みます。
LDI r16,0b00000111
OUT DDRB,r16
この例ではPORT-B の PB0〜2までが出力、PB3〜7までが入力になります。
出力に設定したポートに実際に出力させるには、PORTB出力レジスタ(PORTB)に書き込みます。入力に設定したポートから入力させるには、PORTB入力レジスタ(PINB)を読みます。
ポートを入力に設定した状態で、出力レジスタに1を書き込むと、内蔵プルアップ抵抗が有効になります。0の場合はハイ・インピーダンス(Z)になります。以下の例の場合、PORT-B の PB7, PB5 がプルアップされます。
LDI r16,0b10100000
OUT PORTB,r16
|
■ スタックポインタの設定 ■
|
スタックポインタを設定しないと、サブルーチンコールはもとよりPUSH,POPも使えません。
スタックポインタは、SRAM領域を後ろから使っていきます。SRAMの最終アドレスは、インクルードファイル内で定数RAMENDが$DFと設定されています。この値をSPLレジスタに書き込みます。AT90S1200の場合は若干違うようです。
.include "2313def.inc"
LDI r16,LOW(RAMEND)
OUT SPL,r16
もし、AT90S8515のような容量の大きいAVRを使う場合は、スタックポインタレジスタが上位と下位に分かれているので、別々に設定します。
.include "8515def.inc"
LDI r16,LOW(RAMEND)
OUT SPL,r16
LDI r16,HIGH(RAMEND)
OUT SPH,r16
|
■ ポートの単純入出力 ■
|
AVR-AT90S2313で、単純なポートの入出力を行います。
■ポート単位で入出力する場合
各ポートをバスと考えて、ポート単位でまとめて入出力する場合、in,out命令を使います。ポートから入力する場合と出力する場合とで、レジスタの名前が違うので注意が必要です。
out PORTB,r16
in r16 ,PINB
これで、PORT Bの状態をレジスタr16に取得、およびレジスタr16をPORT Bに出力します。実際に出力できているかどうかは、LEDを付けるかテスターをあてて確かめます。
■ピン単位で出力する場合
ポート単位で出力するよりも、ピン単位で処理したい場合があります。この場合はsbi,cbi命令を使用します。
sbi PORTB,0
cbi PORTB,0
これで、PORT Bの0ビット目のピン(PB0)をHレベル(sbi)、Lレベル(cbi)にします。
■ピン単位で入力処理する場合
ポート単位では単純にレジスタへ入力することはできますが、ピン単位で処理する場合は分岐命令になります。sbic,sbis命令を使います。
sbic PINB,0
sbis PINB,0
前者は、PORT Bの0ビット目のピンがクリア(Lレベル)なら次の命令をスキップ
後者は、PORT Bの0ビット目のピンがセット(Hレベル)なら次の命令をスキップ
となります。
|
■ タイマ割り込みを使う ■
|
AVR-2313は、8bitと16bitの2つのタイマ/カウンタがあり、割り込み間隔が設定可能です。
〜まだ準備中〜
|
■ UARTでRS232C通信する ■
|
AVR 2313 は、UART(Universal Asynchronous Receiver and Transmitter)が内蔵されており、信号レベルさえ調整すれば、面倒なタイミング取りをしなくてもシリアル通信が可能です。
プログラムの最初でボーレートレジスタを設定します。書き込む数値は、AVRのマニュアルを参照します。10MHz駆動の場合は、64で9600bpsとなります。
LDI r16,64
OUT UBRR,r16
次に、UART制御レジスタの送信許可ビット(TXEN)、受信許可ビット(RXEN)を、1にします。
LDI r16,(1<<TXEN)+(1<<RXEN)
OUT UCR,r16
あとは、送受信したいときに、UARTデータレジスタの空きを待って送受信処理を行います。
送信したいときは、UARTステータスレジスタ(USR)のデータレジスタ空きフラグ(UDRE)が1になるのを待って、UARTデータレジスタ(UDR)に書き込みます。
SENDCODE:
SBIS USR,UDRE ; UDRE=1:データレジスタ空きを待つ
RJMP SENDCODE ; UDRE=0:レジスタいっぱいならループ
OUT UDR,r16 ; UARTデータレジスタに入れる
受信するときは、UARTステータスレジスタ(USR)の受信完了フラグ(RXC)が1になるのを待って、UARTデータレジスタ(UDR)を読みます。
RCVCODE:
SBIS USR,RXC ; RXC=1:受信完了を待つ
RJMP RCVCODE ; RXC=0:受信未完了ならループ
IN r16,UDR ; UARTデータレジスタを読む
|