Отправить массив 2d PROGMEM через SoftwareSerial

У меня есть двумерный массив:

const byte messages_for_measurement[2][8] PROGMEM = 
{
  { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 },
  { 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 },
};

Я хочу отправить один из этих подмассивов по серийному номеру программного обеспечения.

Изначально это создавало ненужные данные:

swSerial.write( messages_for_measurement[0], sizeof(messages_for_energy_meter[0]) );

Затем я узнал о pgm_read_byte_near() и pgm_read_word(). Я перепробовал все комбинации, но это не сработало:

swSerial.write(pgm_read_byte_near(pgm_read_word(messages_for_measurement[0]))), sizeof(pgm_read_byte_near(pgm_read_word(messages_for_measurement[0])));

и

swSerial.write(pgm_read_byte_near(&pgm_read_word(messages_for_measurement[0]))), sizeof(pgm_read_byte_near(pgm_read_word(&messages_for_measurement[0])));

и

swSerial.write(char(pgm_read_byte_near(pgm_read_word(messages_for_measurement[0])))), sizeof(char(pgm_read_byte_near(pgm_read_word(messages_for_measurement[0]))));

и

swSerial.write(char(pgm_read_byte_near(pgm_read_word(&messages_for_measurement[0])))), sizeof(char(pgm_read_byte_near(pgm_read_word(&messages_for_measurement[0]))));

Как я могу отправить подмассив по последовательному порту, когда массив 2d находится в PROGMEM?

, 👍0


1 ответ


1

Метод write() из SoftwareSerial (который унаследован от абстрактный класс Print) не поддерживает печать двоичных файлов на основе PROGMEM буферы. Метод print() имеет некоторую поддержку PROGMEM, но он ограничивается печатью символьных строк, заканчивающихся NUL, и предназначен для используется с макросом F(). Вы можете заставить этот метод печатать ваши данные, но для этого потребуется добавить нулевой байт в конце каждый внутренний массив, и трюк не сработает, если вам когда-нибудь придется отправить нулевой байт.

Кроме того, макросы pgm_read_stuff() не могут одновременно читать массив. Ты можно добиться этого с помощью memcpy_P(), но для этого потребуется выделение массива в оперативной памяти. Я думаю, что самое простое решение здесь - получить байты из флэш-памяти один за другим с помощью pgm_read_byte():

const byte *message = messages_for_measurement[0];
size_t size = sizeof messages_for_measurement[0];
for (size_t i = 0; i < size; i++) {
    swSerial.write(pgm_read_byte(&message[i]));
}

Обратите внимание, что первая строка не пытается получить доступ к данным массива: она копирует в message только адрес первого байта: это семантика преобразования в указатель.

,