ふつうマイコンって、コードと定数はROMに、初期値なし変数はRAMに置き、初期値付き変数は、初期値をROMに置いてスタートアップでRAMにコピーしますよね。ところが、AVRって定数もRAMにコピーしてから使うんですね。ただでさえRAM容量乏しいのに、なんでそんな無駄なことするんだろうと思いましたが、それもそのはずで、AVRってPICと同じくハーバード・アーキテクチャなんですね。コードのROM(プログラムメモリ)とデータのRAM(データメモリ)が別々のバスにぶら下がってるわけで、定数といえどデータはRAMの方にないといけないわけです。
あれ? じゃあどうやって最初に値をセットしてるん?
もちろん、定数や初期値は不揮発のROMに置いとかないといけないわけで、やはりスタートアップでRAMにコピーしているようです。コンパイラの吐いたリストを解読してみるとLPMないしELPMという命令が使われています。これはプログラムメモリからレジスタへのロード命令です。許されるアドレッシングはZレジスタ間接のみ。また当然のことながら、通常のLD命令より多くクロックを要するようです。いわばノイマン・アーキテクチャ風に振舞うわけですからね。
やはりテーブルのような大量のデータをRAMに移して使うのは避けたいところ。
C言語で記述するにはどうすればいいのか? WinAVRの場合…
(1) プログラムメモリ(ROM)を使う
詳細はavr-libcの
// 定数をプログラムメモリに置くならこれをインクルード
#include
// プログラムメモリ定数の宣言
const PROGMEM unsigned char piyo[10] = {1,2,3,4,5,6,7,8,9,10};
// 読み出し
a = pgm_read_byte(&piyo[i]);
// マクロにしとく
#define piyo_get(i) pgm_read_byte(&piyo[i])(2) EEPROMを使う
詳細はavr-libcの
// 定数をEEPROMに置くならこれをインクルード
#include
// EEPROM定数の宣言
const EEMEM unsigned char piyo[10] = {1,2,3,4,5,6,7,8,9,10};
// 読み出し
a = eeprom_read_byte(&piyo[i]);
// マクロにしとく
#define piyo_get(i) eeprom_read_byte(&piyo[i])