А у меня есть штурвал, кусок доски и яхтный лак. Поможешь яхту сделать? Тебе в закажу проект. Там бывает бесплатно делают.
А Вы считывать энкодер умеете? Если да... то в чём проблема вообще? Вы же сказали "помочь с кодом" т.е. подсказать...
"помочь" означает, что большую часть работы сделаете вы сами, а мы лишь поможем. Ну, типа, когда напишете 90% меню - приходите, подскажем, как написать остальное... А у вас пока просьба "сделайте за меня" - так что аналогия с яхтой очень даже к месту.
Ну так инкрементируйте и декрементируйте значение номера меню в зависимости от направления поворота энкодера да и анализируйте типа: Код (C++): ... int num; //номер меню - определено где-то и энкодером изменяется в + и в - switch(num) { case 1: //меню 1 .... //формируете меню 1 break; case 2: ....//формируете меню 2 break; .... //для остальных мню default: //а тут можете сделать "закольцовку" или ограничение break; } ... //далее выводите готовое меню ... И что помогать-то?
Присоединяюсь к тем, кто уже написал, вопрос не понятен. Как помочь? Могу скинуть свой обработчик действий для меню и подменю. Но ведь все равно придется разбираться. Готовое, под конкретную задачу, ведь все равно только в закажу проект. Писал для термостата на Меге 8, лет 10 назад. На первом уровне меню показываются: текущее значение температуры, плюсом/минусом можно прибавить убавить значение термостата. Enter позволяет листать: максимум, минимум температуры с временем и датой; максимум, минимум напряжения питания, время работы нагревателя. Их можно сбросить удержав + и -. При длительном удержании кнопки "Enter" попадаем в подменю. Там задаются дополнительные параметры типа: контрастность, яркость подсветки, гистерезис термостата, температуру режима "анти заморозки", адрес RS-485, разрешение выключения подсветки с диммированием при отсутствии нажатия кнопок. Файл <menu.c>: Код (C++): // SubMenu #define KEY_1 2 // Back #define KEY_2 3 // Enter #define KEY_3 0 // UP #define KEY_4 1 // Down #define KEY_5 5 // Power typedef struct _menuItem { // Структура подменю char flash * itemText; // Текст signed char * Cur_Val; // Указатель на значение signed char Esc_Val; // Значение в случае выхода без изменений signed char Min_Val; // Минимально возможное значение signed char Max_Val; // Максимально возможное значение signed char * eep_addr; // Адрес для сохранения значения в EEPROM_WRITE void (*itemFunction)(void); // Функция вызываемая для обработки нового значения. } MenuItem; void MenuProcess(char key); void MenuOpen(void); void MenuClose(void); static flash char _Contrast_str[] = "Contrast", _Backlight_str[] = "LED Ligh", _Gisteresis_str[] = "Gisteres", _NetAddr_str[] = "Net Addr", _AntiFrTemp_str[] = "AF Temp.", _AntiFrOnOff_str[] = " A.F.On ", _KeyBeepOnOff_str[] = "Key Beep", _AutoDimOnOff_str[] = "Auto Dim", _Date_Year_str[] = " Year ", _Date_Month_str[] = " Month ", _Date_Day_str[] = " Day ", _Time_Hour_str[] = " Hour ", _Time_Min_str[] = " Minute " ; void Key_1_1(void) { Mode=0; } void Key_1_2(void) { if (Heating_ON_OFF==HEATING_ON) Heating_ON_OFF=HEATING_OFF; else Heating_ON_OFF=HEATING_ON; ChangeDataFlag|=CHG_TERMOSTAT; EEPROM_WRITE((int)&eep_Heating_ON_OFF, Heating_ON_OFF); } void Key_2_1(void) { if (Mode<NUM_OF_MODE-1) Mode++; else Mode=0; ChangeDataFlag|=CHG_MENUMODE; } void Key_2_2(void) { if (Mode>0) Mode--; else Mode=NUM_OF_MODE-1; MenuOpen(); // активизируем подменю установок ChangeDataFlag|=CHG_MENUMODE; } void Key_3_1(void) { if (Mode==0 && Heating_ON_OFF == HEATING_ON) IncTermostatVal(); } void Key_4_1(void) { if (Mode==0 && Heating_ON_OFF == HEATING_ON) DecTermostatVal(); } void Key_4_2(void) { switch(Mode) { case 1: TempMinVal=125; // сбросим минимальное значение температуры break; case 2: TempMaxVal=-55; // сбросим максимальное значение температуры break; case 3: Min_Voltage=Cur_Voltage; // сбросим минимальное значение напряжения Max_Voltage=Cur_Voltage; // сбросим максимальное значение напряжения break; case 4: HeaterTime.Year=0; // сбросим время наработки нагревателя HeaterTime.Month=0; HeaterTime.Day=0; HeaterTime.Hour=0; HeaterTime.Min=0; HeaterTime.Sec=0; break; } } //MainMenu обработчики кнопок элемент 0 - короткое нажатие, 1 - длинное нажатие. void (*MMFTab[5][2])(void)= { {Key_3_1, NULL}, {Key_4_1, Key_4_2}, {Key_1_1, Key_1_2}, {Key_2_1, Key_2_2}, {Key_1_2, NULL} }; void SetContrast(void) { OCR1AL=(Contrast*5)+155; // при 20 в OCR1AL заносим 255 } void SetBacklight() { OCR1BL =((21-LED)*12)+3; // при 0 в OCR1BL заносим 255 } void SetTime() { // После установки времени сбросим макс и мин температуры. TempMinVal=125; TempMaxVal=-55; } void SetTimeMin() { CurTime.Sec=0; SetTime(); } static MenuItem MenuItems[] = { _Contrast_str, &Contrast, 0,0, 20, &eep_Contrast, &SetContrast, _Backlight_str, &LED, 0,0, 20, &eep_LED, &SetBacklight, _Gisteresis_str, &Gister, 0,0, 10, &eep_Gister, NULL, _NetAddr_str, &NetAddr, 0,2, 99, &eep_NetAddr, NULL, _AntiFrTemp_str, &AntiFrTemp, 0,0, 20, &eep_AntiFrTemp, NULL, _AntiFrOnOff_str, &AntiFrOnOff, 0,0, 1, &eep_AntiFrOnOff, NULL, _KeyBeepOnOff_str,&KeyBeepOnOff, 0,0, 1, &eep_KeyBeepOnOff, NULL, _AutoDimOnOff_str,&AutoDimOnOff, 0,0, 1, &eep_AutoDimOnOff, NULL, _Date_Year_str, &CurTime.Year, 0,1, 99, NULL, &SetTime, _Date_Month_str, &CurTime.Month, 0,1, 12, NULL, &SetTime, _Date_Day_str, &CurTime.Day, 0,1, 31, NULL, &SetTime, _Time_Hour_str, &CurTime.Hour, 0,0, 23, NULL, &SetTime, _Time_Min_str, &CurTime.Min, 0,0, 59, NULL, &SetTimeMin, }; MenuItem *_mptr = MenuItems; MenuItem *_mptr_choiced = NULL; unsigned char SubMenu_choiced = 0; void MenuOpen(void) { SubMenu_choiced=1; _mptr_choiced = NULL; } void MenuClose(void) { Mode=0; SubMenu_choiced=0; _mptr_choiced = NULL; } void MainMenuProcess(char key) { unsigned char num=Key_Mode[key]; void (*function)(void); ChangeDataFlag |= CHG_MENUMODE; function=MMFTab[key][num-1]; if (*function) (*function)(); } void MenuProcess(char key) { ChangeDataFlag |= CHG_MENUMODE; switch (key) { case KEY_1: // Key 1 presed (назад) if(_mptr_choiced) // выход в подменю из выбранного пункта { *(_mptr->Cur_Val) = _mptr->Esc_Val; if(_mptr->itemFunction) (*_mptr->itemFunction)(); _mptr_choiced = NULL; } else if (SubMenu_choiced) // выход из меню устоновок в idle { MenuClose(); } break; case KEY_2: // Key 2 presed (выбор) if(_mptr_choiced) // принимаем значение и выходим { if (_mptr->itemFunction) (*_mptr->itemFunction)(); if (_mptr->eep_addr) EEPROM_WRITE((int)(_mptr->eep_addr), *(_mptr->Cur_Val)); _mptr_choiced = NULL; } else if (SubMenu_choiced) // Переходим в подменю изменения параметра { _mptr_choiced = _mptr; _mptr->Esc_Val= *(_mptr->Cur_Val); } break; case KEY_3: // Key 2 presed (+) if(_mptr_choiced) // увеличиваем значение параметра (если еще можно) { if (*(_mptr->Cur_Val) < _mptr->Max_Val) { (*(_mptr->Cur_Val))++; if(_mptr->itemFunction) (*_mptr->itemFunction)(); } } else if (SubMenu_choiced) { // переходим на предыдуший пункт меню if (--_mptr < MenuItems) // если первый то переходим на последний. _mptr = &MenuItems[(sizeof MenuItems)/(sizeof (struct _menuItem)) - 1]; } break; case KEY_4: // Key 2 presed (-) if(_mptr_choiced) // уменьшаем значение параметра { if (*(_mptr->Cur_Val) > _mptr->Min_Val) { (*(_mptr->Cur_Val))--; if(_mptr->itemFunction) (*_mptr->itemFunction)(); } } else if (SubMenu_choiced) { // переходим на следующий пункт меню if (++_mptr > &MenuItems[(sizeof MenuItems)/(sizeof (struct _menuItem)) - 1]) // если последний _mptr = MenuItems; // то переходим на первый } break; } }
Сейчас посмотрел, есть что оптимизировать - нужно просто переписать. Станет и понятней, и правильней и короче. Но как всегда, писалось для себя и на скорую руку - комментариев минимум. Идея была упростить добавление пунктов в подменю. Просто добавляется элемент структуры, указывается текст, переменная, отвечающая за параметр, макс/мин значения параметра, ячейка EEPROM для сохранения, и функция, если нужно сделать что-то после изменения этого параметра, кроме обновления переменной. И все, появился и работает новый элемент настроек. Сюда попадаем из обработчика кнопок, Функция вывода на экран отображает, если что то изменилось, ориентируясь на флаги и используя выбранные в меню значения. Сделано 6 штук, работают по дачам, глюков, сбоев зависаний - не замечено.