|
Отображение меню на жк, реализация на CVAVR |
|
|
|
Jan 22 2010, 13:19
|

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

|
для собственно TUI опрос кнопок без разницы  но скажите мне, где это может помешать?! у меня меню так же на основе структур, только я отказался от связного списка, в пользу массивов, как раз из-за простоты восприятия. плюс в списке надо хранить ссылки на следующего-предыдущего-корневого, а для массива не надо - FLASH экономится  а разобраться сложно - так можно и не разбираться, достаточно интерфейс понять  описание системы меню не сложнее, чем у MicroMenu - так же при помощи макросов, единственное, до чего я не догнал сразу - так это определить сразу тип для структуры в PROGMEM, и пришлось извращаться с предварительным описанием текстовых строк в виде констант. MicroMenu весьма лаконично - признаю. у меня более путано - да. не стремился к суперлаконичности, старался больше вариантов охватить
--------------------
Я бы взял частями... но мне надо сразу.
|
|
|
|
|
Jan 24 2010, 08:41
|
Участник

Группа: Участник
Сообщений: 57
Регистрация: 9-07-08
Из: Волгоградская обл
Пользователь №: 38 838

|
да согласен код слишком запутаный, как то реолизовал нечто подобное. вопервых можно все масивы вынести во флеш, ОЗУ сильно секономит, вовторых с нажатием кнопок несовсем понял фиксация по временной задержке, непрощели одно нажатие одно срабатывание
|
|
|
|
|
May 10 2010, 12:45
|
Участник

Группа: Участник
Сообщений: 17
Регистрация: 17-03-09
Пользователь №: 46 202

|
Недавно переделал Micro-Menu под dsPIC (MPLAB C30 v2.04). Делюсь опытом: Все изменения в файле Menu.h Во-первых, выбрасываем Код #include <avr/pgmspace.h> Во-вторых, вместо Код typedef struct { void *Next; void *Previous; void *Parent; void *Sibling; FuncPtr SelectFunc; FuncPtr EnterFunc; const char Text[]; } Menu_Item PROGMEM; должно быть Код typedef const struct { void *Next; void *Previous; void *Parent; void *Sibling; FuncPtr SelectFunc; FuncPtr EnterFunc; char Text[]; }Menu_Item; и в-третьих, вместо Код #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)) должно быть Код #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 *((FuncPtr*)(CurrMenuItem->EnterFunc)) #define SELECTFUNC *((FuncPtr*)(CurrMenuItem->SelectFunc)) Вроде, всё. Надеюсь, кому-нибудь поможет.
Сообщение отредактировал reload - May 10 2010, 12:48
|
|
|
|
|
May 11 2010, 14:02
|
Местный
  
Группа: Свой
Сообщений: 300
Регистрация: 15-03-06
Из: Москва
Пользователь №: 15 284

|
Вот окончательный полностью работающий вариант меню. CODE /***************************************************** This program was produced by the CodeWizardAVR V1.24.6 Standard Automatic Program Generator © Copyright 1998-2005 Pavel Haiduc, HP InfoTech s.r.l. http://www.hpinfotech.come-mail:office@hpinfotech.com Project : Version : Date : 15.01.2010 Author : ps1x Company : asd Comments: Chip type : ATmega8 Program type : Application Clock frequency : 8,000000 MHz Memory model : Small External SRAM size : 0 Data Stack size : 256 *****************************************************/ #include <mega8.h> #include <16x2.h> // Declare your global variables here char kod; char last_item; 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, //Главное меню DELAY_MENU, //Меню настроек FOCUS_MENU, QUANTITY_MENU, TIME_MENU //Меню отчёта }; //Имена пунктов unsigned char X1[]={"Задержка"}; unsigned char X2[]={"1 сек"}; unsigned char X3[]={"2 сек"}; unsigned char X4[]={"3 сек"}; unsigned char X5[]={"4 сек"}; unsigned char X6[]={"5 сек"}; unsigned char X7[]={"8 сек"}; unsigned char X8[]={"10 сек"}; unsigned char X9[]={"15 сек"}; unsigned char X10[]={"20 сек"}; unsigned char X11[]={"30 сек"}; unsigned char X12[]={"Фокусировка"}; unsigned char X13[]={"Выкл"}; unsigned char X14[]={"0,5 сек"}; unsigned char X15[]={"1 сек"}; unsigned char X16[]={"Кол. фоток"}; unsigned char X17[]={"50 шт"}; unsigned char X18[]={"100 шт"}; unsigned char X19[]={"200 шт"}; unsigned char X20[]={"300 шт"}; unsigned char X21[]={"500 шт"}; unsigned char X22[]={"800 шт"}; unsigned char X23[]={"1000 шт"}; unsigned char X24[]={"Время фотогр."}; unsigned char X25[]={"Непрерывно"}; unsigned char X26[]={"5 мин"}; unsigned char X27[]={"10 мин"}; unsigned char X28[]={"15 мин"}; unsigned char X29[]={"пол часа"}; unsigned char X30[]={"час"}; unsigned char X31[]={"два часа"}; unsigned char X32[]={"Старт съемки"}; //Заголовки функций void func1(void){} void func2(void){} void func3(void){} void func4(void){} void func5(void){} void func6(){} void func7(void){} //Массив хранищий пункты главного меню (структура SELECTION) static SELECTION menu_[]={ {X1, goto_menu, DELAY_MENU, MAIN_MENU}, //Punkt 1 {X12, goto_menu, FOCUS_MENU, MAIN_MENU}, //Punkt 2 {X16, goto_menu, QUANTITY_MENU, MAIN_MENU}, //Punkt 3 {X24, goto_menu, TIME_MENU, MAIN_MENU}, //Punkt 4 {X32, func7, 0, 0} //Punkt 4 }; //Массив хранищий пункты меню настроек (структура SELECTION) static SELECTION menu_m0[]={ {X2, func6, 0, 0}, //Punkt 1 {X3, func6, 0, 0}, //Punkt 2 {X4, func6, 0, 0}, //Punkt 3 {X5, func6, 0, 0}, //Punkt 2 {X6, func6, 0, 0}, //Punkt 2 {X7, func6, 0, 0}, //Punkt 2 {X8, func6, 0, 0}, //Punkt 2 {X9, func6, 0, 0}, //Punkt 2 {X10, func6, 0, 0}, //Punkt 2 {X11, func6, 0, 0} //Punkt 2 }; static SELECTION menu_m1[]={ {X13, func6, 0, 0}, //Punkt 1 {X14, func6, 0, 0}, //Punkt 2 {X15, func6, 0, 0} //Punkt 3 }; static SELECTION menu_m2[]={ {X17, func6, 0, 0}, //Punkt 1 {X18, func6, 0, 0}, //Punkt 2 {X19, func6, 0, 0}, //Punkt 3 {X20, func6, 0, 0}, //Punkt 1 {X21, func6, 0, 0}, //Punkt 2 {X22, func6, 0, 0}, //Punkt 3 {X23, func6, 0, 0} //Punkt 1 }; static SELECTION menu_m3[]={ {X25, func6, 0, 0}, //Punkt 1 {X26, func6, 0, 0}, //Punkt 2 {X27, func6, 0, 0}, //Punkt 3 {X28, func6, 0, 0}, //Punkt 1 {X29, func6, 0, 0}, //Punkt 2 {X30, func6, 0, 0}, //Punkt 3 {X31, func6, 0, 0} //Punkt 1 }; //Главный массив хранит в себе все меню/подменю //Все меню/подменю должны описываться в таком же порядке как и в enum __menu__id ... static MENU menu[] = { {MAIN_MENU, 5, menu_}, //Меню 1 {DELAY_MENU, 10, menu_m0}, //Меню 2 {FOCUS_MENU, 3, menu_m1}, {QUANTITY_MENU, 7, menu_m2}, {TIME_MENU, 7, menu_m3} }; void goto_menu(void) { switch (kod) { case 'e': {current_menu=menu[current_menu].m[current_poz].ent_f; last_item=current_poz; 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_putsf("> "); lcd_puts(menu[current_menu].m[current_poz].mas); lcd_gotoxy(2,1); if (current_poz == menu[current_menu].num_selections-1) { lcd_puts(menu[current_menu].m[0].mas); // lcd_putsf("-------------------"); } else { lcd_puts(menu[current_menu].m[current_poz+1].mas); } delay_ms(100); kod='k'; } void main(void) { // Declare your local variables here // Input/Output Ports initialization // Port B initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTB=0x00; DDRB=0x00; // Port C initialization // Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out // State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0 PORTC=0x00; DDRC=0xFF; // Port D initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTD=0xFF; DDRD=0x00; // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: Timer 0 Stopped TCCR0=0x00; TCNT0=0x00; // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: Timer 1 Stopped // Mode: Normal top=FFFFh // OC1A output: Discon. // OC1B output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge // Timer 1 Overflow Interrupt: Off // Input Capture Interrupt: Off // Compare A Match Interrupt: Off // Compare B Match Interrupt: Off TCCR1A=0x00; TCCR1B=0x00; 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=0x00; // Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off ACSR=0x80; SFIOR=0x00; lcd_init(); lcd_clear(); lcd_putsf(" МИЭМ"); lcd_gotoxy(0,1); lcd_putsf(" USB частотомер"); print_menu(); while (1) { 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-1;}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 'b': { goto_menu(); current_poz=last_item; print_menu(); break; }; case 'e': { menu[current_menu].m[current_poz].function(); print_menu(); break; }; }; }; }
|
|
|
|
|
May 12 2010, 09:21
|

Частый гость
 
Группа: Участник
Сообщений: 98
Регистрация: 20-06-05
Пользователь №: 6 150

|
Цитата(ps1x @ May 11 2010, 17:02)  Вот окончательный полностью работающий вариант меню. CODE /***************************************************** This program was produced by the CodeWizardAVR V1.24.6 Standard Automatic Program Generator © Copyright 1998-2005 Pavel Haiduc, HP InfoTech s.r.l. http://www.hpinfotech.come-mail:office@hpinfotech.com Project : Version : Date : 15.01.2010 Author : ps1x Company : asd Comments: Chip type : ATmega8 Program type : Application Clock frequency : 8,000000 MHz Memory model : Small External SRAM size : 0 Data Stack size : 256 *****************************************************/ #include <mega8.h> #include <16x2.h> // Declare your global variables here char kod; char last_item; 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, //Главное меню DELAY_MENU, //Меню настроек FOCUS_MENU, QUANTITY_MENU, TIME_MENU //Меню отчёта }; //Имена пунктов unsigned char X1[]={"Задержка"}; unsigned char X2[]={"1 сек"}; unsigned char X3[]={"2 сек"}; unsigned char X4[]={"3 сек"}; unsigned char X5[]={"4 сек"}; unsigned char X6[]={"5 сек"}; unsigned char X7[]={"8 сек"}; unsigned char X8[]={"10 сек"}; unsigned char X9[]={"15 сек"}; unsigned char X10[]={"20 сек"}; unsigned char X11[]={"30 сек"}; unsigned char X12[]={"Фокусировка"}; unsigned char X13[]={"Выкл"}; unsigned char X14[]={"0,5 сек"}; unsigned char X15[]={"1 сек"}; unsigned char X16[]={"Кол. фоток"}; unsigned char X17[]={"50 шт"}; unsigned char X18[]={"100 шт"}; unsigned char X19[]={"200 шт"}; unsigned char X20[]={"300 шт"}; unsigned char X21[]={"500 шт"}; unsigned char X22[]={"800 шт"}; unsigned char X23[]={"1000 шт"}; unsigned char X24[]={"Время фотогр."}; unsigned char X25[]={"Непрерывно"}; unsigned char X26[]={"5 мин"}; unsigned char X27[]={"10 мин"}; unsigned char X28[]={"15 мин"}; unsigned char X29[]={"пол часа"}; unsigned char X30[]={"час"}; unsigned char X31[]={"два часа"}; unsigned char X32[]={"Старт съемки"}; //Заголовки функций void func1(void){} void func2(void){} void func3(void){} void func4(void){} void func5(void){} void func6(){} void func7(void){} //Массив хранищий пункты главного меню (структура SELECTION) static SELECTION menu_[]={ {X1, goto_menu, DELAY_MENU, MAIN_MENU}, //Punkt 1 {X12, goto_menu, FOCUS_MENU, MAIN_MENU}, //Punkt 2 {X16, goto_menu, QUANTITY_MENU, MAIN_MENU}, //Punkt 3 {X24, goto_menu, TIME_MENU, MAIN_MENU}, //Punkt 4 {X32, func7, 0, 0} //Punkt 4 }; //Массив хранищий пункты меню настроек (структура SELECTION) static SELECTION menu_m0[]={ {X2, func6, 0, 0}, //Punkt 1 {X3, func6, 0, 0}, //Punkt 2 {X4, func6, 0, 0}, //Punkt 3 {X5, func6, 0, 0}, //Punkt 2 {X6, func6, 0, 0}, //Punkt 2 {X7, func6, 0, 0}, //Punkt 2 {X8, func6, 0, 0}, //Punkt 2 {X9, func6, 0, 0}, //Punkt 2 {X10, func6, 0, 0}, //Punkt 2 {X11, func6, 0, 0} //Punkt 2 }; static SELECTION menu_m1[]={ {X13, func6, 0, 0}, //Punkt 1 {X14, func6, 0, 0}, //Punkt 2 {X15, func6, 0, 0} //Punkt 3 }; static SELECTION menu_m2[]={ {X17, func6, 0, 0}, //Punkt 1 {X18, func6, 0, 0}, //Punkt 2 {X19, func6, 0, 0}, //Punkt 3 {X20, func6, 0, 0}, //Punkt 1 {X21, func6, 0, 0}, //Punkt 2 {X22, func6, 0, 0}, //Punkt 3 {X23, func6, 0, 0} //Punkt 1 }; static SELECTION menu_m3[]={ {X25, func6, 0, 0}, //Punkt 1 {X26, func6, 0, 0}, //Punkt 2 {X27, func6, 0, 0}, //Punkt 3 {X28, func6, 0, 0}, //Punkt 1 {X29, func6, 0, 0}, //Punkt 2 {X30, func6, 0, 0}, //Punkt 3 {X31, func6, 0, 0} //Punkt 1 }; //Главный массив хранит в себе все меню/подменю //Все меню/подменю должны описываться в таком же порядке как и в enum __menu__id ... static MENU menu[] = { {MAIN_MENU, 5, menu_}, //Меню 1 {DELAY_MENU, 10, menu_m0}, //Меню 2 {FOCUS_MENU, 3, menu_m1}, {QUANTITY_MENU, 7, menu_m2}, {TIME_MENU, 7, menu_m3} }; void goto_menu(void) { switch (kod) { case 'e': {current_menu=menu[current_menu].m[current_poz].ent_f; last_item=current_poz; 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_putsf("> "); lcd_puts(menu[current_menu].m[current_poz].mas); lcd_gotoxy(2,1); if (current_poz == menu[current_menu].num_selections-1) { lcd_puts(menu[current_menu].m[0].mas); // lcd_putsf("-------------------"); } else { lcd_puts(menu[current_menu].m[current_poz+1].mas); } delay_ms(100); kod='k'; } void main(void) { // Declare your local variables here // Input/Output Ports initialization // Port B initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTB=0x00; DDRB=0x00; // Port C initialization // Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out // State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0 PORTC=0x00; DDRC=0xFF; // Port D initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTD=0xFF; DDRD=0x00; // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: Timer 0 Stopped TCCR0=0x00; TCNT0=0x00; // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: Timer 1 Stopped // Mode: Normal top=FFFFh // OC1A output: Discon. // OC1B output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge // Timer 1 Overflow Interrupt: Off // Input Capture Interrupt: Off // Compare A Match Interrupt: Off // Compare B Match Interrupt: Off TCCR1A=0x00; TCCR1B=0x00; 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=0x00; // Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off ACSR=0x80; SFIOR=0x00; lcd_init(); lcd_clear(); lcd_putsf(" МИЭМ"); lcd_gotoxy(0,1); lcd_putsf(" USB частотомер"); print_menu(); while (1) { 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-1;}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 'b': { goto_menu(); current_poz=last_item; print_menu(); break; }; case 'e': { menu[current_menu].m[current_poz].function(); print_menu(); break; }; }; }; } А теперь то же самое, но для четырёх языков, русский, украинский, польский и английский.  Во! А мне приходилось наворачивать.... В принципе, ничего особенного, просто добавляются ещё вложения.
|
|
|
|
|
Feb 14 2011, 12:18
|
Группа: Новичок
Сообщений: 4
Регистрация: 14-02-11
Из: UA-RU
Пользователь №: 62 962

|
Здравствуйте! Понравилась данная реализация меню для ЖКИ. Сделал себе по такому же принципу, но нужно добавить две функции: 1. Вывод текстовой информации на ЖКИ и выход из функции по нажатию ESC. 2. Ввод значения целого числа с клавиатуры (использую клавиатуру 3х4) и выход из функции с сохранением значения по нажатию ENTER и без сохранения по ESC. Пока разбираюсь с первой функцией вывод текста и выход из неё по ESC. Делаю так: Код void func2(void) { do { LCDClear(); //очистить LCD LCDWriteString("Hello World!"); //вывод строки на LCD _delay_ms(1000); //задержка для проверки } while (key == ESC); //Для выхода - ESC } И получаеться так, что после отображения текста 1сек. меня выбрасывает в меню, хотя возврат должен происходить по нажатию ESC... Что я не так делаю?
|
|
|
|
|
Feb 15 2011, 16:57
|
Группа: Новичок
Сообщений: 9
Регистрация: 28-01-09
Из: Смоленск
Пользователь №: 44 099

|
Цитата 1. Вывод текстовой информации на ЖКИ и выход из функции по нажатию ESC. В кей по идее и остается ESC, просто перед входом в цикл обнулите кей. Цитата 1. Вывод текстовой информации на ЖКИ и выход из функции по нажатию ESC. В кей по идее и остается ESC, просто перед входом в цикл обнулите кей. Код do while (key != ESC) Выполняем цикл пока кей не равен ESC, как только кей равен, т.е. нажата кнопка ESC, выходим из цикла.
--------------------
Я электронику люблю! Возьму паяльничком пройду! В ней нет проблем и главный плюс. Мы совместимы как припой и флюс.
|
|
|
|
|
Feb 15 2011, 18:11
|
Группа: Новичок
Сообщений: 4
Регистрация: 14-02-11
Из: UA-RU
Пользователь №: 62 962

|
Цитата(Saadov @ Feb 15 2011, 19:57)  В кей по идее и остается ESC, просто перед входом в цикл обнулите кей. Saadov, спасибо, заработало как надо!  Осталось реализовать вторую функцию: Цитата 2. Ввод значения целого числа с клавиатуры (использую клавиатуру 3х4) и выход из функции с сохранением значения по нажатию ENTER и без сохранения по ESC.
|
|
|
|
|
Feb 19 2011, 22:30
|
Группа: Новичок
Сообщений: 9
Регистрация: 28-01-09
Из: Смоленск
Пользователь №: 44 099

|
Все названные функции для примера Код vvod_chisla(){
key = null; znachenie = 0;
do{
znachenie = obrabotka_knopok(); //смотрите апноут у атмела по подключению и обработке матрицы кнопок, ну или сами придумаете.
}while(key == null);
if(key == ENTER) eeprom_write( znachenie );
} Лучше не оффтопить, а создать отдельную тему в http://electronix.ru/forum/index.php?showforum=191
--------------------
Я электронику люблю! Возьму паяльничком пройду! В ней нет проблем и главный плюс. Мы совместимы как припой и флюс.
|
|
|
|
|
Dec 24 2012, 07:55
|
Группа: Новичок
Сообщений: 1
Регистрация: 24-12-12
Пользователь №: 74 955

|
Цитата(ps1x @ May 11 2010, 17:02)  Вот окончательный полностью работающий вариант меню. Спасибо за код,в Протеусе посмотрел,всё-ОК Теперь,извините меня за тупость  , обьясните пожалуйста, как связать это с реальной жизнью, т.е. как менять свои переменные связав их именно с нужными пунктами и значениями меню.
|
|
|
|
|
Nov 10 2014, 11:40
|
Группа: Новичок
Сообщений: 7
Регистрация: 13-05-12
Пользователь №: 71 815

|
Разобрался с меню. Но при размещении большого количества структур забилась вся оперативная память. И встал вопрос о размещении структур в флешь памяти. CODE ...
//Структура описывает пункт меню 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; ... //Массив хранищий пункты главного меню (структура SELECTION) static SELECTION menu_[]={ {X1, goto_menu, DELAY_MENU, MAIN_MENU}, //Punkt 1 {X12, goto_menu, FOCUS_MENU, MAIN_MENU}, //Punkt 2 {X16, goto_menu, QUANTITY_MENU, MAIN_MENU}, //Punkt 3 {X24, goto_menu, TIME_MENU, MAIN_MENU}, //Punkt 4 {X32, func7, 0, 0} //Punkt 4 };
//Массив хранищий пункты меню настроек (структура SELECTION) static SELECTION menu_m0[]={ {X2, func6, 0, 0}, //Punkt 1 {X3, func6, 0, 0}, //Punkt 2 {X4, func6, 0, 0}, //Punkt 3 {X5, func6, 0, 0}, //Punkt 2 {X6, func6, 0, 0}, //Punkt 2 {X7, func6, 0, 0}, //Punkt 2 {X8, func6, 0, 0}, //Punkt 2 {X9, func6, 0, 0}, //Punkt 2 {X10, func6, 0, 0}, //Punkt 2 {X11, func6, 0, 0} //Punkt 2 }; ... Так вот, кто-нибудь размещал эти структуры во флешь памяти?
Сообщение отредактировал IgorKossak - Dec 5 2014, 19:23
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
|
|
|
|
|
Dec 5 2014, 19:30
|
Местный
  
Группа: Участник
Сообщений: 333
Регистрация: 19-12-13
Из: Новосибирск
Пользователь №: 79 709

|
Как-то так: menu.h: CODE //======================================================================== #ifndef MENU_H
#define MENU_H
#include "menu.h" //========================================================================
//======================================================================== #include <pgmspace.h> #include <stdbool.h>
#include "avrlibtypes.h" #include "kbd_drv.h" //========================================================================
//======================================================================== // Typedefs: typedef void (*FuncPtr)(void); //========================================================================
//======================================================================== typedef struct menu_item { void *Parent; void *Child; void *Next; void *Prev; FuncPtr NumFunc; FuncPtr EnterFunc; FuncPtr MenuFunc; char Text[20]; } menu_item; //========================================================================
// Externs: //======================================================================== extern menu_item __flash *CurrMenuItem; // Текущий пункт меню. extern menu_item __flash *BeginCurrMenuLevel; // Начало массива текущего уровня меню.
extern __flash menu_item Null_Menu;
extern char Menu_Str_Buf []; // Буфер для вывода текста.
extern void (*MenuFuncPtr)(void); //========================================================================
// Defines and Macros: //======================================================================== #define NULL_ENTRY Null_Menu #define NULL_FUNC (void*)0 #define NULL_TEXT 0x00 #define PAGE_MENU 3 //========================================================================
//======================================================================== #define MAKE_MENU(Name, Parent, Child, Next, Prev, NumFunc, EnterFunc, MenuFunc, Text) \ extern menu_item __flash Parent; \ extern menu_item __flash Child; \ extern menu_item __flash Next; \ extern menu_item __flash Prev; \ menu_item __flash Name \ { \ (menu_item*) &Parent, \ (menu_item*) &Child, \ (menu_item*) &Next, \ (menu_item*) &Prev, \ NumFunc, \ EnterFunc, \ MenuFunc, \ {Text} \ } //========================================================================
//======================================================================== #define PARENT *((menu_item __flash*) (CurrMenuItem->Parent)) #define CHILD *((menu_item __flash*) (CurrMenuItem->Child)) #define NEXT *((menu_item __flash*) (CurrMenuItem->Next)) #define PREV *((menu_item __flash*) (CurrMenuItem->Prev)) #define NUM_FUNC *((FuncPtr) (CurrMenuItem->NumFunc)) #define ENTER_FUNC *((FuncPtr) (CurrMenuItem->EnterFunc)) #define MENU_FUNC *((FuncPtr) (CurrMenuItem->MenuFunc)) //========================================================================
//======================================================================== #define SET_MENU_LEVEL(x) \ Set_Menu_Level(&x)
#define SET_MENU_ITEM(x) \ Set_Menu_Item(&x) #define GO_MENU_FUNC(x) \ MenuFunc((FuncPtr*)&x) #define EXTERN_MENU(Name) \ extern menu_item __flash Name; //========================================================================
//======================================================================== enum { SET_LEVEL = 0, SET_NEXT, SET_PREV, }; //========================================================================
// Prototypes: //======================================================================== void Set_Menu_Level (menu_item __flash *NewMenu); void Set_Menu_Item (menu_item __flash *NewMenu); void MenuFunc(FuncPtr* Function); //========================================================================
//======================================================================== EXTERN_MENU (L_OUT_MODE); //========================================================================
//======================================================================== void Out_Menu_Items_Init (void); void Out_Menu_Items (void); //========================================================================
//======================================================================== bool proc_menu_keys (void); //========================================================================
//======================================================================== void out_name_level (void); u08 count_chars (char __flash *data); void make_page_menu (void); void inc_pos_y_curs (void); void dec_pos_y_curs (void); void set_pos_curs (void); //========================================================================
#endif menu.c: CODE //======================================================================== #include "menu.h" //========================================================================
//======================================================================== static u08 quant_items; static u08 pos_y_curs; //========================================================================
//======================================================================== ============================================================== menu_item __flash *CurrMenuItem; // Текущий пункт меню.
menu_item __flash *BeginCurrMenuLevel; // Начало массива текущего уровня меню.
menu_item __flash *temp_menu;
menu_item __flash Null_Menu = {(void*)0, (void*)0, (void*)0, (void*)0, NULL_FUNC, NULL_FUNC, NULL_FUNC, {NULL_TEXT}};
void (*MenuFuncPtr)(void); //======================================================================== ==============================================================
//======================================================================== void Set_Menu_Level (menu_item __flash *NewMenu) { if ((void*)NewMenu == (void*)&NULL_ENTRY) return;
CurrMenuItem = NewMenu;
Out_Menu_Items_Init (); // Так как новый уровень, инициализация переменных. Out_Menu_Items (); // Вывод названия уровня меню и пунктов меню, курсора.
GO_MENU_FUNC (ENTER_FUNC); } //========================================================================
//======================================================================== void Set_Menu_Item (menu_item __flash *NewMenu) { if ((void*)NewMenu == (void*)&NULL_ENTRY) return;
CurrMenuItem = NewMenu;
Out_Menu_Items (); // Вывод названия уровня меню и пунктов меню, курсора.
GO_MENU_FUNC (ENTER_FUNC); } //========================================================================
//======================================================================== void MenuFunc (FuncPtr* Function) { if ((void*) Function == (void*) NULL_FUNC) return;
((FuncPtr) Function)(); } //========================================================================
//======================================================================== bool proc_menu_keys (void) { bool a = false; u08 key;
if (Get_Event (EV_ID_KEY_PRESSED)) { key = GetKeyCode ();
switch (key) { case KEY_ESC_COD: SET_MENU_LEVEL (PARENT); a = true; break;
case KEY_ENTER_COD: SET_MENU_LEVEL (CHILD); a = true; break;
case KEY_NEXT_COD: inc_pos_y_curs (); SET_MENU_ITEM (NEXT); a = true; break;
case KEY_PREV_COD: dec_pos_y_curs (); SET_MENU_ITEM (PREV); a = true; break;
default: break; }
if (key < 10) { GO_MENU_FUNC (NUM_FUNC); // Сервисные меню. Ввод числовых параметров. a = true; } }
if (a) return true; else return false; } //========================================================================
/* Уровни, пункты, текст - все выводится автоматом. Так как все переходы по меню расписаны в структуре, то отпадает надобность в запоминании перемещений по меню. */
//======================================================================== void Out_Menu_Items_Init (void) { quant_items = 1; pos_y_curs = 1;
// Получение адреса начала массива уровня меню. BeginCurrMenuLevel = CurrMenuItem; temp_menu = (menu_item __flash *)(CurrMenuItem->Prev);
while (1) { if ((void*)temp_menu == (void*)&NULL_ENTRY) { break; } else { BeginCurrMenuLevel = temp_menu; temp_menu = (menu_item __flash *)(temp_menu->Prev); } }
// Получение количества пунктов меню. temp_menu = (menu_item __flash *)(BeginCurrMenuLevel->Next);
while (1) { if ((void*)temp_menu == (void*)&NULL_ENTRY) { break; }
temp_menu = (menu_item __flash *)(temp_menu->Next); quant_items++; }
// Позиция курсора. if (quant_items > 1) { temp_menu = BeginCurrMenuLevel;
while (1) { if ((void*)temp_menu == (void*)&NULL_ENTRY) return;
if (temp_menu == CurrMenuItem) return; else pos_y_curs++;
temp_menu = (menu_item __flash *)(temp_menu->Next); } } }
void Out_Menu_Items (void) { clr_dsp_buf ();
out_name_level (); // Вывод названия уровня меню.
make_page_menu (); // Вывод пунктов меню.
set_pos_curs (); // Установка позиции и вывод курсора. } //========================================================================
//======================================================================== // Вывод названия уровня меню. void out_name_level (void) { temp_menu = (menu_item __flash *)(CurrMenuItem->Parent); // Считывание названия уровня меню из пункта меню в верхнем уровне.
if ((void*)temp_menu != (void*)&NULL_ENTRY) { char __flash *data = temp_menu->Text;
u08 i = count_chars (data); // Подсчет кол-ва символов в строке.
// Выравнивание текста посередине строки дисплея.
u08 a = i;
i = (20 - i); // Дисплей 20x4. Отнимаем от 20 число символов.
i >>= 1; // Делим остаток на 2.
if (a & (1<<0)) i += 2; // Если число нечетное. else i++; // Если число четное.
Print_Buf (1, i, temp_menu->Text); } } //========================================================================
//======================================================================== // Подсчет кол-ва символов в строке. u08 count_chars (char __flash *data) { u08 i = 0;
while (data [i]) { i++; } return i; } //========================================================================
//======================================================================== void make_page_menu (void) { signed char tmp_pos_y_curs; u08 i; // Счетчик страниц. u08 j; // Страница меню.
if (quant_items > 1) // Если пунктов меню больше 1, значит есть что выводить. { temp_menu = BeginCurrMenuLevel;
if (pos_y_curs > PAGE_MENU) { tmp_pos_y_curs = pos_y_curs;
i = 0; // Счетчик страниц.
while (tmp_pos_y_curs > 0) { tmp_pos_y_curs -= PAGE_MENU; i++; } tmp_pos_y_curs += PAGE_MENU;
j = PAGE_MENU; // Страница меню.
while (i-- > 1) { while (j--) { temp_menu = (menu_item __flash *)(temp_menu->Next); // Следующий пункт меню. } j = PAGE_MENU; // Страница меню. } }
u08 pos_y_text_item = 2; // j = PAGE_MENU; // Страница меню.
while (j--) { Print_Buf (pos_y_text_item, 2, temp_menu->Text); // вывод названия пункта меню.
temp_menu = (menu_item __flash *)(temp_menu->Next); // Следующий пункт меню.
if ((void*)temp_menu == (void*)&NULL_ENTRY) // Если элемент Next return; // пустой, то выход. else pos_y_text_item++; } } } //========================================================================
//======================================================================== void inc_pos_y_curs (void) { if (quant_items > 1) { if (pos_y_curs < quant_items) pos_y_curs++; } }
void dec_pos_y_curs (void) { if (quant_items > 1) { if (pos_y_curs > 1) pos_y_curs--; } } //========================================================================
//======================================================================== void set_pos_curs (void) { if (quant_items > 1) { signed char tmp = pos_y_curs;
while (tmp > 0) { tmp -= PAGE_MENU; }
if (tmp <= 0) tmp += PAGE_MENU;
PrintChar (tmp + 1, 1, ARROW_RIGHT); } } //======================================================================== Пример использования: Где-то создаем точку входа в меню: Код SET_MENU_LEVEL (YOU_MENU); Где-то делаем опрос клавиатуры и где-то проверяем, было ли событие клавиатуры: Код if (proc_menu_keys ()) return; Пример меню: Код // NAME PARENT CHILD NEXT PREV NUM_FUNCE ENTER_FUNC MENU_FUNC TEXT MAKE_MENU (ITEM_1, NULL_ENTRY, NULL_ENTRY, ITEM_2, NULL_ENTRY, NULL_FUNC, NULL_FUNC, NULL_FUNC, "ПУНКТ 1"); MAKE_MENU (ITEM_2, NULL_ENTRY, NULL_ENTRY, ITEM_3, ITEM_1, NULL_FUNC, NULL_FUNC, NULL_FUNC, "ПУНКТ 2"); MAKE_MENU (ITEM_3, NULL_ENTRY, NULL_ENTRY, ITEM_4, ITEM_2, NULL_FUNC, NULL_FUNC, NULL_FUNC, "ПУНКТ 3"); MAKE_MENU (ITEM_4, NULL_ENTRY, SUBITEM_1, NULL_ENTRY, ITEM_3, NULL_FUNC, NULL_FUNC, NULL_FUNC, "ПУНКТ 4");
MAKE_MENU (SUBITEM_1, ITEM_4, NULL_ENTRY, SUBITEM_2, NULL_ENTRY, NULL_FUNC, NULL_FUNC, NULL_FUNC, "ПОДПУНКТ 1"); MAKE_MENU (SUBITEM_2, ITEM_4, NULL_ENTRY, SUBITEM_3, SUBITEM_1, NULL_FUNC, NULL_FUNC, NULL_FUNC, "ПОДПУНКТ 2"); MAKE_MENU (SUBITEM_3, ITEM_4, NULL_ENTRY, SUBITEM_4, SUBITEM_2, NULL_FUNC, NULL_FUNC, NULL_FUNC, "ПОДПУНКТ 3"); MAKE_MENU (SUBITEM_4, ITEM_4, NULL_ENTRY, NULL_ENTRY, SUBITEM_4, NULL_FUNC, NULL_FUNC, NULL_FUNC, "ПОДПУНКТ 4"); Так как используется структура, нет надобности в запоминании навигации по меню. Вся информация в структуре. Видео пробного проекта меню
Сообщение отредактировал IgorKossak - Dec 5 2014, 19:29
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
|
|
|
|
|
Mar 16 2015, 09:58
|
Группа: Новичок
Сообщений: 5
Регистрация: 16-03-15
Пользователь №: 85 692

|
Здравствуйте уважаемые Хочу воскресить темку т.к. форум не даёт отправлять личные сообщения ..... почемуто Очень нужно сделать своё меню, не хочу использовать МикроМеню а тут относительно просто всё и понятно. Но запустить не получается... Точнее меню ТС запустил, но в конце темы уважаемый demiurg1978 показал чтото очень хорошее ). Юзаю CodeVisionAVR 3.12 Так вот эта штука у меня не взлетает 1. avrlibtypes.h нашёл такую библиотеку но там используются х64 (long long) я просто закоментил строки в данной библиотеке. 2. SET_MENU_LEVEL (YOU_MENU); что такое YOU_MENU ? как создать ? 3. Любая строка из примера (MAKE_MENU (ITEM_1, NULL_ENTRY, NULL_ENTRY, ITEM_2, NULL_ENTRY, NULL_FUNC, NULL_FUNC, NULL_FUNC, "ПУНКТ 1") даёт непонятную мне ошибку "Error: C:\Project\IntKeyNew\intkey.c(83): storage modifier not allowed in this context" Не пинайте сильно учусь только ещё Спасибо за ваше время и ответы
Сообщение отредактировал binarick - Mar 16 2015, 09:59
|
|
|
|
|
Mar 30 2018, 21:47
|
Группа: Новичок
Сообщений: 1
Регистрация: 30-03-18
Пользователь №: 102 785

|
Цитата(ut1wpr @ May 12 2010, 10:21)  А теперь то же самое, но для четырёх языков, русский, украинский, польский и английский.  Во! А мне приходилось наворачивать.... В принципе, ничего особенного, просто добавляются ещё вложения. приветствую. тут есть кто нибудь? не могу разобраться с кодом.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|