こちら花小金井3丁目  Last update:2002/02/28
[TopPage] [FMTOWNS] [Hardware] [Freesoft] [怪飲料] [CHAT兼掲示板] [LINK・etc] [About]

■ 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データレジスタを読む


もどる