PROGMEM поврежден массив
Я пытаюсь сохранить большое количество значений в нескольких массивах с помощью PROGMEM, но обнаруживаю, что некоторые значения считываются обратно поврежденными. Я сохраняю только 1 и 0, но когда я читаю эти значения, я иногда получаю значения больше 1. Для этого я использую MEGA 2560.
// Каждый массив содержит 32000 значений
const byte VALUES_1[] PROGMEM = { 1, 0, 1, .... 0 };
const byte VALUES_2[] PROGMEM = { 1, 1, 0, .... 0 };
const byte VALUES_3[] PROGMEM = { 1, 0, 1, .... 1 };
const byte VALUES_4[] PROGMEM = { 1, 0, 1, .... 1 };
const byte VALUES_5[] PROGMEM = { 1, 0, 1, .... 1 };
const long ARR_LEN = 32000;
long index = 0;
void setup() {
Serial.begin(57600);
while (!Serial) {}
}
byte readNextValue() {
if (index >= 160000L) {
return -1;
}
Serial.print(index);
Serial.print(" ");
long arr = index / ARR_LEN;
long i = index % ARR_LEN;
index++;
byte j = -1;
switch(arr) {
case 0:
j = pgm_read_byte_far(VALUES_1 + i);
Serial.println(j);
return j;
case 1:
j = pgm_read_byte_far(VALUES_2 + i);
Serial.println(j);
return j;
case 2:
j = pgm_read_byte_far(VALUES_3 + i);
Serial.println(j);
return j;
case 3:
j = pgm_read_byte_far(VALUES_4 + i);
Serial.println(j);
return j;
case 4:
j = pgm_read_byte_far(VALUES_5 + i);
Serial.println(j);
return j;
}
Serial.println("Unable to return next value");
return -1;
}
void loop() {
// поместите сюда свой основной код для многократного запуска:
readNextValue();
}
Я заметил, что когда я использую pgm_read_byte_far
для case 0
, я сразу получаю мусорные значения, но использование pgm_read_byte_near
будет привести к тому, что эти мусорные значения появятся когда-нибудь позже. Любое понимание этой проблемы приветствуется.
@KaYBlitZ, 👍1
Обсуждение1 ответ
Просто дополнительная информация на случай, если у кого-то возникнет такая же проблема. Одним из решений является ответ Ника в его комментарии, который сначала захватывает дальние адреса в настройке, сохраняет их в массиве и использует. я
// Каждый массив содержит 32000 значений
const byte VALUES_1[] PROGMEM = { 1, 0, 1, .... 0 };
const byte VALUES_2[] PROGMEM = { 1, 1, 0, .... 0 };
const byte VALUES_3[] PROGMEM = { 1, 0, 1, .... 1 };
const byte VALUES_4[] PROGMEM = { 1, 0, 1, .... 1 };
const byte VALUES_5[] PROGMEM = { 1, 0, 1, .... 1 };
long VALUES[] = { 0, 0, 0, 0, 0 };
const long ARR_LEN = 32000;
long index = 0;
void setup() {
Serial.begin(57600);
while (!Serial) {}
VALUES[0] = (long) pgm_get_far_address(VALUES_1);
VALUES[1] = (long) pgm_get_far_address(VALUES_2);
VALUES[2] = (long) pgm_get_far_address(VALUES_3);
VALUES[3] = (long) pgm_get_far_address(VALUES_4);
VALUES[4] = (long) pgm_get_far_address(VALUES_5);
}
byte readNextValue() {
if (index >= 160000L) {
return -1;
}
Serial.print(index);
Serial.print(" ");
long arr = index / ARR_LEN;
long i = index % ARR_LEN;
index++;
byte j = pgm_read_byte_far(VALUES[arr] + i);
Serial.println(j);
return j;
}
void loop() {
// поместите сюда свой основной код для многократного запуска:
readNextValue();
}
Это работает отлично, все байты верны. Лучшим ответом было бы преобразовать байты в биты, как говорили все остальные, чтобы сэкономить место в памяти.
- Сбой Arduino во время последовательной печати без очевидной причины
- Будет ли адаптер питания 12В постоянного тока, 1А подавать слишком большую мощность и повредит Arduino Mega 2560?
- Как запрограммировать Robotdyn Mega 2560 PRO MINI?
- Отключите автоматический сброс Mega 2560 на последовательном мониторе, открытом с помощью резистора 60 Ом.
- Программирование пользовательских Arduino Mega с Arduino Uno
- Регистр ATmega 32A и 2560 R3 для сопоставления контактов
- Ardunio Mega/ATmega2560: использование порта F или K как для аналоговых входов, так и для цифровых выходов.
- Как подсчитать количество нарастающих фронтов на DS3231 rtc?
Не используйте ни близко, ни далеко? Позвольте компилятору разобраться, что есть что?, @Majenko
Общий размер вашего массива составляет 5 * 32000 = 160 000 байт. Почему бы не сохранить его в виде битов, которые займут всего 20 000 байт? Тогда бы отпали все вопросы дальней адресации. Вы можете использовать небольшой скрипт для преобразования 0 и 1 в подходящие байты, а затем простой макрос или функцию для извлечения отдельных битов., @Nick Gammon
Также см. [этот вопрос](https://arduinoprosto.ru/q/34586/reading-a-10-byte-buffer-out-of-a-progmem-string-stored-in-a-string-table /) об индексации в большие массивы, где я разместил ответ, позволяющий избежать повреждения., @Nick Gammon
Спасибо за ответы, ребята. Завтра попробую некоторые предложения и посмотрю, как пойдет. В худшем случае, похоже, мне придется просто использовать такие биты, как предложил Ник, чтобы избежать проблемы с адресацией 64 КБ, которая, похоже, есть у Arduino., @KaYBlitZ
Память Mega достаточно ограничена: если вы сохраняете только 0 или 1 в байте (8 бит), вы теряете много памяти (7 неиспользуемых битов на байт). Рассмотрите возможность объединения 8 0 и 1 в 1 байт (с использованием операторов сдвига битов)., @Michel Keijzers