Помогите новичку (хитрости)
- Войдите на сайт для отправки комментариев
Вс, 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", что это такое)
Чтобы меньше путаться, можно определить все кейсы текстовыми константами и обращаться к ним по имени.
Чтобы ещё меньше путаться, можно вынести выполнение по нескольку строк из свитча в отдельные функции.
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 используется та же идеология.
Чтобы меньше путаться, можно определить все кейсы текстовыми константами и обращаться к ним по имени.
Чтобы ещё меньше путаться, можно вынести выполнение по нескольку строк из свитча в отдельные функции.
Blink без ожидания вот здесь: https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
идея с константами значительно упрощает, спасибо большое, код я решил оставить старый
А по поводу блинк светодиодом это все знают, я подумал что это что-то другое, невстречал полного названия на английском, та и в английском я несилен
Согласен, это не полноценный ГУИ, но хоть какойто интерфейс))
Что бы не городить такие вещи.
и
ну и так далее, содайте класс display , и напишите методы screen1,screen2 и так далее. Можете так же создать метод case_screen который уже будет переключать на нужные и созданые методы. Для чего делать так? Так модульность. Чем меньше модуль, тем легче наладить и оттестировать правильность его работы.
следующим логичным шагом после
\\можно вынести выполнение по нескольку строк из свитча в отдельные функции.
будет массив указателей на эти функции, тогда вместо свича можно будет просто по MenuS как по индексу массива одной командой выполнить действие. При этом интересно выглядит вариант с одной функцией и для первого и для второго свича, а разделять их параметром. Получится вызовы типа
И соответственно в каждой функции - весь код относящийся к соответствующему действию (например к HELP_MENU) все рядом как просил ТС.
И соответственно после этого так и просится - убрать MenuS а вместо ее сделать переменную - указатель на ту функцию индекс которой ранее был в MenuS. Получим весьма профессиональный, быстрый и лаконичный код, без лишних идентификаторов, с ясным соответствием: каждое действие (или что там, пункт меню?) в отдельной функции.
Такой вот ООП без ООП. Так что хитростей валом )))
Городить классы и модули здесь врядли целесообразно, писанины много а повторное использование сомнительно.