ATmega32_LED_MENU

A co třeba nějak takhle …

Definice typů a proměnných

[code]typedef struct // Položka menu
{
char *ItemText; // Text položky, pokud není definovaná programově generovaná položka.
void (*UserPaintLine)(void); // Programově generovaný text položky (třeba položka obsahující v textu nastavovanou hodnotu)
void *OnEnterKey; // Které menu se má zobrazit při krátkém stisku Enter.
void *OnLongEnterKey; // Které menu se má zobrazit při dlouhém stisku Enter.
void (*OnEnterCall)(void); // Funkce, která se zavolá při stisku Enter.
} MenuItemStruct;

typedef struct // Struktura menu
{
unsigned char ItemCount; // Počet položek
unsigned char ItemIndex; // Index vybrané položka
char *MenuLabel; // Záhlaví menu
void *OnEscapeKey; // Nadřazené menu (NULL = žádné)
void *OnLongEscapeKey; // Dlouhý stisk Escape (NULL = žádné)
MenuItemStruct MenuItem[4]; // Položky menu (počet položek odpovídá nejdelšímu menu
unsigned char TopIndex; // Index (0…x) první zobrazené položky (pro scrolování menu)
} MenuStruct;

MenuStruct *ActiveMenu; // Pointer na proměnnou aktuálně zobrazeného menu (NULL = žádné menu nezobrazeno)
[/code]

Zobrazovací rutina

[code]void UserMenu( void )
{
if (ActiveMenu!=NULL)
{
char Line = 0;

	if ( ActiveMenu->MenuLabel != NULL )
	{
		LCD_GotoXY(Line++, 0);
		LCD_Write_PM_String(ActiveMenu->MenuLabel);
	}

	volatile char PrintedMenuLine=ActiveMenu->TopIndex ;
	
	while((Line < 4)&&(PrintedMenuLine < ActiveMenu->ItemCount ))
	{
		if ( ActiveMenu->MenuItem[PrintedMenuLine].UserPaintLine != NULL )
		{
			LCD_GotoXY(Line++, 1);
			ActiveMenu->MenuItem[PrintedMenuLine].UserPaintLine();
		}
		else
		{
			if ( ActiveMenu->MenuItem[PrintedMenuLine].ItemText != NULL )
			{
				LCD_GotoXY(Line++, 1);
				LCD_Write_PM_String(ActiveMenu->MenuItem[PrintedMenuLine].ItemText);
			}
		}
		if ( PrintedMenuLine == ActiveMenu->ItemIndex )
		{
			LCD_GotoXY(Line-1, 0);
			LCD_Data = 0;
			LCD_Write_Data();
		}
		PrintedMenuLine++;
	}

}

}
[/code]

Hlavní program

// Deklarace textů položek menu.
const PROGMEM char MenuItemText][17] = {\
											"  Hlavni menu   ", "Polozka hl. 1  ", "Polozka hl. 2  ", "Polozka hl. 3  ", \
											"  Podmenu 1     ", "Polozka pm. 1-1", "Polozka pm. 1-2", "Polozka pm. 1-3", \
											"  Podmenu 2     ", "Polozka pm. 2-1", "Polozka pm. 2-2", "Polozka pm. 2-3", \
											"Polozka pm. 2-4", "Polozka pm. 3-1", "Polozka pm. 3-2", "Polozka pm. 3-3"  \
										};

MenuStruct HlavniMenu, Podmenu1, Podmenu2;	// Deklarace tří menu

int main(void)
{

// Nastavit hlavní menu	
	HlavniMenu.ItemIndex = 0;
	HlavniMenu.ItemCount = 2;
	HlavniMenu.MenuLabel = MenuItemText[0];
	HlavniMenu.MenuItem[0].ItemText = MenuItemText[1];
	HlavniMenu.MenuItem[1].ItemText = MenuItemText[2];
	HlavniMenu.MenuItem[2].ItemText = MenuItemText[3];
	HlavniMenu.MenuItem[0].OnEnterKey = &Podmenu1;
	HlavniMenu.MenuItem[1].OnEnterKey = &Podmenu2;
	
// Nastavit podmenu 1
	Podmenu1.ItemIndex = 0;
	Podmenu1.ItemCount = 2;
	Podmenu1.MenuLabel = MenuItemText[4];
	Podmenu1.MenuItem[0].ItemText = MenuItemText[5];
	Podmenu1.MenuItem[0].UserPaintLine = NapisTestovaciRadekMenu;
	Podmenu1.MenuItem[1].ItemText = MenuItemText[6];
	Podmenu1.MenuItem[2].ItemText = MenuItemText[7];
	Podmenu1.OnEscapeKey = &HlavniMenu;
	
// Nastavit podmenu 2
	Podmenu2.ItemIndex = 0;
	Podmenu2.ItemCount = 4;
	Podmenu2.MenuLabel = MenuItemText[8];
	Podmenu2.MenuItem[0].ItemText = MenuItemText[9];
	Podmenu2.MenuItem[1].ItemText = MenuItemText[10];
	Podmenu2.MenuItem[2].ItemText = MenuItemText[11];
	Podmenu2.MenuItem[3].ItemText = MenuItemText[12];
	Podmenu2.OnEscapeKey = &HlavniMenu;
	
// Zvolit hlavní menu
	ActiveMenu = &HlavniMenu;
	
// Zobrazit zvolené menu
	UserMenu();

.
.
.
.
.

Zobrazovací rutina i obsluha vstupů (tlačítka, rotační koder, dotykový panel atd.) je společná pro všechna menu. Přepínání jednotlvých menu se děje jenom přepnutím jednoho pointeru.

Psané je to v Atmel Studiu 7.