Опять PROGMEM
- Войдите на сайт для отправки комментариев
Чт, 09/06/2022 - 13:13
Добрый день, камрады. Снова взялся колупать PROGMEM и снова хожу по граблям. Вот код, работает как я ожидаю, в сериал выводятся значение " FWD" (соотвественно если вызываю foo(1), то выводится " REW", если foo(2), то выводится "FWD/REW".
const char name_30[] PROGMEM = " FWD";
const char name_31[] PROGMEM = " REW";
const char name_32[] PROGMEM = "FWD/REW";
const char *const directionNames[] PROGMEM = {name_30, name_31, name_32 };
void setup() {
Serial.begin(115200);
foo(0);
}
void foo (const uint16_t _value) {
for (uint16_t i = 0; i < 7; i++) Serial.print((char)pgm_read_byte_near(directionNames[_value] + i));
}
void loop() {
// put your main code here, to run repeatedly:
}
Но стоит продолжить мысль и возжелать вывести несколько значений - получаю кракозябры (даже если с одним аргементом пытаюсь вызвать foo более одного раза):
const char name_30[] PROGMEM = " FWD";
const char name_31[] PROGMEM = " REW";
const char name_32[] PROGMEM = "FWD/REW";
const char *const directionNames[] PROGMEM = {name_30, name_31, name_32 };
void setup() {
Serial.begin(115200);
foo(0);
foo(1);
}
void foo (const uint16_t _value) {
for (uint16_t i = 0; i < 7; i++) Serial.print((char)pgm_read_byte_near(directionNames[_value] + i));
}
void loop() {
// put your main code here, to run repeatedly:
}
Что я делаю не так?
Сколько у тебя уровней вложенности progmem
и сколько вызовов чтения из этой памяти?И зачем ты вообще со строками работаешь посимвольно?
Сколько у тебя уровней вложенности progmem
и сколько вызовов чтения из этой памяти?М... Два выходит? (я не настоящий сварщик, маску на стройке нашёл)...
И зачем ты вообще со строками работаешь посимвольно?
Задача такая - есть массив char подготовленный для вывода на экран. Нужно на определенное место вставить в него значения параметров. Мой больной разум породил для этой задачи такую функцию (визуально работает как надо, хотя не исключаю возникновения подводных камней типа как в первом сообщении):
void addDirectionValue (char* buffer, const uint8_t value) { uint8_t bufSize = strlen_P(pgm_read_ptr_near(directionNames + value)) + 1; char bufferVal[bufSize]; strcpy_P(bufferVal, pgm_read_ptr_near(directionNames + value)); for (uint8_t i = 0; i < bufSize; i++) buffer[i + 12] = bufferVal[i]; }Но захотелось уйти от промежуточного буффера и напрямую из прогмема писать в массив, для вывода на экран.
...pgm_read_byte_near(&directionNames[_value] + i));
...pgm_read_byte_near(&directionNames[_value] + i));
По Вашему не взлетело, а вот так получилось:
void addDirectionValue (char* buffer, const uint8_t value) { char *ptr = pgm_read_ptr_near(directionNames + value); for (uint8_t i = 0; i < strlen_P(pgm_read_ptr_near(directionNames + value)); i++) { buffer[12 + i] = pgm_read_byte_near(ptr++); } }И такой вариант тоже заработал:
void addDirectionValue (char* buffer, const uint8_t startPosition, const uint8_t value) { for (uint8_t i = 0; i < strlen_P(pgm_read_ptr_near(directionNames + value)); i++) { buffer[startPosition + i] = pgm_read_byte_near((char*)pgm_read_ptr_near(directionNames + value) + i); } }Вроде то что я хотел. Если более опытные товарищи скажут что я пытаюсь вырвать гланды через задницу, а после объяснят как это делать правильно - выслушаю с благодарностью.
Чтобы было понятно - названия параметров хранятся так:
const char name_30[] PROGMEM = " FWD"; const char name_31[] PROGMEM = " REW"; const char name_32[] PROGMEM = "FWD/REW"; const char *const directionNames[] PROGMEM = { name_30, name_31, name_32 };const char directionNames[] PROGMEM = " FWD"" REW""FWD/REW"; void setup() { Serial.begin(115200); foo(0); foo(1); foo(2); } void foo(const uint16_t _value) { for (uint16_t i = 0; i < 7; i++) Serial.print((char)pgm_read_byte(&directionNames[_value * 7 + i])); } void loop() { }Не?
Чтобы было понятно - названия параметров хранятся так:
const char name_30[] PROGMEM = " FWD"; const char name_31[] PROGMEM = " REW"; const char name_32[] PROGMEM = "FWD/REW"; const char *const directionNames[] PROGMEM = { name_30, name_31, name_32 };если перенести массив указателей directionNames[] в ОЗУ из ПРОГМЕМа (он небольшой, занимает мало) - то работать со строками станет занчительно проще.
если перенести массив указателей directionNames[] в ОЗУ из ПРОГМЕМа (он небольшой, занимает мало) - то работать со строками станет занчительно проще.
Это я понимаю, но все равно рано или поздно придётся с указателями и прогмемом разбираться.
Да, спасибо, очень интересная мысль уложить все значения в одну строку, при условии что они одного размера.