Работа с массивами

forfrends
Offline
Зарегистрирован: 24.02.2015
Всем привет! Делаю небольшой проект. Устройство не большое, в основном нужно будет обрабатывать массивы с данными. Массивов будет много. Для экономии ОЗУ решил сделать массивы типа PROGMEM (в массивы ничего записываться не будет, только чтение). Столкнулся с тем, что если сделать массив типа PROGMEM то чтение с него не происходит (точнее на выходе получаю "левые" значения). Вот пример кода:
byte A = 0;
byte B = 0;
byte i = 0;

const int bitmap[] PROGMEM = {
    0x99,0x42,0x24,0x99,0x99,0x24,0x42,0x99  
};

void setup() {
    Serial.begin(115200);
}

void loop() {
    A = 1 << i;
    B = bitmap[i];
   
    Serial.print(A);
    Serial.print(" ");
    Serial.println(B);
    
    delay(1000);
    i++;
    if (i>7) i = 0;
}

На выходе получается следующее:

1 0
2 6
4 0
8 1
16 0
32 6
64 6
128 6

Если же массив убрать из PROGMEM, то все считывается правильно:

byte A = 0;
byte B = 0;
byte i = 0;

int bitmap[]= {
    0x99,0x42,0x24,0x99,0x99,0x24,0x42,0x99  
};

void setup() {
    Serial.begin(115200);
}

void loop() {
    A = 1 << i;
    B = bitmap[i];
    
    Serial.print(A);
    Serial.print(" ");
    Serial.println(B);
    
    delay(1000);
    i++;
    if (i>7) i = 0;
}

На выходе:

1 153
2 66
4 36
8 153
16 153
32 36
64 66
128 153

Подскажите, что я делаю не так? Мне нужно Чтобы массивы читались из флеша, а не загружались в ОЗУ

forfrends
Offline
Зарегистрирован: 24.02.2015

Прошу прощения. Первый абзац почему-то оказался под спойлером....

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

массивы из PROGMEM надо читать "ручками". 

forfrends
Offline
Зарегистрирован: 24.02.2015

Можно подробнее? 

Komandir
Offline
Зарегистрирован: 18.08.2018

pgm_read_ надо загуглить

b707
Offline
Зарегистрирован: 26.05.2017

непосредственный доступ к переменным в ПРОГМЕМ, типа

a = b[3];

- не работает. необходимо использовать специальные операторы типа pgm_read_byte() pgm_reaf_word() и так далее

Подробнее - в референсе

forfrends
Offline
Зарегистрирован: 24.02.2015

Спасибо за помощь! Исправил, теперь работает:

B = pgm_read_byte(&bitmap[i]);

Komandir
Offline
Зарегистрирован: 18.08.2018

forfrends вы там еще с типами переменных разберитесь ! А то пишете в память int, а читаете byte ...

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

Komandir пишет:

forfrends вы там еще с типами переменных разберитесь ! А то пишете в память int, а читаете byte ...

ему - абсолютно пох. главное - прочитать чонить. 

b707
Offline
Зарегистрирован: 26.05.2017

DetSimen пишет:

ему - абсолютно пох. главное - прочитать чонить. 

ага, он уже отключился, побежал использовать...

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

DetSimen пишет:

Komandir пишет:

forfrends вы там еще с типами переменных разберитесь ! А то пишете в память int, а читаете byte ...

ему - абсолютно пох. главное - прочитать чонить. 

потому как есть разделение, кто читатели, кто писатели )))

FoxJone
Offline
Зарегистрирован: 19.04.2019

b707 пишет:

непосредственный доступ к переменным в ПРОГМЕМ, типа

a = b[3];

- не работает. необходимо использовать специальные операторы типа pgm_read_byte() pgm_reaf_word() и так далее

Подробнее - в референсе

Не помню, говорил я или нет, что я ламер, но вот эта информация для меня вообще новая. В последнем проекте CRC-таблицу держал в прогмеме и замечательно она оттуда читалась. Можете подсказать тупенькому, почему она читалась?

const unsigned short PROGMEM CRC_Table[256] = { тута длиннющая таблица на СРС16 };

unsigned short CRC_Sum(unsigned short wIniValue, uint8_t lpData)
{
  wIniValue = CRC_Table[((wIniValue >> 8) ^ lpData++) & 0xFF] ^ (wIniValue << 8);
  return wIniValue;
};

Как я понимаю, тут как раз классический a = b[3]*с;

b707
Offline
Зарегистрирован: 26.05.2017

FoxJone пишет:

Не помню, говорил я или нет, что я ламер, но вот эта информация для меня вообще новая. В последнем проекте CRC-таблицу держал в прогмеме и замечательно она оттуда читалась. Можете подсказать тупенькому, почему она читалась?

а контроллер какой был?

FoxJone
Offline
Зарегистрирован: 19.04.2019

b707 пишет:

FoxJone пишет:

Не помню, говорил я или нет, что я ламер, но вот эта информация для меня вообще новая. В последнем проекте CRC-таблицу держал в прогмеме и замечательно она оттуда читалась. Можете подсказать тупенькому, почему она читалась?

а контроллер какой был?

Ну так STM32 жеж

Я почему интересуюсь то? Алгоритм мною успешно сперт из этих ваших интернетов (правда пришлось доработать под свой СРС) и я откровенно не все в нем понимаю. Работает и ладно. Но хотелось бы иметь понимание даже спертого кода, а не только мною написанного :)

Так вот и учусь поманеньку...

forfrends
Offline
Зарегистрирован: 24.02.2015

DetSimen, b707Я не пишу, потому что не вижу смысла кому-то что-то доказывать. 

b707
Offline
Зарегистрирован: 26.05.2017

forfrends пишет:

DetSimen, b707Я не пишу, потому что не вижу смысла кому-то что-то доказывать. 

а разве тут надо что-то доказывать? - Вы описали массив как int, читаете как байт. Это надо доказывать или пока согласны?

далее вам указали на эту очевидную ошибку, умный человек поблагодарил бы и исправил... а вы что-то доказывать рветесь... Что?

FoxJone
Offline
Зарегистрирован: 19.04.2019

b707 пишет:
а вы что-то доказывать рветесь... Что?

Ну как что? Что вы жалкие, ничтожные личности. Некоторые люди кюшать не могут, пока в интернете кому то это не докажут :)

b707
Offline
Зарегистрирован: 26.05.2017

FoxJone пишет:

Ну так STM32 жеж

не, я пока не настолько продвинут, чтобы уверенно обсуждать. У меня в коде PROGMEM активно используется. но я работаю с ним "по прописи", через pgm_read_xxx. Возможно, что в СТМ32 разницы между const PROGMEM и просто const нет, но повторюсь что пока не готов что-то говорить. Может кто другой подскажет.

b707
Offline
Зарегистрирован: 26.05.2017

попробовал на примере кода ТС из первого поста

//#define USE_PGM

#ifndef USE_PGM
const byte bitmap[]= {
    0x99,0x42,0x24,0x99,0x99,0x24,0x42,0x99  };
#else
const byte bitmap[] PROGMEM= {
    0x99,0x42,0x24,0x99,0x99,0x24,0x42,0x99  };
#endif

void setup() {
    Serial.begin(115200);
}

void loop() {
    A = 1 << i;
#ifndef USE_PGM
    B = bitmap[i];
#else
    B = pgm_read_byte(&bitmap[i]);
#endif
   
    Serial.print(A);
    Serial.print(" ");
    Serial.println(B);
    
    delay(1000);
    i++;
    if (i>7) i = 0;
}

для Ардуино Нано код с ПРОГМЕМ занимает 205 байт ОЗУ, без - 213 (флеш одинаков)

для СТМ32 - что с прогмем, что без - разницы нет.

Зато если в коде для СТМ32 убрать const в описании массива - оперативка становится меньше на 8 байт.

 

Вывод - для СТМ32 квалификатор PROGMEM не нужен, достаточно описать данные как const

forfrends
Offline
Зарегистрирован: 24.02.2015

b707, я посмотрю как вы сможете исправить код в первом сообщении...

Не понимаю. почему вы завелись? Или вам мало той благодарности, которую я выразил в сообщении №6? Ок, разные типы данных, ок, исправил это у себя на компьютере, так зачем обсирать в 5-м и 6-м сообщении? для этого есть повод? Только потому что я не ответил и тем самым зацепил ваше самолюбие? Зачем высмеивать кого-то и искать что-то за что можно зацепиться и полить человека грязью?

b707, относительно PROGMEM - это не влияет на использование флеша, только влияет на использование ОЗУ.

b707
Offline
Зарегистрирован: 26.05.2017

forfrends пишет:

b707, я посмотрю как вы сможете исправить код в первом сообщении...

не понял, вы разве его еще не исправили? спрашивайте тогда

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Мужики, "жесть" - это уже  отожжённая сталь, так что отжигать её здесь совершенно не обязательно.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

FoxJone пишет:

Ну так STM32 жеж

Так если если stm32, то при чем здесь PROGMEM?

В STM и ОЗУ и flash находятся в едином адресном пространстве. В отличие от AVR.

И в дефайнах PROGMEM для STM заменяется то ли на пробел, то ли вообще опускается.

 

Кстати, опишите для STM переменную и константу, а потом выведите адреса той и другой и сравните с таблицей распределения памяти. Узнаете много интересного.