AVR avr/io.h インクルードファイルは一体何をしているのか??
AVRでポート出力を制御するためにC言語で書くときは、
DDRD = 0xFF; //ポートDを全部出力設定
PORTD = 0x10; //PORTD出力
のようにしているが、インクルードファイル”avr/io.h”がなければこのように書くことはできない。なぜなら、本来はDDRDやPINDというのは、単なるメモリのうちの一つにすぎないから。もしio.hがない場合は、こんな風に書かなければならない。
int *pind; //PINDへのアドレスを指すポインタ。
pind = 0x09 + 0x20; //ポインタ変数pindにPINDのアドレスを入れる。
そうしてようやく、値を目的のアドレスに入れることができる。
*pind = 0xFF;
AVRの”avr/io.h”が何を宣言しているか。
WinAVRのドキュメントを紐解いてみた。
<avr/io.h>: AVR device-specific IO definitions
を見てみると、io.hのファイルの中身には宣言の実体はなく、AVRstudioで選んだデバイスをコンパイラが受け取り、それに対応したヘッダファイルをインクルードするようにマクロが組んであるという。
WinAVR\avr\includeのフォルダに、それぞれのデバイスに対応したヘッダファイルが置いてある。io.hの中身を見ると、確かにIOレジスタに関する名前が一切出てこず、elif definedの行がズラズラ並んでいる。おそらくここからATmega328Pなら"avr/iom328P.h"が読み込まれる。
"avr/iom328P.h"の中身はどうなっているか。
下記のような塊が何個も並んでいる。この塊の一行目のところが大事で、0x09というアドレスが_SFR_IO8というマクロに引数として渡されているのがわかる。
#define PIND _SFR_IO8(0x09)
#define PIND0 0
#define PIND1 1
#define PIND2 2
#define PIND3 3
#define PIND4 4
#define PIND5 5
#define PIND6 6
#define PIND7 7
じゃあこのマクロはどこで宣言されているのか?というと、
WinAVRドキュメントの<avr/io.h>のページの本文に、
Note that this file always includes the following files:
See <avr/sfr_defs.h>: Special function registers for more details about that header file.
というのがあって、 <avr/sfr_defs.h>の説明にリンクが貼ってある。ここの説明を見れば、よく使う_BVマクロやbit_is_setマクロについての説明が全部載っている。
WinAVR\avr\includeのフォルダにsfr_defs.hが入っていて、マクロの実体が書き込まれている。そしてとうとう_SFR_IO_ADDR(io_addr)というマクロの宣言を見つけることができる。
#define _SFR_IO8(io_addr)((io_addr)+__SFR_OFFSET)
というのがそれ。そしてそのなかにこういうマクロが中に入っていて、
#define __SFR_OFFSET 0x20
とかいうのがあるから、レジスタのアドレスについて。
にある、IOレジスタにデータスペースとしてアクセスするための手法を使っているのだと思う。
具体的にアドレスをいれて考えてみる。
たとえばDDRBにアクセスしたかったら、mega328Pの仕様書のresister summuryをみる。すると、DDRBが0x04番地になっているから、これに普通のデータスペース、つまり変数のようにアクセスしたければ、
0x20+0x04 = DDRBのアドレス
ということになる。
実際にアクセスできるかどうかはAVRstudioを使えば試すことができるので、AVRはその点非常に便利。
実際にやってみたソースファイルも用意していますので、試してみてください。
IOのヘッダファイルを一切使わずにIOポートを叩く荒業。
このサイトはアセンブラプログラミングをどんどん書いています。
アセンブラでプログラムを書いてスキルアップ
« WinAVRでio.hファイルをインクルードせずにIOポートを制御する荒業。 | トップページ | AVRアセンブラ関数でIOを叩く方法。 »
「AVRマイコン」カテゴリの記事
- Arduino CuHead Wifi Shield for Arduino V2.0 (LinkSprite)の使い方(2015.04.28)
- AVR デバッグのときだけdelay関数を無効化するフレーズ(2014.05.01)
- AVRでプレステのコントローラを使えるようにする。SPIの使い方(2013.12.23)
- ATmega328でADコンバータを使う。+距離測定センサを動かす。(2013.10.09)
- AVRからI2CタイプのEEPROMを読む。(2013.08.20)
« WinAVRでio.hファイルをインクルードせずにIOポートを制御する荒業。 | トップページ | AVRアセンブラ関数でIOを叩く方法。 »
コメント