Помогите новичку (хитрости)
- Войдите на сайт для отправки комментариев
Вс, 24/07/2016 - 13:07
Добрый день! Имеется код в котором выводится информация на дисплей в зависимости от переменной MenuS
void ScreenUp (void)
{switch (MenuS){
case 0://menu
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(punkt+1);
lcd.setCursor(2, 0);
lcd.print(GUI.Menu[punkt]+" "); lcd.write(byte(0));
lcd.setCursor(0, 1);
lcd.print(punkt + 2);
lcd.setCursor(2, 1);
lcd.print(GUI.Menu[punkt+1]);
break;
case 1:
lcd.clear();
lcd.scrollDisplayRight();
lcd.print("Test AutoScroll Text");
break;
case 2:
break;
case 3:
lcd.clear();
lcd.setCursor(0, 0);
lcd.write(byte(punkt));
lcd.print(" "+punkt);
lcd.setCursor(0, 1);
lcd.write(byte(punkt+1));
lcd.print(" "+punkt+1);
break;
case 20:
lcd.clear();
lcd.print(AlarmArrS[punkt]);
break;
}
}
имеется функция которая срабатывает по нажатию кнопки и в зависимости от информации на экране совершает различные действия
void buttonOn (void)
{
switch (MenuS) {
case -1: lcd.backlight(); MenuS = 0; ScreenUp(); break;
case 0:
switch (punkt) {
case 0: DisplayOff();
break;
case 1: MenuS = 2; ScreenUp(); break;
case 3: MenuS = 3; ScreenUp(); break;
case 6:
lcd.clear(); lcd.print("Alarm Tested!");
for (int i = 0; i <= 10; i++) {
tone(12, 800, 40);
delay(42);
tone(12, 1200, 40);
delay(42);}
lcd.clear(); ScreenUp();
break;
case 9: MenuS = 1; break;
default:
lcd.clear();
lcd.print("page not found");
delay(800);
ScreenUp(); break;
case 1:
case 2: //help
lcd.noAutoscroll();
MenuS = 0;
break;
case 3:
MenuS = 0; ScreenUp();
break;
case 20:
if (AlarmState == false){ //alarm
if (punkt != 0) {
lcd.clear();
lcd.print("Timer set");
lcd.setCursor(0,1);
lcd.print(AlarmArrS[punkt]);
delay(400);
DisplayOff();
MenuS = 1;
delay(AlarmArr[punkt]*1000);
AlarmState=true;
} else {MenuS = 0; ScreenUp(); }
} else { AlarmState = false; MenuS = 0; lcd.backlight(); ScreenUp();} break;
break;
}
}
И вот тут встает праблема, у нас 2 огромных свитч-кейс"а в двух разных функциях, могу ли я после выполнения функции ScreenUp (после вывода информаци на экран) изменить выполняемый код в функции buttonOn c учетом того, что функция buttonOn будет запущена через неопределенное время (секунда, час, день) Возможно существуют какие либо хитрости?
И вот тут встает праблема, у нас 2 огромных свитч-кейс"а в двух разных функциях, могу ли я после выполнения функции ScreenUp (после вывода информаци на экран) изменить выполняемый код в функции buttonOn c учетом того, что функция buttonOn будет запущена через неопределенное время (секунда, час, день) Возможно существуют какие либо хитрости?
Гарвардская архитектура (по которой построены AVR) в принципе не предполагает возможности изменения кода программы самой программой.
Впрочем, подозреваю, что под "изменить выполняемый код в функции" Вы подразумевали что-то другое. Но что именно, мне неизвестно.
Что же касается самого кода функции buttonOn, то его IMHO следовало бы переписать, опираясь на идеологию "blink without delay". Вполне вероятно, Ваш вопрос в результате разрешится сам собой.
под изменением кода я подразумеваю тот же switch-case только проще или быстрее... просто начинаешь путаться когда вывод информации (ScreenUp) находится далеко от функции ButtonOn, выбора варианта
Как вы уже поняли я пытаюсь написать эдакий GUI только общий размер программы уже составляет 47% а это только меню и пара тестовых "страниц" Было бы "по людски" разделить GUI и часть программы, которая будет выполнять действия на 2 ардуинки, но пока немогу себе такого позволить...
В функции buttonON первый свитч-кейс определяет на какой странице находится пользователь
если MenuS = -1 то GUI выключен и при нажатии кнопки, мы попадаем в главное меню, его номер = 0, тоесть MenuS =0 там же уже основываясь, какой пункт меню мы выбрали, по нажатию кнопки производится действие...
А можно по подробнее про "blink without delay", что это такое)
Чтобы меньше путаться, можно определить все кейсы текстовыми константами и обращаться к ним по имени.
Чтобы ещё меньше путаться, можно вынести выполнение по нескольку строк из свитча в отдельные функции.
case HELP_MENU: help_menu_function(); break; ... void help_menu_function(void) { lcd.noAutoscroll; MenuS=0; }Blink без ожидания вот здесь: https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
Как вы уже поняли я пытаюсь написать эдакий GUI только общий размер программы уже составляет 47% а это только меню и пара тестовых "страниц"
Честно говоря, еще не понял.
Более того, я обнаружил у Вас только текстовый вывод. Чем по-Вашему графический интерфейс отличается от текстового?
Вообще же, IMHO Arduino не предназначена и непригодна для GUI - слишком мало операивной памяти.
А можно по подробнее про "blink without delay", что это такое)
Посмотрел дату регистрации на форуме - вчера. ТОгда понятно.
blink without delay - это классика: https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
Кстати, в Windows GUI используется та же идеология.
Чтобы меньше путаться, можно определить все кейсы текстовыми константами и обращаться к ним по имени.
Чтобы ещё меньше путаться, можно вынести выполнение по нескольку строк из свитча в отдельные функции.
case HELP_MENU: help_menu_function(); break; ... void help_menu_function(void) { lcd.noAutoscroll; MenuS=0; }Blink без ожидания вот здесь: https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
идея с константами значительно упрощает, спасибо большое, код я решил оставить старый
А по поводу блинк светодиодом это все знают, я подумал что это что-то другое, невстречал полного названия на английском, та и в английском я несилен
Согласен, это не полноценный ГУИ, но хоть какойто интерфейс))
Что бы не городить такие вещи.
lcd.clear(); lcd.setCursor(0, 0); lcd.print(punkt+1); lcd.setCursor(2, 0); lcd.print(GUI.Menu[punkt]+" "); lcd.write(byte(0)); lcd.setCursor(0, 1); lcd.print(punkt + 2); lcd.setCursor(2, 1); lcd.print(GUI.Menu[punkt+1]);и
lcd.clear(); lcd.scrollDisplayRight(); lcd.print("Test AutoScroll Text");ну и так далее, содайте класс display , и напишите методы screen1,screen2 и так далее. Можете так же создать метод case_screen который уже будет переключать на нужные и созданые методы. Для чего делать так? Так модульность. Чем меньше модуль, тем легче наладить и оттестировать правильность его работы.
следующим логичным шагом после
\\можно вынести выполнение по нескольку строк из свитча в отдельные функции.
будет массив указателей на эти функции, тогда вместо свича можно будет просто по MenuS как по индексу массива одной командой выполнить действие. При этом интересно выглядит вариант с одной функцией и для первого и для второго свича, а разделять их параметром. Получится вызовы типа
#define SCREEN 1 #define BUTTON 2 void ButtonON (void) { arrFunc[MenuS](BUTTON); } void ScreenUp (void) { arrFunc[MenuS](SCREEN ); }И соответственно в каждой функции - весь код относящийся к соответствующему действию (например к HELP_MENU) все рядом как просил ТС.
И соответственно после этого так и просится - убрать MenuS а вместо ее сделать переменную - указатель на ту функцию индекс которой ранее был в MenuS. Получим весьма профессиональный, быстрый и лаконичный код, без лишних идентификаторов, с ясным соответствием: каждое действие (или что там, пункт меню?) в отдельной функции.
Такой вот ООП без ООП. Так что хитростей валом )))
Городить классы и модули здесь врядли целесообразно, писанины много а повторное использование сомнительно.