|
|
  |
Отображение меню на жк, реализация на CVAVR |
|
|
|
Mar 29 2006, 10:34
|
Участник

Группа: Свой
Сообщений: 38
Регистрация: 25-11-05
Из: Россия, Москва
Пользователь №: 11 377

|
Код 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 указатель на строку...
|
|
|
|
|
Mar 29 2006, 14:08
|
Местный
  
Группа: Свой
Сообщений: 300
Регистрация: 15-03-06
Из: Москва
Пользователь №: 15 284

|
Код /***************************************************** 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:office@hpinfotech.com
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) Вторая и САМАЯ ВАЖНАЯ проблема - не работает выход из подменю в предыдущее меню
|
|
|
|
|
Mar 29 2006, 15:25
|
Участник

Группа: Свой
Сообщений: 38
Регистрация: 25-11-05
Из: Россия, Москва
Пользователь №: 11 377

|
может стоит без приведении к 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);
|
|
|
|
|
Mar 29 2006, 15:52
|
Местный
  
Группа: Свой
Сообщений: 300
Регистрация: 15-03-06
Из: Москва
Пользователь №: 15 284

|
Цитата может стоит без приведении к 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....
|
|
|
|
|
Mar 31 2006, 16:00
|
Участник

Группа: Свой
Сообщений: 38
Регистрация: 25-11-05
Из: Россия, Москва
Пользователь №: 11 377

|
Нашёл я проблему по которой невозможно быйти из подменю... Допустим я захожу в меню настройки. Там 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 и при критических ситуациях там просматривать, что происходит с кодом...
|
|
|
|
|
Jan 21 2010, 04:59
|
Участник

Группа: Участник
Сообщений: 41
Регистрация: 1-06-08
Пользователь №: 37 967

|
Спасибо, сделал себе меню таким же образом. Легко меняется, код читабельный. Хороший Сайт.
|
|
|
|
|
Jan 22 2010, 09:00
|

Профессионал
    
Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581

|
я тоже делал меню, правда на WinAVR. любая вложенность подменю (делается рекурсивно, потому надо осторожность соблюдать), пункты меню разных видов (просто пункт, пункт-опция [аналог галочки в винде, типа "посветка вкл."], пункт-параметр [т.е. типа "громкость 35%"]). выбор просто пункта - просто возврат его Id, выбор пункта-параметра - вызов специальной функции изменения параметра (можно очень гибко все делать), пункт опция - так же вызов особой функции. описание системы пунктов меню при помощи макросов - достаточно простое, как мне кажется. предусмотрен вариант для ЖКИ с числом строк более 2 - тогда меню выглядит примерно как в древних мобилках типа Siemens. мне кажется, портировать под CVAVR несложно. кому интересно, подробности тут
--------------------
Я бы взял частями... но мне надо сразу.
|
|
|
|
|
Jan 22 2010, 10:03
|
Местный
  
Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527

|
Цитата(ARV @ Jan 22 2010, 12:00)  я тоже делал меню, правда на WinAVR. любая вложенность подменю (делается рекурсивно, потому надо осторожность соблюдать) Есть же MicroMenu (http://www.avrfreaks.net/index.php?module=Freaks%20Files&func=viewFile&id=2178&showinfo=1), там без рекурсий строится меню любой вложенности. Не обязательно брать 1 в 1, можно только принцип построения позаимствовать. Меню это ОЗУ вообще не расходует, что не мешает в него параметры вводить через константные уазатели. Принцип же построения простой и достаточно эффективный. А главное - удобный.
|
|
|
|
|
Jan 22 2010, 12:12
|
Местный
  
Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527

|
Цитата(ARV @ Jan 22 2010, 14:20)  рекурсию я имел ввиду для вызова функции, "путешествующей" по пунктам и возвращающей результат выбора пользователя, т.е. расход памяти на рекурсию небольшой. а что касается MicroMenu - кой чего интересного там подсмотрел, попробую улучшить свой вариант (у моего возможности шире). Дело то не в возможностях, а в принципах построения. Меню на основе структур очень легко дооснастить требующемся функционалом, но при этом оно не будет запутанным, а останется легко редактируемым. В Вашем же варианте без поллитры вообще не разобраться.  Кстати остальные подходы в Вашей TUI тоже как то не очень оптимальны. Методы опроса кнопок с использованием софтовых задержек на 20мс удивляет.
|
|
|
|
|
  |
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|