質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

Q&A

解決済

2回答

521閲覧

複合リテラルをPROGMEMの時にも使いたい

UMA821

総合スコア27

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

0グッド

0クリップ

投稿2020/07/24 05:19

前提・実現したいこと

Arduinoのプログラムで、それぞれの配列の長さが違うので複合リテラルを使って初期化したポインタを変数としてPROGMEM機能を使った際に思った通りになりませんでした。
どうすれば上手くいくのか、できないのであれば理由を教えていただけると幸いです。
下記のプログラムは例ですが、同じ問題になっています。

ソースコード

Arduino

1const int *const Length[3] PROGMEM = { 2 (int[]){58, 63, 65, 58, 0}, 3 (int[]){62, 67, 69, 62, 0}, 4 (int[]){65, 70, 72, 65, 0} 5}; 6 7void setup() { 8 Serial.begin(9600); 9} 10 11void loop() { 12 Serial.println(pgm_read_byte(&(Length[0][2]))); 13 //「65」と出力してほしいが、「207」と出力される 14 Serial.println(pgm_read_byte(&(Length[1][2]))); 15 //「69」と出力してほしいが、「207」と出力される 16 Serial.println(pgm_read_byte(&(Length[2][2]))); 17 //「72」と出力してほしいが、「207」と出力される 18 while(1){} 19}

試したこと

######PROGREMだけ

Arduino

1const int Length[3][4] PROGMEM = { 2 {58, 63, 65, 58, 0}, 3 {62, 67, 69, 62, 0}, 4 {65, 70, 72, 65, 0} 5}; 6 7void setup() { 8 Serial.begin(9600); 9} 10 11void loop() { 12 Serial.println(pgm_read_byte(&(Length[1][2]))); 13 //「69」と出力される 14 while(1){} 15}

######複合リテラルだけ

Arduino

1const int *Length[3] = { 2 (int[]){58, 63, 65, 58, 0}, 3 (int[]){62, 67, 69, 62, 0}, 4 (int[]){65, 70, 72, 65, 0} 5}; 6 7void setup() { 8 Serial.begin(9600); 9} 10 11void loop() { 12 Serial.println(Length[1][2]); 13 //「69」と出力される 14 while(1){} 15}

補足情報

Arduino 1.8.13
Arduino Uno を使っています。
よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

回答未満ではありますが、

Arduino

1//Arduino IDE 1.8.12ですけどそう変わらないでしょう。多分。 2const int array1[]PROGMEM ={10,11,12,13,14}; 3const int array2[]PROGMEM ={20,21,22,23,24}; 4const int *const Length[] PROGMEM={ 5 array1, 6 array2 7}; 8 9char buf[256]; 10void setup() { 11 Serial.begin(9600); 12 Serial.println("\nStart"); 13 14 sprintf(buf,"array1:%p",&array1); 15 Serial.println(buf); 16 17 sprintf(buf,"&Length[0][0]:%p",&Length[0][0]); 18 Serial.println(buf); 19 20 sprintf(buf,"&Length[0]:%p",&Length[0]); 21 Serial.println(buf); 22 23 Serial.println(Length[0][0]); 24 Serial.println(Length[0][1]); 25 Serial.println(Length[1][0]); 26} 27 28void loop() { 29 30}

としてみたところ、

Text

1 2Start 3array1:0x76 4&Length[0][0]:0x76 5&Length[0]:0x72 610 711 820

という結果が得られました。datasheetを見ると328PのSRAMは0x100からなので、領域はFLASHにとられているように思えるし、
const int array1[2048]PROGMEM ={10,11,12,13,14};
とか
const int *const Length[2048] PROGMEM={
とかやるとSRAMがパンクせずにプログラム領域の消費が増えるのもFLASH領域と思えます。
「複合リテラルを使いたい」というのがメインならそれには合致しませんが、とりあえずデータ一式をプログラム領域に置くことは出来ている模様。

しかし。
pgm_readなんちゃらマクロを使わなくてもそのまま値が読めてしまっているというのが謎です。そういうものだっけ?

今日は気力がないので明日ちょっとAtmel Studioとデバッガを引っ張りだして調べてみようか、と。

投稿2020/07/24 13:18

thkana

総合スコア7610

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

UMA821

2020/07/24 13:40

回答していただきありがとうございます。 pgm_read_byte()を使っても同じ10,11,20という値が出ました なんでなのでしょう
thkana

2020/07/24 14:12

「コンパイラが利口になった」のかも。PROGMEM属性を残して適切に処理してくれるようになったとか?
thkana

2020/07/26 08:35

久々に使ったらAtmelStudioでVisualMicroがうまく動かなかったり、デバック用にfuseを書き換えたらいろいろやっちゃって手間取ってました。 (const int PROGMEM[])など試してみましたが、リテラルをプログラム領域に配置してくれないみたいです。 定数だとできちゃうのは https://teratail.com/questions/280065#reply-399120 にて
UMA821

2020/07/26 09:17

疑問が解消しました、ありがとうございます!
guest

0

ベストアンサー

Arduinoで使われているAVRというCPUでは、フラッシュメモリ(ROM)とRAMは完全に別メモリ空間となっていて、それぞれの読み出しには専用命令が使われます

だもんで、変数定義にconstをつけたところでROM空間には配置してくれません。
そのためには、特別なキーワード、PROGREMを使う必要があります
で、このフラッシュメモリを読む命令にしても、制限があって、通常のRAMを読むようには自由にはできないという事情があります
という事情から、PROGMEM空間を指すポインタというのも使用できません

だもんで、

const int *const Length[3] PROGMEM = {

という定義の使用はできません。

投稿2020/07/24 05:40

編集2020/07/24 05:42
y_waiwai

総合スコア87719

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

UMA821

2020/07/24 06:19

なるほど、配列のサイズをはっきりさせていないといけないのですね
y_waiwai

2020/07/24 06:21

可能性あるのは、PROGREMだけ、ってのだけど、これでもダメなんでしょうか
UMA821

2020/07/24 07:35

ボタン押したつもりが反映されてなかったようです
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問