上野家のホームページ
ナーマル,マリン,ココ
[
新規
|
一覧
|
検索
|
最新
|
ヘルプ
]
開発/AVR/FlashROM上の定数
をテンプレートにして作成
資料室
開発/AVR/FlashROM上の定数 をテンプレートにして作成
[
差分
|
バックアップ
|
リロード
]
[ ]
開始行:
#contents
*ROM上の定数・変数
AVRはハーバードアーキテクチャーで,プログラム用メモリROM...
-プログラムメモリ:まあまあサイズがある(512~256kB)
-レジスタおよび内蔵SRAMメモリ:サイズが小さい(32~数kB)
WinAVR(avr-gcc)では,特に指定しないと定数はSRAM上に作成...
**ヘッダーファイル
プログラムメモリを使用する場合には,以下のヘッダをインク...
#include <avr/pgmspace.h>
宣言の仕方~
__attribute__ ((progmem))
を加えるか,<avr/pgmspace.h>内で定義されているマクロ,"PR...
const 型名 定数名 PROGMEM = 定数式;
整数や文字,文字列定数については<avr/pgmspace.h>で定義さ...
**小さな整数定数は#defineマクロまたは直接記述で
定数を実現する簡単な方法として,直接数値をコードに書いて...
8bitや16bitの小さなサイズの定数を使用したい場合は,この方...
#define CONST_A (1234)
uint16_t X;
:
X = X - CONST_A;
この定数は,プログラムメモリ内に置かれて命令の一部として...
配列・文字列・構造体についても同じようにはできるが,多少...
***単一の値(配列でない定数)をROM上に置く宣言:
-8 bitデータ型: prog_uint8 , prog_int8 , prog_char~
-16bitデータ型: prog_uint16 , prog_int16~
-32bitデータ型: prog_uint32 , prog_int32~
-64bitデータ型: prog_uint64 , prog_int64~
などなど,すべての整数型の頭に"prog_"がついた型が用意され...
***ROMに各種サイズの定数を作る
prog_char c_flash = 1;
prog_uint16_t w_flash = 1234;
c_flashの名前で8bitの値1が,w_flashの名前で16bitの値1234...
***定数の読み出し
ROMから読ませるために,関数を介して参照する。
char res1 = pgm_read_byte(&c_flash);
uint16_t res2 = pgm_read_word(&w_flash);
c_flashのアドレス値(&c_flash)を使って,値をROMから読み出...
pgm_read_byte(address)
pgm_read_word(address)
pgm_read_dword(address)
**配列
***プログラムメモリの中に配列を作る
const prog_char *TEN = {0,1,2,3,4,5,6,7,8,9};
***配列の要素を読む
char res = pgm_read_byte(&TEN[5]); // TEN[X]の読み出し
char res = pgm_read_byte(TEN+X); // TENからXバイト...
***文字列の配列
次のようにする。
#include <avr/pgmspace.h>
// 文字列をROMに置く
const char foo[] PROGMEM = "Foo";
const char bar[] PROGMEM = "Bar";
// ROM上のアドレスポインタを要素とする配列を作る
PGM_P array[2] PROGMEM = {
foo,
bar
};
**文字列定数
***文字列定数宣言
const prog_char msg[] = "The first line of my LCD displa...
***1文字だけを取り出す
char res = pgm_read_byte(&msg[position]);
char res = pgm_read_byte(msg+position);
***strcpy_Pで全体をRAM上文字列変数にコピーして使用
char s[48];
strcpy_P(s,msg); // プログラムメモリ上文字列を,RAM上...
上記例のように,WinAVRのライブラリには,文字列を扱う標準...
これらは関数名末尾に "_P" がついている。~
void * memcpy_P (void *, PGM_VOID_P, size_t)
int strcasecmp_P (const char *, PGM_P)
char * strcat_P (char *, PGM_P)
int strcmp_P (const char *, PGM_P)
char * strcpy_P (char *, PGM_P)
size_t strlcat_P (char *, PGM_P, size_t)
size_t strlcpy_P (char *, PGM_P, size_t)
size_t strlen_P (PGM_P)
int strncasecmp_P (const char *, PGM_P, size_t)
char * strncat_P (char *, PGM_P, size_t)
int strncmp_P (const char *, PGM_P, size_t)
char * strncpy_P (char *, PGM_P, size_t)
size_t strnlen_P (PGM_P, size_t)
宣言とコピーをまとめて使いたいときは,PSTR()マクロを使っ...
char s[48];
strcpy_P(s,PSTR("hogehoge"));
LCD_print(s);
PSTRは,()内の文字列を前述の例と同様に宣言し,文字列のROM...
ROM専用文字列関数strcpy_P()によって,ROMからRAMへのコピー...
***ROM上の文字列を関数に引き渡す
前記のように,ROM上の文字列をRAM上にコピーすれば,RAM文字...
しかしこれはRAMの容量を食うので,例えばLCDに文字列を表示...
void LCD_print_P(const prog_char *pgm_s)
{
char c;
c=pgm_read_byte(pgm_s++);
while ((c=pgm_read_byte(pgm_s++)) != 0)
LCD_putc(c); //LCDに一文字を送る関数
}
//main routine側
LCD_print_P(PSTR("hogehoge"));
PSTR()をつけるのも面倒なので,さらにマクロを咬ませるとわ...
// 関数ライブラリ側
#define lcd_printp LCD(s) _print_P(PSTR(s))
// main側
LCD_print_P(PSTR("hogehoge"));
**RAM上の文字列定数
LCD_print("The first line of my LCD display");
//LCD_print()は,RAM上文字列を表示する関数
この方法だと,文字列定数をRAM上に置く(変更できない初期値...
+RAM上に,文字列定数を確保する(あらかじめ、プログラムに...
+LCD_printなどの関数は,RAM上の文字列を参照する ~
この領域は開放することが出来ないので,文字列定数を使った...
**構造体定数とその利用
構造体に対応するprog_型がないのでちょっとやっかいですが,...
たとえば,
typedef struct {
int16_t X,Y,R;
uint8_t color;
} circle;
circle en PROGMEM = {-123,456,78,1};
としておいて,利用先で
X = pgm_read_word(&en.X);
のようにして各要素を読むことが出来ます。構造体全体をRAM変...
circle en_sram;
memcpy_P(&en_sram,&en,sizeof(circle));
単に↓でもいけるんだけど,RAM上にコピーを作ってメモリを圧...
#define en {-123,456,78,1}
circle en_sram=en;
**PROGMEM
基本的には,
const 型名 定数名 PROGMEM = 定数式;
で,ROM上に定数を置いてくれるようです。
終了行:
#contents
*ROM上の定数・変数
AVRはハーバードアーキテクチャーで,プログラム用メモリROM...
-プログラムメモリ:まあまあサイズがある(512~256kB)
-レジスタおよび内蔵SRAMメモリ:サイズが小さい(32~数kB)
WinAVR(avr-gcc)では,特に指定しないと定数はSRAM上に作成...
**ヘッダーファイル
プログラムメモリを使用する場合には,以下のヘッダをインク...
#include <avr/pgmspace.h>
宣言の仕方~
__attribute__ ((progmem))
を加えるか,<avr/pgmspace.h>内で定義されているマクロ,"PR...
const 型名 定数名 PROGMEM = 定数式;
整数や文字,文字列定数については<avr/pgmspace.h>で定義さ...
**小さな整数定数は#defineマクロまたは直接記述で
定数を実現する簡単な方法として,直接数値をコードに書いて...
8bitや16bitの小さなサイズの定数を使用したい場合は,この方...
#define CONST_A (1234)
uint16_t X;
:
X = X - CONST_A;
この定数は,プログラムメモリ内に置かれて命令の一部として...
配列・文字列・構造体についても同じようにはできるが,多少...
***単一の値(配列でない定数)をROM上に置く宣言:
-8 bitデータ型: prog_uint8 , prog_int8 , prog_char~
-16bitデータ型: prog_uint16 , prog_int16~
-32bitデータ型: prog_uint32 , prog_int32~
-64bitデータ型: prog_uint64 , prog_int64~
などなど,すべての整数型の頭に"prog_"がついた型が用意され...
***ROMに各種サイズの定数を作る
prog_char c_flash = 1;
prog_uint16_t w_flash = 1234;
c_flashの名前で8bitの値1が,w_flashの名前で16bitの値1234...
***定数の読み出し
ROMから読ませるために,関数を介して参照する。
char res1 = pgm_read_byte(&c_flash);
uint16_t res2 = pgm_read_word(&w_flash);
c_flashのアドレス値(&c_flash)を使って,値をROMから読み出...
pgm_read_byte(address)
pgm_read_word(address)
pgm_read_dword(address)
**配列
***プログラムメモリの中に配列を作る
const prog_char *TEN = {0,1,2,3,4,5,6,7,8,9};
***配列の要素を読む
char res = pgm_read_byte(&TEN[5]); // TEN[X]の読み出し
char res = pgm_read_byte(TEN+X); // TENからXバイト...
***文字列の配列
次のようにする。
#include <avr/pgmspace.h>
// 文字列をROMに置く
const char foo[] PROGMEM = "Foo";
const char bar[] PROGMEM = "Bar";
// ROM上のアドレスポインタを要素とする配列を作る
PGM_P array[2] PROGMEM = {
foo,
bar
};
**文字列定数
***文字列定数宣言
const prog_char msg[] = "The first line of my LCD displa...
***1文字だけを取り出す
char res = pgm_read_byte(&msg[position]);
char res = pgm_read_byte(msg+position);
***strcpy_Pで全体をRAM上文字列変数にコピーして使用
char s[48];
strcpy_P(s,msg); // プログラムメモリ上文字列を,RAM上...
上記例のように,WinAVRのライブラリには,文字列を扱う標準...
これらは関数名末尾に "_P" がついている。~
void * memcpy_P (void *, PGM_VOID_P, size_t)
int strcasecmp_P (const char *, PGM_P)
char * strcat_P (char *, PGM_P)
int strcmp_P (const char *, PGM_P)
char * strcpy_P (char *, PGM_P)
size_t strlcat_P (char *, PGM_P, size_t)
size_t strlcpy_P (char *, PGM_P, size_t)
size_t strlen_P (PGM_P)
int strncasecmp_P (const char *, PGM_P, size_t)
char * strncat_P (char *, PGM_P, size_t)
int strncmp_P (const char *, PGM_P, size_t)
char * strncpy_P (char *, PGM_P, size_t)
size_t strnlen_P (PGM_P, size_t)
宣言とコピーをまとめて使いたいときは,PSTR()マクロを使っ...
char s[48];
strcpy_P(s,PSTR("hogehoge"));
LCD_print(s);
PSTRは,()内の文字列を前述の例と同様に宣言し,文字列のROM...
ROM専用文字列関数strcpy_P()によって,ROMからRAMへのコピー...
***ROM上の文字列を関数に引き渡す
前記のように,ROM上の文字列をRAM上にコピーすれば,RAM文字...
しかしこれはRAMの容量を食うので,例えばLCDに文字列を表示...
void LCD_print_P(const prog_char *pgm_s)
{
char c;
c=pgm_read_byte(pgm_s++);
while ((c=pgm_read_byte(pgm_s++)) != 0)
LCD_putc(c); //LCDに一文字を送る関数
}
//main routine側
LCD_print_P(PSTR("hogehoge"));
PSTR()をつけるのも面倒なので,さらにマクロを咬ませるとわ...
// 関数ライブラリ側
#define lcd_printp LCD(s) _print_P(PSTR(s))
// main側
LCD_print_P(PSTR("hogehoge"));
**RAM上の文字列定数
LCD_print("The first line of my LCD display");
//LCD_print()は,RAM上文字列を表示する関数
この方法だと,文字列定数をRAM上に置く(変更できない初期値...
+RAM上に,文字列定数を確保する(あらかじめ、プログラムに...
+LCD_printなどの関数は,RAM上の文字列を参照する ~
この領域は開放することが出来ないので,文字列定数を使った...
**構造体定数とその利用
構造体に対応するprog_型がないのでちょっとやっかいですが,...
たとえば,
typedef struct {
int16_t X,Y,R;
uint8_t color;
} circle;
circle en PROGMEM = {-123,456,78,1};
としておいて,利用先で
X = pgm_read_word(&en.X);
のようにして各要素を読むことが出来ます。構造体全体をRAM変...
circle en_sram;
memcpy_P(&en_sram,&en,sizeof(circle));
単に↓でもいけるんだけど,RAM上にコピーを作ってメモリを圧...
#define en {-123,456,78,1}
circle en_sram=en;
**PROGMEM
基本的には,
const 型名 定数名 PROGMEM = 定数式;
で,ROM上に定数を置いてくれるようです。
ページ名:
Counter: 0, today: 0, yesterday: 0
Copyright©2008 Yuji Ueno All Rights Reserved.
ログイン
ユーザ名:
パスワード:
IDとパスワードを記憶
パスワード紛失
メインメニュー
ホーム
でぶlog
資料室
最新ページ一覧
全ページ一覧
ヘルプ
フォーラム
お問い合わせ