Перейти к содержанию
    

Отображение меню на жк

для собственно TUI опрос кнопок без разницы :) но скажите мне, где это может помешать?!

 

у меня меню так же на основе структур, только я отказался от связного списка, в пользу массивов, как раз из-за простоты восприятия. плюс в списке надо хранить ссылки на следующего-предыдущего-корневого, а для массива не надо - FLASH экономится :)

 

а разобраться сложно - так можно и не разбираться, достаточно интерфейс понять :) описание системы меню не сложнее, чем у MicroMenu - так же при помощи макросов, единственное, до чего я не догнал сразу - так это определить сразу тип для структуры в PROGMEM, и пришлось извращаться с предварительным описанием текстовых строк в виде констант.

 

MicroMenu весьма лаконично - признаю. у меня более путано - да. не стремился к суперлаконичности, старался больше вариантов охватить :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

да согласен код слишком запутаный, как то реолизовал нечто подобное. вопервых можно все масивы вынести во флеш, ОЗУ сильно секономит, вовторых с нажатием кнопок несовсем понял фиксация по временной задержке, непрощели одно нажатие одно срабатывание
согласен с чем? ;) все массивы и так во FLASH :) и кнопки именно так: одно нажатие - одно срабатывание. но предусмотрен случай автоповтора при длительном нажатии (у меня в TUI).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Недавно переделал 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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот окончательный полностью работающий вариант меню.

/*****************************************************
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.com
e-mail:[email protected]

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;
   };
   };
     };

}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот окончательный полностью работающий вариант меню.

/*****************************************************
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.com
e-mail:[email protected]

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;
   };
   };
     };

}

А теперь то же самое, но для четырёх языков, русский, украинский, польский и английский. :)

Во! А мне приходилось наворачивать.... В принципе, ничего особенного, просто добавляются ещё вложения.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Здравствуйте! Понравилась данная реализация меню для ЖКИ. Сделал себе по такому же принципу, но нужно добавить две функции:

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... Что я не так делаю?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1. Вывод текстовой информации на ЖКИ и выход из функции по нажатию ESC.

В кей по идее и остается ESC, просто перед входом в цикл обнулите кей.

 

1. Вывод текстовой информации на ЖКИ и выход из функции по нажатию ESC.

В кей по идее и остается ESC, просто перед входом в цикл обнулите кей.

do
while (key != ESC)

 

Выполняем цикл пока кей не равен ESC, как только кей равен, т.е. нажата кнопка ESC, выходим из цикла.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В кей по идее и остается ESC, просто перед входом в цикл обнулите кей.

Saadov, спасибо, заработало как надо! :)

 

Осталось реализовать вторую функцию:

2. Ввод значения целого числа с клавиатуры (использую клавиатуру 3х4) и выход из функции с сохранением значения по нажатию ENTER и без сохранения по ESC.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Все названные функции для примера

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот окончательный полностью работающий вариант меню.

 

Спасибо за код,в Протеусе посмотрел,всё-ОК :rolleyes:

Теперь,извините меня за тупость :01: , обьясните пожалуйста, как связать это с реальной жизнью, т.е. как менять свои переменные связав их именно с нужными пунктами и значениями меню. :help:

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Разобрался с меню. Но при размещении большого количества структур забилась вся оперативная память. И встал вопрос о размещении структур в флешь памяти.

...

//Структура описывает пункт меню
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
[codebox] для длинного кода, [code] - для короткого!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как-то так:

 

menu.h:

//========================================================================
#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:

//========================================================================
#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
[codebox] для длинного кода, [code] - для короткого!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Здравствуйте уважаемые

Хочу воскресить темку т.к. форум не даёт отправлять личные сообщения ..... почемуто

Очень нужно сделать своё меню, не хочу использовать МикроМеню а тут относительно просто всё и понятно.

 

Но запустить не получается... Точнее меню ТС запустил, но в конце темы уважаемый 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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А теперь то же самое, но для четырёх языков, русский, украинский, польский и английский. :)

Во! А мне приходилось наворачивать.... В принципе, ничего особенного, просто добавляются ещё вложения.

 

приветствую. тут есть кто нибудь? не могу разобраться с кодом.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...