e-moe 0 29 марта, 2006 Опубликовано 29 марта, 2006 · Жалоба menu[current_menu].m[current_poz].mas menu - массив current_menu указывает на текущее меню .m обращаемся к помлю структуры в текущего меню т.к. там тоже массив, то current_poz указывает текущий пункт меню .mas есть указательна строку текущего меню и текущего пункта. Если взять код выше, то: menu[1].m[1].mas Активно второе меню (т.к. счёт начинается с 0): SETTINGS_MENU, далее в подменю SETTINGS_MENU выбран пункт 2 и далее .mas указатель на строку... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vet 0 29 марта, 2006 Опубликовано 29 марта, 2006 · Жалоба ps1x Совет: не пожалейте времени, прочитайте какой-нибудь учебник языка С, хотя бы тот же Керниган & Ритчи - будете программировать намного увереннее, и множество вопросов пропадёт. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ps1x 0 29 марта, 2006 Опубликовано 29 марта, 2006 · Жалоба спасибо за совет, но я уже так и делаю, только учебник другой )) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ps1x 0 29 марта, 2006 Опубликовано 29 марта, 2006 · Жалоба /***************************************************** This program was produced by the CodeWizardAVR V1.24.5 Standard Automatic Program Generator © Copyright 1998-2005 Pavel Haiduc, HP InfoTech s.r.l. http://www.hpinfotech.com e-mail:[email protected] Project : Version : Date : 28.03.2006 Author : ps1x Company : ccc Comments: Chip type : ATmega8 Program type : Application Clock frequency : 1,000000 MHz Memory model : Small External SRAM size : 0 Data Stack size : 256 *****************************************************/ #include <mega8.h> // Alphanumeric LCD Module functions #asm .equ __lcd_port=0x18;PORTB #endasm #include <lcd.h> #include <stdio.h> #include <delay.h> char kod; int current_menu=0; //Переменная указывает на текущее меню int current_poz=1; //Переменная указывает на текущий пункт меню/подменю void goto_menu(void); void print_menu(void); //Структура описывает пункт меню typedef struct _selection { unsigned char *mas; // Указатель на название пункта void (*function)(void); //Указатель на функцию выполняющуюся по нажатии на enter/escape unsigned ent_f: 4; //Флаг входа 4 бита - обычно ID меню в которое надо войти unsigned esc_f: 4; //Флаг выхода 4 бита - обычно ID меню в которое надо вернуться }SELECTION; //Структура описывает меню/подменю typedef struct _menu { unsigned char id; //Номер меню/подменю unsigned char num_selections; //Количество пунктов данного меню/подменю SELECTION *m; //Указатель намассив пунктов данного меню/подменю }MENU; //Номера меню/подменю enum __menu__id { MAIN_MENU, //Главное меню SETTINGS_MENU, //Меню настроек REPORT_MENU //Меню отчёта }; //Имена пунктов unsigned char X1[]={"Punkt 1"}; unsigned char X2[]={"Punkt 2"}; unsigned char X3[]={"Settings"}; unsigned char X4[]={"Report"}; unsigned char X5[]={"set 1"}; unsigned char X6[]={"set 2"}; unsigned char X7[]={"set 3"}; //Заголовки функций void func1(void){} void func2(void){} void func3(void){} void func4(void){} void func5(void){} void func6(void){} void func7(void){} //Массив хранищий пункты главного меню (структура SELECTION) static SELECTION menu_[]={ {X1, func1, 0, 0}, //Punkt 1 {X2, func2, 0, 0}, //Punkt 2 {X3, goto_menu, SETTINGS_MENU, MAIN_MENU}, //Punkt 3 {X4, goto_menu, REPORT_MENU, MAIN_MENU} //Punkt 4 }; //Массив хранищий пункты меню настроек (структура SELECTION) static SELECTION menu_m0[]={ {X5, func5, 0, 0}, //Punkt 1 {X6, func6, 0, 0}, //Punkt 2 {X7, func7, 0, 0} //Punkt 3 }; //Главный массив хранит в себе все меню/подменю //Все меню/подменю должны описываться в таком же порядке как и в enum __menu__id ... static MENU menu[] = { {MAIN_MENU, 4, menu_}, //Меню 1 {SETTINGS_MENU, 3, menu_m0} //Меню 2 }; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void goto_menu(void) {///////////////////////////в этой рутине возможно проблема/////////////////// switch (kod) {//////////////////////////////////////////////////////////////////////////////////////////////// case 'e': {current_menu=menu[current_menu].m[current_poz].ent_f; break;};//enter case 'b': {current_menu=menu[current_menu].m[current_poz].esc_f; break;};//escape } current_poz=0; } void print_menu() { lcd_clear(); lcd_puts(menu[current_menu].m[current_poz].mas); lcd_gotoxy(0,1); if (current_poz==(int) menu[current_menu].num_selections) ///////////////////////////////////////// {lcd_putsf("-------------------");}/////////////////проблема здесь!!!!!!!!!!!!////////////////////////////// else {lcd_puts(menu[current_menu].m[current_poz+1].mas);}//////////////////////////////////////// delay_ms(100); kod='k'; } // Timer 0 overflow interrupt service routine interrupt [TIM0_OVF] void timer0_ovf_isr(void) { // Place your code here } // Timer 1 overflow interrupt service routine interrupt [TIM1_OVF] void timer1_ovf_isr(void) { // Place your code here } // Declare your global variables here void main(void) { // Declare your local variables here // Input/Output Ports initialization // Port B initialization // Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out // State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0 PORTB=0x00; DDRB=0xFF; // Port C initialization // Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTC=0x00; DDRC=0x00; // Port D initialization // Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out // State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0 PORTD=0xFF; DDRD=0x00; // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 0,977 kHz TCCR0=0x05; TCNT0=0x00; // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 3,906 kHz // Mode: Normal top=FFFFh // OC1A output: Discon. // OC1B output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge TCCR1A=0x00; TCCR1B=0x04; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; // Timer/Counter 2 initialization // Clock source: System Clock // Clock value: Timer 2 Stopped // Mode: Normal top=FFh // OC2 output: Disconnected ASSR=0x00; TCCR2=0x00; TCNT2=0x00; OCR2=0x00; // External Interrupt(s) initialization // INT0: Off // INT1: Off MCUCR=0x00; // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x05; // Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off ACSR=0x80; SFIOR=0x00; // LCD module initialization lcd_init(16); // Global enable interrupts #asm("sei") while (1) { // Place your code here if(PIND.0==0){delay_ms(150);kod='u';} if(PIND.1==0){delay_ms(150);kod='d';} if(PIND.2==0){delay_ms(150);kod='e';} if(PIND.3==0){delay_ms(150);kod='b';} switch (kod) { case 'u': { if (current_poz<=0){current_poz=menu[current_menu].num_selections;}else{current_poz--;} print_menu(); break; }; case 'd': { if(current_poz>=menu[current_menu].num_selections-1){current_poz=0;}else{current_poz++;} print_menu(); break; }; case 'e': { menu[current_menu].m[current_poz].function(); print_menu(); break; }; case 'b': { menu[current_menu].m[current_poz].function(); print_menu(); break; }; }; }; } Возможные проблемы я выделил большим колличеством "//////". Во первых, меню почти заработало, но есть две проблемы: 1) Почемуто не сравнивается количество пунктов меню и активный пункт меню??? (если не сравнивать то можно делать меню на котором отображается только 1 пункт, что не есть хорошо) 2) Вторая и САМАЯ ВАЖНАЯ проблема - не работает выход из подменю в предыдущее меню :( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
e-moe 0 29 марта, 2006 Опубликовано 29 марта, 2006 · Жалоба может стоит без приведении к int попробовать? if (current_poz==menu[current_menu].num_selections) или же поля (esc_f и ent_f) объявить как char или int попробуй вызывать переход как void goto_menu(char); //// void goto_menu(char kod) {...}; //// goto_menu(kod); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ps1x 0 29 марта, 2006 Опубликовано 29 марта, 2006 · Жалоба может стоит без приведении к int попробовать? if (current_poz==menu[current_menu].num_selections) - с этим уже разобрался, показывает сносно ) или же поля (esc_f и ent_f) объявить как char или int попробуй вызывать переход как void goto_menu(char); //// void goto_menu(char kod) {...}; //// goto_menu(kod); - В подменю входит, а выходить из него не хочет (((( ума не приложу, вроде-бы все seems to be alright.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ps1x 0 29 марта, 2006 Опубликовано 29 марта, 2006 · Жалоба Неужели никто на этом форуме не знает язык С??? Это же не драйвер видеокарты, а всего лишь менюшка! Полный код программы есть немного выше. Спасибо всем кто откликнется. p.s. не отправляйте меня сразу книжки читать, я считаю что начинать изучение языка с типов переменных неправильно. Лучше изучать в примерах, имхо доступнее для понимания. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 30 марта, 2006 Опубликовано 30 марта, 2006 · Жалоба Делал меню под заказ. Правда для графических дисплеев. Вот исходник. Думаю, откинув (или заменив) функции вывода графики получите то что Вам надо Menu_unit.rar Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
e-moe 0 31 марта, 2006 Опубликовано 31 марта, 2006 · Жалоба Нашёл я проблему по которой невозможно быйти из подменю... Допустим я захожу в меню настройки. Там 3 пункта: Настройка 1 >Настройка 2 Настройка 3 Активен пункт 2. тогда при нажатии на ESC происходит вызов: menu[current_menu].m[current_poz].function() Совершенно очевидно что function() не является функцией goto_menu(), т.к. это функция вызовает опии пункта настройки 2. Есть 2 выхода либо добавть отдельно пункт Выход в каждое подменю и поместить для вызова функцию goto_menu(), либо: case ESC: { //убрать menu[current_menu].m[current_poz].function(&kkk); goto_menu(); //оставить /*В таком случае при нажати на ESC всегда будет вызываться данная функция*/ print_menu(); . . . break; P.S. В ИАР есть возможность посмотреть как ведёт себя код, какие переменные куда идут, в режиме отладки. Если нет возможности его использовать, то неплохо бы поставить AVRStudio и при критических ситуациях там просматривать, что происходит с кодом... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ps1x 0 31 марта, 2006 Опубликовано 31 марта, 2006 · Жалоба Все получилось, хотя сначала делал вариант с пунктом "назад" в каждом подменю, но то что предложили Вы гораздо удобнее с точки зрения юзера )) Большое спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
LSergM 0 21 января, 2010 Опубликовано 21 января, 2010 · Жалоба Спасибо, сделал себе меню таким же образом. Легко меняется, код читабельный. Хороший Сайт. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ARV 1 22 января, 2010 Опубликовано 22 января, 2010 · Жалоба я тоже делал меню, правда на WinAVR. любая вложенность подменю (делается рекурсивно, потому надо осторожность соблюдать), пункты меню разных видов (просто пункт, пункт-опция [аналог галочки в винде, типа "посветка вкл."], пункт-параметр [т.е. типа "громкость 35%"]). выбор просто пункта - просто возврат его Id, выбор пункта-параметра - вызов специальной функции изменения параметра (можно очень гибко все делать), пункт опция - так же вызов особой функции. описание системы пунктов меню при помощи макросов - достаточно простое, как мне кажется. предусмотрен вариант для ЖКИ с числом строк более 2 - тогда меню выглядит примерно как в древних мобилках типа Siemens. мне кажется, портировать под CVAVR несложно. кому интересно, подробности тут Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Qwertty 0 22 января, 2010 Опубликовано 22 января, 2010 · Жалоба я тоже делал меню, правда на WinAVR. любая вложенность подменю (делается рекурсивно, потому надо осторожность соблюдать) Есть же MicroMenu (http://www.avrfreaks.net/index.php?module=Freaks%20Files&func=viewFile&id=2178&showinfo=1), там без рекурсий строится меню любой вложенности. Не обязательно брать 1 в 1, можно только принцип построения позаимствовать. Меню это ОЗУ вообще не расходует, что не мешает в него параметры вводить через константные уазатели. Принцип же построения простой и достаточно эффективный. А главное - удобный. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ARV 1 22 января, 2010 Опубликовано 22 января, 2010 · Жалоба Есть же MicroMenu (http://www.avrfreaks.net/index.php?module=Freaks%20Files&func=viewFile&id=2178&showinfo=1), там без рекурсий строится меню любой вложенности. Не обязательно брать 1 в 1, можно только принцип построения позаимствовать. Меню это ОЗУ вообще не расходует, что не мешает в него параметры вводить через константные уазатели. Принцип же построения простой и достаточно эффективный. А главное - удобный.рекурсию я имел ввиду для вызова функции, "путешествующей" по пунктам и возвращающей результат выбора пользователя, т.е. расход памяти на рекурсию небольшой. а что касается MicroMenu - кой чего интересного там подсмотрел, попробую улучшить свой вариант (у моего возможности шире). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Qwertty 0 22 января, 2010 Опубликовано 22 января, 2010 · Жалоба рекурсию я имел ввиду для вызова функции, "путешествующей" по пунктам и возвращающей результат выбора пользователя, т.е. расход памяти на рекурсию небольшой. а что касается MicroMenu - кой чего интересного там подсмотрел, попробую улучшить свой вариант (у моего возможности шире). Дело то не в возможностях, а в принципах построения. Меню на основе структур очень легко дооснастить требующемся функционалом, но при этом оно не будет запутанным, а останется легко редактируемым. В Вашем же варианте без поллитры вообще не разобраться. :) Кстати остальные подходы в Вашей TUI тоже как то не очень оптимальны. Методы опроса кнопок с использованием софтовых задержек на 20мс удивляет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться