Что за хрень у меня с PROGMEM?
- Войдите на сайт для отправки комментариев
Ср, 23/09/2020 - 12:26
Вот такой несложный примерчик:
char buf[30] = {};
typedef const struct PROGMEM MENU1 {
const struct MENU1 *Next;
const struct MENU1 *Previous;
const struct MENU1 *Parent;
const struct MENU1 *Child;
void (*handler)(void);
const char Name[21];
} MENU;
MENU *curr = NULL;
MENU Menu[]={
{&Menu[1],&Menu[2],&Menu[0],&Menu[3],0,"Menu1"}, //
{&Menu[2],&Menu[0],&Menu[1],&Menu[1],0,"Menu2"}, //
{&Menu[0],&Menu[1],&Menu[2],&Menu[2],0,"Menu3"}, //
{&Menu[4],&Menu[5],&Menu[0],&Menu[6],0,"SUB_Menu1 "}, //
{&Menu[5],&Menu[3],&Menu[1],&Menu[4],0,"SUB_Menu2 "}, //
{&Menu[3],&Menu[4],&Menu[2],&Menu[5],0,"SUB_Menu3 "}
};
void setup() {
Serial.begin(115200);
for (int i=0; i<6;i++)
{
curr = (MENU*)pgm_read_byte(&Menu[i]);
sprintf_P(buf, PSTR("%S"), (char*)curr->Name);
Serial.println(buf);
}
}
void loop() {
}
А на выходе:
Menu2
Menu3
Menu1
SUB_Menu2
⸮⸮⸮⸮
SUB_Menu1
Это как так получается?
Atmega328. Компилятор предупреждений не дает даже с -Wall
pgm_read_byteНу и указатели на память из progmem-структуры - шикардос
хм, я бы тоже спросил "что за хрень"?
MENU Menu[]={ {&Menu[1],&Menu[2],&Menu[0],&Menu[3],0,"Menu1"}, // {&Menu[2],&Menu[0],&Menu[1],&Menu[1],0,"Menu2"}, // {&Menu[0],&Menu[1],&Menu[2],&Menu[2],0,"Menu3"}, // {&Menu[4],&Menu[5],&Menu[0],&Menu[6],0,"SUB_Menu1 "}, // {&Menu[5],&Menu[3],&Menu[1],&Menu[4],0,"SUB_Menu2 "}, // {&Menu[3],&Menu[4],&Menu[2],&Menu[5],0,"SUB_Menu3 "} };указатели сами на себя? - ну допустим...
а ничего, что в момент инициализации первой строки еще не существует Menu[1] Menu[2] и Menu[3] - а ссылки на них уже используются? - или компилятор разберется?
pgm_read_byteЗамена на pgm_read_word в данном случае ничего не меняет, хотя да, байт это косяк.
Ну и как надо?
хм, я бы тоже спросил "что за хрень"?
MENU Menu[]={ {&Menu[1],&Menu[2],&Menu[0],&Menu[3],0,"Menu1"}, // {&Menu[2],&Menu[0],&Menu[1],&Menu[1],0,"Menu2"}, // {&Menu[0],&Menu[1],&Menu[2],&Menu[2],0,"Menu3"}, // {&Menu[4],&Menu[5],&Menu[0],&Menu[6],0,"SUB_Menu1 "}, // {&Menu[5],&Menu[3],&Menu[1],&Menu[4],0,"SUB_Menu2 "}, // {&Menu[3],&Menu[4],&Menu[2],&Menu[5],0,"SUB_Menu3 "} };указатели сами на себя? - ну допустим...
а ничего, что в момент инициализации первой строки еще не существует Menu[1] Menu[2] и Menu[3] - а ссылки на них уже используются? - или компилятор разберется?
Да бог с ними с указателями, я же ими не пользуюсь. Просто взял пример с просторов. Хотя по
curr = (MENU*)pgm_read_byte(&curr->Next);
Переходит, вроде, правильно.
А начал с того что пытался прикрутить https://github.com/abcminiuser/micromenu-v2
Нихрена не заработало. Решил протестировать на чем попроще.
а если сначала создать массив, а потом уже заполнить ссылками? я понимаю, что некрасиво - но если глюки пропадут. будет ясно. что дело в инициализации
Заработало после того как добавил указатель на самого себя
char buf[30] = {}; typedef const struct PROGMEM MENU1 { const struct MENU1 *Self; const struct MENU1 *Next; const struct MENU1 *Previous; const struct MENU1 *Parent; const struct MENU1 *Child; void (*handler)(void); const char Name[21]; } MENU; MENU *curr = NULL; MENU Menu[]={ {&Menu[0],&Menu[1],&Menu[2],&Menu[0],&Menu[3],0,"Menu1"}, // {&Menu[1],&Menu[2],&Menu[0],&Menu[1],&Menu[1],0,"Menu2"}, // {&Menu[2],&Menu[0],&Menu[1],&Menu[2],&Menu[2],0,"Menu3"}, // {&Menu[3],&Menu[4],&Menu[5],&Menu[0],&Menu[6],0,"SUB_Menu1 "}, // {&Menu[4],&Menu[5],&Menu[3],&Menu[1],&Menu[4],0,"SUB_Menu2 "}, // {&Menu[5],&Menu[3],&Menu[4],&Menu[2],&Menu[5],0,"SUB_Menu3 "} }; void setup() { Serial.begin(115200); for (int i=0; i<6;i++) { curr = (MENU*)pgm_read_word(&Menu[i]); sprintf_P(buf, PSTR("%S"), (char*)curr->Name); Serial.println(buf); } curr = (MENU*)pgm_read_word(&curr->Next); sprintf_P(buf, PSTR("%S"), (char*)curr->Name); Serial.println("Next"); Serial.println(buf); curr = (MENU*)pgm_read_word(&curr->Parent); sprintf_P(buf, PSTR("%S"), (char*)curr->Name); Serial.println("Parent"); Serial.println(buf); }asam, могу тебе подправленное микроменю2 выдать. У меня тоже с ходу не завелось, пришлось подебажить.
asam, могу тебе подправленное микроменю2 выдать. У меня тоже с ходу не завелось, пришлось подебажить.
О, буду очснь признателен.
давай мыло или сам напиши на wrk.sadman@gmail.com
давай мыло или сам напиши на wrk.sadman@gmail.com
Написал, но, на всякий случай продублирую здесь - automation248@hotmail.com
asam, могу тебе подправленное микроменю2 выдать. У меня тоже с ходу не завелось, пришлось подебажить.
а мне что-то оно вообще не понравилось, все эти ссылки совершенно левые :)
Слепил свое, упрощенное, в нет никаких Парентов и Некстов :), а просто каждая строчка может быть либо переходом в другое меню(дочернее, родительское - не важно), либо функцией.
Я его тут на форуме публиковал, надо поискать ссылку
asam, могу тебе подправленное микроменю2 выдать. У меня тоже с ходу не завелось, пришлось подебажить.
а мне что-то оно вообще не понравилось, все эти ссылки совершенно левые :)
А мне лень было лепить своё, я там подправил в трёх местах... наверное можно было и в двух, ну да ладно )
Вполне себе работает. Разве что удобно интегрируется на однострочники... с остальным всё равно приходится башку ломать.
во, нашел примерчик своего
http://arduino.ru/forum/pesochnitsa-razdel-dlya-novichkov/sozdanie-mnogourovnevogo-graficheskogo-menyu#comment-530028
Кстати, вспомнил главное достоинство моего варианта (ну с моей иочки зрения) - в моей структуре можно в любое место добавить дополнительные пункты, не меняя ссылок соседних элементов. А удалять - просто комментируя строчки меню в коде, структура меню подстроится под изменения сама.
да, там вся ветка интересная, много других примеров кода
1 Я вообще против организации меню на структурах. Конечно организация отображение информации на экране решается хорошо. Вот со сменой обработчиков кнопок выходит не очень. И при кнопках подключенных на отдельные выводы, что сенсорные кнопки на экране.
2 Вторая тюфтень. Что это за позиции 0,1,2,3 и так далее. Да это удобно для компьютера, Для человека это первый источник поймать косяк. Так что здесь сразу объявлять костанты page0,page1,page2, и разумеется делать их подразделы page0_0,page0_1,page1_0,page1_1,page2_0,page2_1. Перечисляемый тип это оно.
3 Переходить из одного пункта меню лучше по отдельной специальной функции goPage(page0_1);
1 Я вообще против организации меню на структурах. Конечно организация отображение информации на экране решается хорошо. Вот со сменой обработчиков кнопок выходит не очень. И при кнопках подключенных на отдельные выводы, что сенсорные кнопки на экране.
Это интересная тема которую, возможно, стоит обсудить в отдельном топике про организацию меню.
Еще раз повторю для тех кто не читает весь топик - Я не пытаюсь организовать меню именно таким образом. Я пытаюсь разобраться как адресовать структуры и их поля из PROGMEM и просто взял готовый пример.
И мне так до конца и не понятно почему если засунуть в начало структуры указатель на свой экземпляр, то все начинает работать, как ожидалось, а без этого нет. Если есть что по этому поводу сказать, то с удовольствием выслушаю. А про меню, давайте в другой топик.