Если меню имеет несколько пунктов, то это обычно называю SubMenu. Значение этой переменной определяет номер текущего пункта меню и учитывается при отрисовке меню. Текущий пункт рисую инверсным или со стрелочкой. Как пример, меню калибровки генератора SG-642, используется графический ЖКИ:
void Mnu_Calib(bool ini)
{
static char __flash Mnu_StrS[] = {"CALIB"};
static char __flash Mnu_StrM[] = {"Frequency:\n"
"Level A :\n"
"Level B :\n"
"Save :\n"
"Exit :"};
if(ini) //если требуется прорисовка, то
{
//вывод текста меню:
LCD_Clear(); //очистка дисплея
LCD_Inv(1); //включение инверсии
LCD_PutString(Mnu_StrS); //вывод CALIB
LCD_Inv(0); //выключение инверсии
LCD_SetLinPos(2, 1); //установка координаты для текста меню
LCD_PutString(Mnu_StrM); //вывод текста меню
//вывод параметров:
Show_Calib(CAL_F); //калибровка частоты
Show_Calib(CAL_A); //калибровка уровня A
Show_Calib(CAL_B); //калибровка уровня B
Show_Calib(CAL_S); //сохранение калибровки
Show_Calib(CAL_E); //выход из калибровки
LCD_Update(); //обновление дисплея
BuffK = Control_GetK(SubMenu); //загрузка калибровочного коэффициента
DispMenu = Menu; //снятие требования прорисовки
}
//кнопка "CHAN":
if(KeyCode == KEY_CHAN)
{
Control_ReadCal(); //чтение старой калибровки из EEPROM
ApplyK(Control_GetK(CAL_F), CAL_F); //обновление частоты каналов A и B
ApplyK(Control_GetK(CAL_A), CAL_A); //обновление амплитуды канала A
ApplyK(Control_GetK(CAL_B), CAL_B); //обновление амплитуды канала B
Menu = RetMenu; //возврат
Sound_Beep(); //beep
KeyCode = KEY_NO; //кнопка обработана
}
//кнопка "UP":
if((KeyCode & ~REP) == KEY_UP)
{
if(SubMenu > 0) SubMenu--; //предыдущий параметр
else SubMenu = CAL_MAX - 1;
DispMenu = MNU_NO; //требование перерисовки меню
Sound_Tick(); //короткий звуковой сигнал
KeyCode = KEY_NO; //кнопка обработана
}
//кнопка "DN":
if((KeyCode & ~REP) == KEY_DN)
{
if(SubMenu < CAL_MAX - 1) SubMenu++; //следующий параметр
else SubMenu = 0;
DispMenu = MNU_NO; //требование перерисовки меню
Sound_Tick(); //короткий звуковой сигнал
KeyCode = KEY_NO; //кнопка обработана
}
//вращение энкодера вправо
if(KeyCode == KEY_EUP)
{
if(BuffK < MAX_CALIB)
{
BuffK++;
ApplyK(BuffK, SubMenu);
Show_Calib(SubMenu); //вывод параметра
LCD_Update(); //обновление дисплея
KeyCode = KEY_NO; //кнопка обработана
}
}
//вращение энкодера влево
if(KeyCode == KEY_EDN)
{
if(BuffK > MIN_CALIB)
{
BuffK--;
ApplyK(BuffK, SubMenu);
Show_Calib(SubMenu); //вывод параметра
LCD_Update(); //обновление дисплея
KeyCode = KEY_NO; //кнопка обработана
}
}
//кнопка энкодера:
if(KeyCode == KEY_ESB)
{
if(SubMenu != CAL_S)
{
Control_ReadCal(); //чтение старой калибровки из EEPROM
ApplyK(Control_GetK(CAL_F), CAL_F); //обновление частоты каналов A и B
ApplyK(Control_GetK(CAL_A), CAL_A); //обновление амплитуды канала A
ApplyK(Control_GetK(CAL_B), CAL_B); //обновление амплитуды канала B
Sound_Beep(); //beep
Menu = RetMenu; //возврат
}
KeyCode = KEY_NO; //кнопка обработана
}
//удержание кнопки энкодера:
if(KeyCode == (KEY_ESB | REP))
{
if(SubMenu == CAL_S)
{
Sound_High(); //звуковой сигнал сохранения
Control_SaveCal(); //сохранение калибровки
Menu = RetMenu; //возврат
KeyCode = KEY_NO; //кнопка обработана
}
}
}