MRW 0 28 марта, 2007 Опубликовано 28 марта, 2007 · Жалоба // Menus define: void KeySC (void); // Прототипы фуекций void TimeMenu1 (void); void TimeMenu0 (void); void FPout (void); void Fauto (void); void Fstop (void); void FPr0 (void); void FPr1 (void); void FPr2 (void); void FPr3 (void); // Главное меню MAKE_MENU(POUT,STAT,PARAM,NULL_ENTRY,NULL_ENTRY,FPout,TimeMenu0,"Pout"); MAKE_MENU(STAT,PARAM,POUT,POUT,AUTO,KeySC,TimeMenu1,"Stat"); MAKE_MENU(PARAM,POUT,STAT,POUT,PR1,KeySC,TimeMenu1,"Prtr"); // Подменю STAT MAKE_MENU(AUTO,STOP,HAND,STAT,okAUTO,KeySC,TimeMenu0,"Auto"); MAKE_MENU(okAUTO,NULL_ENTRY,NULL_ENTRY,NULL_ENTRY,NULL_ENTRY,KeySC,Fauto,"end "); MAKE_MENU(STOP,HAND,AUTO,STAT,okSTOP,KeySC,TimeMenu0,"Stop"); MAKE_MENU(okSTOP,NULL_ENTRY,NULL_ENTRY,NULL_ENTRY,NULL_ENTRY,KeySC,Fstop,"end "); MAKE_MENU(HAND,AUTO,STOP,STAT,NULL_ENTRY,KeySC,TimeMenu0,"Hand"); // Подменю PARAM MAKE_MENU(PR1,NULL_ENTRY,NULL_ENTRY,PARAM,SetParam,FPr1,FPr0,"Pr "); MAKE_MENU(SetParam,NULL_ENTRY,NULL_ENTRY,PR1,NULL_ENTRY,FPr3,FPr2,"__ "); Это основное описание. Как я уже говорил, работаем на GCC. Изменения незначительны. Из всех вариантов, которые мы использовали, это самый удобный в использовании, пасширении/изменении, и наименьший по объему памяти. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alux 0 29 марта, 2007 Опубликовано 29 марта, 2007 · Жалоба Первую ошибку можно обойти, указав размер массива Text[6] при определении Menu_Item. А вот со второй ошибкой не могу справится. В чем же дело? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kolia 0 30 марта, 2007 Опубликовано 30 марта, 2007 · Жалоба Выкладываю исходник простого и удобного меню для HD44780. Новигация осуществляется при помощи 3 клавиш, плюс добавлена процедура редактирования переменных этими же клавишами. В общем при помощи этого меню и трех клавиш можно сорать полноценное устройство. Menu.zip Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
beer_warrior 0 30 марта, 2007 Опубликовано 30 марта, 2007 · Жалоба А вот со второй ошибкой не могу справится. В чем же дело? Поблема в разной реализации доступа к чтению констант. Неоспоримым преимуществом ИАРа есть свободное использование инструкции LPM в к любой константе с модификатором _flash. В gcc это обходится с помошью специальных процедур чтения байтов. ИМХО в макросах затерялся модификатор _flash используемый некорректно. Для исправления можно объявить все простыми константами и работать с ними в памяти. Потом найти лишний _flash или PROGMEM Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
IgorKossak 0 1 апреля, 2007 Опубликовано 1 апреля, 2007 · Жалоба Первую ошибку можно обойти, указав размер массива Text[6] при определении Menu_Item. А вот со второй ошибкой не могу справится. В чем же дело? Очевидно, что в параметрах некой функции вместо указателя на функцию используется указатель на unsigned char const. Или наоборот. В любом случае полезно локализовывать место ошибки. Если в одной строке несколько мест, вызывающих сомнение, то такую строку полезно разбить на несколько, благо С это позволяет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Яrik 0 13 июля, 2007 Опубликовано 13 июля, 2007 · Жалоба Только сильно не ругайте: Решил попробывать код предложеный Andy_F: struct menu_item { unsigned char Name[17]; struct menu_item *Parent; struct menu_item *Child; struct menu_item *Prev; struct menu_item *Next; }; struct menu_item Menu[5]={ {"Volume ", NULL, NULL, NULL, &Menu[1]}, // [0] {"Power ", NULL, NULL, &Menu[0], &Menu[2]}, // [1] {"Light ", NULL, NULL, &Menu[1], &Menu[3]}, // [2] {"U min of batt ", NULL, NULL, &Menu[2], &Menu[4]}, // [3] {"Autotune ", NULL, NULL, &Menu[3], NULL} // [4] }; но чего то ругается, пишет undefined symbol 'Menu' в строке {"Volume ", NULL, NULL, NULL, &Menu[1]}, // [0] Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
IceS 0 16 июля, 2007 Опубликовано 16 июля, 2007 (изменено) · Жалоба но чего то ругается, пишет undefined symbol 'Menu' в строке {"Volume ", NULL, NULL, NULL, &Menu[1]}, // [0] У меня IAR 4.30 скомпилил без проблем. Вернее у меня не был определен NULL, после #define NULL 0 все скомпилировалось нормально Изменено 16 июля, 2007 пользователем IceS Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alux 0 7 августа, 2007 Опубликовано 7 августа, 2007 · Жалоба По поводу Micro-Menu... При попытке вызова SET_MENU(Level1Item1); как указано в псевдокоде (MicroMenu.zip) программа вылетает. Пробовал определить структуру меню в ОЗУ. Не помогает. Вот мой пример: #include <inavr.h> #include "defines.h" #include "i2c.h" #include "tic154.h" #include "Menu.c" // Prototypes: void Level1Item1Sub1_Text(void); void Level1Item1Sub1_Func(void); const char Buffer[]="OPTIONS"; // Menus: MAKE_MENU(Level1Item1, Level1Item2, Level1Item3, NULL_ENTRY, Level1Item1Sub1, NULL_FUNC, NULL_FUNC, "ITEM 1"); MAKE_MENU(Level1Item2, Level1Item3, Level1Item1, NULL_ENTRY , NULL_ENTRY, NULL_FUNC, NULL_FUNC, "ITEM 2"); MAKE_MENU(Level1Item3, Level1Item1, Level1Item2, NULL_ENTRY, NULL_ENTRY, NULL_FUNC, NULL_FUNC, "ITEM 3"); MAKE_MENU(Level1Item1Sub1, NULL_ENTRY , NULL_ENTRY , Level1Item1, NULL_ENTRY,Level1Item1Sub1_Func, Level1Item1Sub1_Text, NULL_TEXT); // Functions: void Level1Item1Sub1_Text(void) { char Buffer[] = "*YNAMIC MENU TEXT"; Buffer[0] = 'D'; LCD_Put_Str(Buffer); // LCD_Write_SRAM_String(Buffer); } void Level1Item1Sub1_Func(void) { // Shutdown_App(); } //.......................................... void main (void) { // Initialise TWI_Init(100); // set TWI bit rate to 100KHz LCD_Init(); SET_MENU_WRITE_FUNC(Buffer); SET_MENU(Level1Item1); SET_MENU(PARENT); SET_MENU(SIBLING); SET_MENU(PREVIOUS); SET_MENU(NEXT); GO_MENU_FUNC(SELECTFUNC); } //################################ // Menu.c #include "Menu.h" #include <string.h> Menu_Item Null_Menu = {(void*)0, (void*)0, (void*)0, (void*)0, (void*)0, (void*)0, {0x00}}; Menu_Item* CurrMenuItem; WriteFuncPtr* WriteFunc; void MenuChange(Menu_Item* NewMenu) { if ((void*)NewMenu == (void*)&NULL_ENTRY) return; CurrMenuItem = NewMenu; #if defined(MENU_USE_SRAM_BUFFER) #if (MENU_USE_SRAM_BUFFER < 1) #error Menu SRAM Buffer Size not Defined! #endif char Buffer[MENU_USE_SRAM_BUFFER]; strcpy(Buffer, CurrMenuItem->Text); //strcpy_P ((WriteFuncPtr)WriteFunc)((const char*)Buffer); #else ((WriteFuncPtr)WriteFunc)((const char*)CurrMenuItem->Text); #endif GO_MENU_FUNC(ENTERFUNC); } void MenuFunc(FuncPtr* Function) { if ((void*)Function == (void*)NULL_FUNC) return; ((FuncPtr)Function)(); } //##################################################### //Menu.h #ifndef MENU_H #define MENU_H //#include <pgmspace.h> // Typedefs: typedef void (*FuncPtr)(void); typedef void (*WriteFuncPtr)(const char*); typedef struct { // __flash void *Next; void *Previous; void *Parent; void *Sibling; FuncPtr SelectFunc; FuncPtr EnterFunc; const char Text[6]; } Menu_Item; // Externs: extern WriteFuncPtr* WriteFunc; extern Menu_Item Null_Menu; extern Menu_Item* CurrMenuItem; // Defines and Macros: #define NULL_ENTRY Null_Menu #define NULL_FUNC (void*)0 #define NULL_TEXT 0x00 #define MENU_USE_SRAM_BUFFER 32 #define PREVIOUS *((Menu_Item*)(&CurrMenuItem->Previous)) #define NEXT *((Menu_Item*)(&CurrMenuItem->Next)) #define PARENT *((Menu_Item*)(&CurrMenuItem->Parent)) #define SIBLING *((Menu_Item*)(&CurrMenuItem->Sibling)) #define ENTERFUNC *((Menu_Item*)(&CurrMenuItem->EnterFunc)) #define SELECTFUNC *((Menu_Item*)(&CurrMenuItem->SelectFunc)) #define MAKE_MENU(Name, Next, Previous, Parent, Sibling, SelectFunc, EnterFunc, Text) \ extern Menu_Item Next; \ extern Menu_Item Previous; \ extern Menu_Item Parent; \ extern Menu_Item Sibling; \ Menu_Item Name = {(void*)&Next, (void*)&Previous, (void*)&Parent, (void*)&Sibling, (FuncPtr)SelectFunc, (FuncPtr)EnterFunc, { Text }} #define SET_MENU_WRITE_FUNC(x) \ WriteFunc = (WriteFuncPtr*)&x; #define SET_MENU(x) \ MenuChange((Menu_Item*)&x); #define GO_MENU_FUNC(x) \ MenuFunc((FuncPtr*)&x) #define EXTERN_MENU(Name) \ extern Menu_Item Name; // Prototypes: void MenuChange(Menu_Item* NewMenu); void MenuFunc(FuncPtr* Function); #endif Помогите, пожалуйста, разобраться с этим меню. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
id_Alx 0 28 августа, 2007 Опубликовано 28 августа, 2007 · Жалоба Первую ошибку можно обойти, указав размер массива Text[6] при определении Menu_Item. А вот со второй ошибкой не могу справится. В чем же дело? Для IAR получилось так... umenu.rar Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Unknown_Usr 0 9 сентября, 2007 Опубликовано 9 сентября, 2007 · Жалоба Очень интересная, а главная злободневная для меня тема, жаль что раньше не набрёл на этот форум )). Меня интересует как вы решаете проблему размещения меню в памяти ? У меня сейчас всё меню создаётся при включении девайса и так там в памяти и висит. Для этих целей в прикрученой внешней оперативке под меню отведен килобайт памяти. Ну и приведу схематично то что сделано у меня. Требовалось создать иерархическое меню, причём в пунктах меню может быть что угодно от логотипа прибора и его настроек до отображения сигнала. Первым делом объявляеться структурка. Эта структура сама по себе не используеться, но все остальные типы меню содержат точно такие же поля, объявленые в той же последовательности: struct CustomMenu{ unsigned int ID;//номер, уникальный для каждого экземпляра меню unsigned char Count;//количество подменю unsigned char State;//текущее состояние меню struct CustomMenu *Prev;//указатель на предыдущее меню, у главного меню равен NULL struct CustomMenu **SubMenus;//массив указателей на подменю, на какое из этих подменю нужно //переходить видно по полю State void ( *OnDraw )( struct CustomMenu *Menu );//указатель на функцию отрисовки void ( *OnEvent )( struct CustomMenu *Menu, unsigned char Event );//указатель на функцию реакции на события }; //////////// /// /////////// Далее создаются "потомки" этой структуры, например строчное меню: struct StringMenu{ //поля "унаследованые" от CustomMenu: unsigned int ID;//номер, уникальный для каждого экземпляра меню unsigned char Count;//количество подменю unsigned char State;//текущее состояние меню struct CustomMenu *Prev;//указатель на предыдущее меню, у главного меню равен NULL struct CustomMenu **SubMenus;//массив указателей на подменю, на какое из этих подменю нужно //переходить видно по полю State void ( *OnDraw )( struct StringMenu *Menu );//функция отрисовки void ( *OnEvent )( struct StringMenu *Menu, unsigned char Event );//функция реакции на события //собственные поля unsigned char **TextStrings;//строки меню; Текущая строка в меню определяеться полем State }; Далее объявляем функции void StringMenuOnDraw( struct StringMenu *Menu )//функция отрисовки StringMenu { } void StringMenuOnEven( struct StringMenu *Menu, unsigned char Event );//функция реакции на события //StringMenu { } При создании экземпляра StringMenu присваиваем его полям - указателям на функции соответствующие обработчики. Здесь удобно то, что можно ко всем экземплярам меню обращаться так же, как к CustomMenu. Если теперь объявим переменную CustomMenu* CMenu и присвоим ей адрес созданного StringMenu *SMenu, то при выполнении кода СMenu->OnDraw( SMenu ); вызовется StringMenuOnDraw. Добавление нвых элементов можно реализовать так: void AddMenu( CustomMenu *Menu, unsigned char ID_Parent, unsigned char N_Child, unsigned char ID_Child ); где *Menu - указатель на главное меню; ID_Parent - ID экземпляра меню, в который хотим добавить новое меню: N_Child - номер нового меню в родительском ( по сути индекс нового экземпляра в массиве SubMenus родителя ); ID_Child - ID нового экземпляра меню. В общем я привёл основную идею, в коде могут попасться и некоторые ошибки и очепятки, но думаю, вполне понятно что я имею в виду )). Просьба большими кирпичами в меня не кидать и по голове не бить ; - )) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alux 0 27 сентября, 2007 Опубликовано 27 сентября, 2007 · Жалоба Для IAR получилось так... У меня не получается вызвать меню через символические имена: void menu_Init(void) { Level1Item1Sub1_Text(); SET_MENU_WRITE_FUNC(Level1Item1Sub1_Text); SET_MENU(Level1Item1); delay_ms(1000); SET_MENU(PARENT); delay_ms(1000); SET_MENU(SIBLING); delay_ms(1000); SET_MENU(PREVIOUS); delay_ms(1000); SET_MENU(NEXT); } Если вызывать через имя меню : void menu_Init(void) { Level1Item1Sub1_Text(); SET_MENU_WRITE_FUNC(Level1Item1Sub1_Text); SET_MENU(Level1Item1); delay_ms(1000); SET_MENU(Level1Item2); delay_ms(1000); SET_MENU(Level1Item3); delay_ms(1000); SET_MENU(Level1Item1); delay_ms(1000); SET_MENU(Level1Item2); } ... то все нормально, т.е. с интервалом в секунду выводятся пункты меню. В оригинальном исходнике символические имя определены так: #define PREVIOUS *((Menu_Item*)pgm_read_word(&CurrMenuItem->Previous)) #define NEXT *((Menu_Item*)pgm_read_word(&CurrMenuItem->Next)) #define PARENT *((Menu_Item*)pgm_read_word(&CurrMenuItem->Parent)) #define SIBLING *((Menu_Item*)pgm_read_word(&CurrMenuItem->Sibling)) #define ENTERFUNC *((FuncPtr*)pgm_read_word(&CurrMenuItem->EnterFunc)) #define SELECTFUNC *((FuncPtr*)pgm_read_word(&CurrMenuItem->SelectFunc)) В исправленной версии от Id_Alx опущен знак &. Добавление & приводит к перезапуску программы. Манипуляции с размерами CSTACK(0x100), RSTACK(0x40) не помогает. В чем же дело? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
id_Alx 0 2 октября, 2007 Опубликовано 2 октября, 2007 · Жалоба В исправленной версии от Id_Alx опущен знак &. Добавление & приводит к перезапуску программы. Манипуляции с размерами CSTACK(0x100), RSTACK(0x40) не помогает. В чем же дело? Вот только не надо не надо добавлять значки ("&"), смысл которых Вам, видимо, не совсем ясен, а потом жаловаться. Вероятность того, что программа заработает корректно после подобных манипуляций очень мала. Версия из моего архива не собирается или не работает после сборки? Я пользуюсь IAR 4.20A. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alux 0 3 октября, 2007 Опубликовано 3 октября, 2007 · Жалоба У меня меню заработало. Как теперь сделать, чтобы пункты меню выводились не последовательно в одно и то же место дисплея, а отобразить на экране пункты меню одного уровня, и навигацию осуществлять либо стрелочкой, либо инверсией пунктов меню? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
admiral 0 8 апреля, 2008 Опубликовано 8 апреля, 2008 · Жалоба Продолжу тему. У меня возникла необходимость создать грамотное меню с кучей подменю для своего устройства. Облазив этот форум, понял, что наилучший вариант по возможности в дальнейшем расширять меню, по требовательности к памяти... - это micro-menu. Программирую на CVAVR для МК Мега16 Общий смысл работы этого меню примерно, точнее сказать смутно :05:, представляю, поэтому начал потихоньку разбираться что где и как. В интернете по нему информации почти никакой. Нашел сайт создателя с его разработками, но там по теме микроменю ссылка на сайт http://avrfreaks.net/, но туда пускают только зарегеных пользователей. Зарегится мне не получилось. Вот решил тогда здесь спросить у знающих людей. Предупреждаю заранее, СИ я начал изучать месяц назад, но меню грамотное нужно обязательно, так что не пинайте если что за то, что я взялся за работу не по зубам. По мне так лучше день потерять, потом за пять минут долететь. (с) Как раз поможет углубленно изучит СИ. В общем так, комментариев там нету. Поэтому первым делом я начал добавлять комментарии. Вот докуда я дошел: / MICRO_MENU.H #ifndef _MENU_H_ #define _MENU_H_ //Тут указываются указатели на функции typedef void (* FuncPtr) (void); /*Новый тип FuncPtr - указатель на функцию, которая ничего не принимает и не возвращает */ typedef void (* WriteFuncPtr) (const char*); /*Новый тип WriteFuncPtr - указатель на функцию, входным параметром которой является указатель на строку в ПЗУ, которая ничего не вовращает */ typedef struct PROGMEM { void *Next; //Следующее меню void *Previous; //Предыдущее меню void *Parent; //Родительское меню void *Sibling; //Дочернее меню (вложение) FuncPtr SelectFunc; //Выбор фнкции при выборе меню FuncPtr EnterFunc; //Выбор функции при входе в меню (Применяется после того, как текст меню отображен) const char Text[22]; //Текст меню } Menu_Item; //Externs extern WriteFuncPtr *WriteFunc; //Переменная-указатель на функцию extern Menu_Item Null_Menu; //Переменная типа PROGMEM extern Menu_Item *CurrMenuItem; //Переменная-указаетль на данные типа PROGMEM //Defines and Macros #define NULL_ENTRY Null_Menu #define NULL_FUNC 0 #define NULL_TEXT 0x00 #define PREVIOUS *((Menu_Item*)pgm_read_word(&CurrMenuItem->Previous)) Вот теперь возник затык на последней строчке. 1. pgm_read_word - то я так понимаю функция из прикрепленного <avr/pgmspace.h> в оригинальном тексте. В примере выше для IAR эта строка отсутствовала, поэтому я тоже ее удалил. 2.Теперь я попытался разобраться для чего эта строка нужна. В примере использования было так: SET_MENU(PREVIOUS); Смотрим что такое SET_MENU #define SET_MENU(x) \ MenuChange((Menu_Item*)&x); Делаем подстановку: SET_MENU(PREVIOUS); == MenuChange((Menu_Item*)&*((Menu_Item*)(&CurrMenuItem->Previous))); Вот с этой строкой я не могу разобраться, особенно с сочетанием &* В общем если есть знающие люди и особенно те, кто уже работал с этим меню, отзовитесь. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sKWO 0 8 апреля, 2008 Опубликовано 8 апреля, 2008 · Жалоба #define PREVIOUS *((Menu_Item*)pgm_read_word(&CurrMenuItem->Previous)) Вот теперь возник затык на последней строчке. 1. pgm_read_word - то я так понимаю функция из прикрепленного <avr/pgmspace.h> в оригинальном тексте. В примере выше для IAR эта строка отсутствовала, поэтому я тоже ее удалил. с этим меню не работал , но вполне логично можна переписать под стандартный макрос Кодевизиона чтения слова из флеш, или создать свою функцию чтения, а удалять незя. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться