Главная » Статьи » Проекты

Делаем меню для своего проекта на микроконтроллере
 Когда любой проект растет в функционале, и из простого показометра хочется сделать нечто большее, нужно придумать, как организовать удобную работу с устройством. Хорошо если в проекте задействован дисплей (графический, алфавитно-цифровой, да хоть семисегментный) тогда можно создать свое меню и рулить настройками оттуда.  Вот и попробуем организовать несложное древовидное меню из небольшого списка, с возможностью выбора любого пункта. Для начала необходимо определится с организацией и количеством пунктов меню и нарисовать структурную схему. Например, сделаем меню из 4-х пунктов, в каждом из которых по 3 подпункта, такую вот:
организация меню

 Для микроконтроллера каждый пункт это всего лишь переменная (А), которая меняется при нажатии кнопок и в зависимости от значения которой, на дисплей выводится информация или выполняется то или иное действие.  Кнопок, кстати всего 4: вверх (up), вниз (down), выбор (ok) и выход (esc). Сейчас подробно рассмотрим, что происходит с переменной при нажатии этих кнопок.

 При старте программы (или при входе в меню), переменной А присваивается значение 10, это соответствует первому пункту меню. При нажатии кнопки «Вниз», к  переменной прибавляется 10, и она становится равна 20, это соответствует второму пункту меню. Если еще раз нажать на эту кнопку, переменная станет равна 30, что будет соответствовать третьему пункту меню и так далее. Если нажать кнопку «Вверх» переменная будет уменьшаться на 10, до тех пор, пока не станет равна 10. Таким образом, организована навигация по главному списку меню.

 Для примера остановимся на первом пункте, и войдем в подменю первого пункта нажав кнопку "Вход". При этом к переменной прибавляется единичка и переменная становится равна 11. Это соответствует первому подпункту первого пункта меню %)
 Теперь если нажать на кнопку "Вниз" переменная будет увеличиваться на 1, пока не станет равна 13 (всего у нас 3 подпункта меню). Если нажимать на кнопку "Вверх" переменная будет уменьшаться на 1, пока не достигнет значения 11. Вот и организовали навигацию по пунктам подменю. Теперь, находясь в подменю, к примеру на пункте 1.1, если нажать кнопку "Ввод" переменная умножается на 10 и становится равна 110. 
При таком значении переменной вызывается подпрограмма 1.1, в которой совершаем какие нибудь действия. Выход организован проверкой значения переменной и присвоением переменной определенного значения. 
 Если все вышесказанное кажется бредом не совсем понятно, посмотри на рисунок ниже. Тут я на примере двух пунктов меню показал, как изменяется значение переменной и какие действия с ней происходят когда мы нажимаем на кнопки:

логика работы навигации по меню


Под каждую кнопку задействовано свое внешнее прерывание. Обработка нажатия кнопок у меня выглядит следующим образом:


Код обработчиков внешнийх прерываний
Ok:                                                         'обработка нажатия кнопки "OK"

If A = 11 Or A = 12 Or A = 13 Then
  A = A * 10
End If

If A = 21 Or A = 22 Or A = 23 Then
  A = A * 10
End If

If A = 31 Or A = 32 Or A = 33 Then
  A = A * 10
End If

If A = 41 Or A = 42 Or A = 43 Then
  A = A * 10
End If

If A = 10 Or A = 20 Or A = 30 Or A = 40 Then
  Incr A
End If

Return



Esc:                                                        'обработка нажатия кнопки "ESC"

If A = 11 Or A = 12 Or A = 13 Then
 A = 10
End If

If A = 21 Or A = 22 Or A = 23 Then
 A = 20
End If

If A = 31 Or A = 32 Or A = 33 Then
 A = 30
End If

If A = 41 Or A = 42 Or A = 43 Then
 A = 40
End If

If A > 100 Then
A = A / 10
End If

Return



Down:                                                       'обработка нажатия кнопки "DOWN"

If A = 10 Or A = 20 Or A = 30 Then
  A = A + 10
End If

If A = 11 Or A = 12 Then
  Incr A
End If

If A = 21 Or A = 22 Then
  Incr A
End If


If A = 31 Or A = 32 Then
  Incr A
End If

If A = 41 Or A = 42 Then
  Incr A
End If

Return



Up:                                                         'обработка нажатия кнопки "UP"

If A = 20 Or A = 30 Or A = 40 Then
 A = A - 10
End If

If A = 12 Or A = 13 Then
  Decr A
End If

If A = 22 Or A = 23 Then
  Decr A
End If

If A = 32 Or A = 33 Then
  Decr A
End If

If A = 42 Or A = 43 Then
  Decr A
End If
 
Return

  Такая логика дает во-первых жесткую привязку выполняемых действий при нажатии кнопки, в зависимости от предыдущего значения переменной. Что гарантирует точное выполнение кода. А во-вторых, легко добавить или убрать необходимые пункты и подпункты, подстраивая меню под свой проект.

  В главном цикле программы, в зависимости от значения переменной, будет происходить отрисовка меню и выполняемых операций. Тут все зависит от фантазии и применяемого дисплея.
В своем примере я применил алфавитно-цифровой 4-х строчный дисплей и микроконтроллер Atmega64. Почему такой жирный камень? Просто в нем есть необходимое количество внешних прерываний, и с ним нормально работает протеус. А вообще программа получилась размером чуть больше 4 кб, поэтому можно использовать контроллеры со значительно меньшей флэш памятью. А если сделать принудительный опрос кнопок, то не обязательно будет использовать микроконтроллер с большим числом внешних прерываний. В общем, на вкус и цвет... Схема подключения дисплея и кнопок ниже:



  Итак, при старте программы, переменная имеет значение 10. Это значение переменной соответствует первому пункту меню, нарисуем напротив этого пункта курсор. Например так:



 Код отрисовки выделения первого пункта меню у меня такой:

Подпрограмма вывода на дисплей выделения курсором первого пункта меню
10:                                   'подпрограмма отрисовки на дисплее выделения первого пункта

Lcd "label 1        <"                'в первой строке нарисовали курсор 
Lowerline                             'пишем на второй строке 
Lcd "label 2"
Thirdline                             'пишем на третьей строке
Lcd "label 3"
Fourthline                            'пишем на четвертой строке
Lcd "label 4"

Return                                'возвращаемся в основной цикл программы


 Теперь жмем на кнопку "Down", переменная увеличивается, и нужно нарисовать движение курсора вниз: остановимся например на третьем пункте, при этом значение переменной будет А=30:


Подпрограмма вывода на дисплей выделения курсором третьего пункта меню
30:                                   'подпрограмма при А=30

Lcd "label 1"                          
Lowerline                              
Lcd "label 2"
Thirdline                              
Lcd "label 3        <"                'курсор напротив третьего пункта
Fourthline                             
Lcd "label 4"

Return                                'возвращаемся в основной цикл программы
 

 Вот что будет на дисплее:


 При нажатии на кнопку "OK" переменная станет равна 31. На дисплее отобразится вход в подменю. В шапке отобразим родителя (пункт откуда пришли):

Подпрограмма вывода на дисплей выделения курсором третьего пункта меню
31:                                   'подпрограмма при А=31

Lcd "    label 3"                          
Lowerline                              
Lcd "label 3.1      <"
Thirdline                              
Lcd "label 3.2"               
Fourthline                             
Lcd "label 3.3"

Return                                'возвращаемся в основной цикл программы
 


 При повторном нажатии кнопки "OK" переменная станет равна 310, и произойдет выполнение подпрограммы, какой угодно, например просто выведем надпись "Run program 3.1" на дисплей: 


310:                                  'подпрограмма при А=310

Lcd "RUN PROGRAM  3.1"                'выводим надпись       

Return                                'возвращаемся в основной цикл программы
 


 При нажатии на кнопку "ESC" переменная изменится и произойдет выход из этой подпрограммы. Ну а дальше принцип думаю ясен. Как видишь, организовать свое меню, не такая уж непосильная задача как может показаться. Удачи!

Ниже можно скачать архив с моделью в Proteus, исходник и откомпилированный файл:

СКАЧАТЬ

UPD:  если нет протеуса, то для просмотра работы меню сгодится симулятор самого bascom-avr, как его заюзать писалось ранее





Категория: Проекты | Добавлено: 25.06.2011
Просмотров: 67749 | Комментарии: 35 | Теги: atmega64, дисплей, Алгоритм, меню | Рейтинг: 4.6/19
Всего комментариев: 331 2 »
33 rustr   (15.12.2013 11:40) [Материал]
Нее, алгоритм понятен, даже для меня :-)
Я не могу придумать, как при A=, допустим 0 (при старте) вызывать меню нажатием кнопки "Ok" и далее по алгоритму и при выходе снова присваивать А=0

32 exersizze   (12.12.2013 13:39) [Материал]
А в чем проблема? с алгоритмом или с обработкой кнопки при нажатии. Если проблема с алгоритмом посмотри вот этот проект http://avrproject.ru/publ/logger_temperatury_2_0/1-1-0-134 там как раз меню у меня организовано для настроек разных. Суть там вся в следующем: есть переменная Z,  и стоит проверка этой переменной в главном цикле. Если она равна нулю тогда на дисплей выводятся показания датчиков и прочая рабочая информация. При нажатии на кнопку "ОК" переменная Z становится равна 1 и при следующей проверки этой переменной на дисплей выводится первое окно менюшки  (см файл Menu.bas) Ну и так далее нажимая кнопки, эта переменная меняется и на дисплей выводится соответствующая информация.

31 rustr   (11.12.2013 22:13) [Материал]
Пытаюсь, опыта не хватает.
Например, никак не могу придумать, как вызывать меню при нажатии на кнопку Ok

30 exersizze   (09.12.2013 08:34) [Материал]
Дело в том что влево/вправо да и любая комбинация добавляется аналогично тому что приведено в примере, нужно просто немного подумать и вникнуть в идею.

29 rustr   (06.12.2013 11:53) [Материал]
Здравствуйте.
Пытаюсь приспособить Вашу идею под свои нужды, возник вопрос - а как можно добавить в Ваш код обработку кнопок "Влево" и "Вправо"?

28 exersizze   (31.10.2013 19:50) [Материал]
Обычно сначала вникают в алгоритм чтобы переписать на другой язык, могу посоветовать сделать также.

27 shansov   (31.10.2013 14:49) [Материал]
Подскажите как перевести на СИ?

26 exersizze   (19.09.2013 18:48) [Материал]
В железе не должно ничего мигать, текст выводится на дисплей быстро. Проверьте правильность выставленных фьюз, может частота работы стоит на самом деле ниже 16МГц
И попробуйте убрать команду Cls  в коде перед строками вывода строк на дисплей.

25 rus9892   (19.09.2013 13:53) [Материал]
на 16Мгц

24 exersizze   (19.09.2013 10:50) [Материал]
на какой частоте работает микроконтроллер?

23 rus9892   (19.09.2013 10:18) [Материал]
почем у меня пункты меню медленно вырисовываются на жк не подскажите ребята?

22 Zheckiss   (09.07.2013 17:26) [Материал]
Гениально! Вы решили мою проблему! Спасибо!!!

21 max   (06.04.2013 17:17) [Материал]
Антошин, вот это то, что тебе нужно:
http://avrproject.ru/publ....1-0-138

20 Антошин   (06.04.2013 16:25) [Материал]
Хотелось бы тоже самое для камней по проще у которых Int0 и Int1,т.е еще две кнопки
повесить на обычные пины...Возможно ли?

19 exersizze   (02.01.2013 16:57) [Материал]
Данные с часов принимаются в двоично-десятичном формате, возможно проблема в этом. Посмотри вот этот проект http://avrproject.ru/publ....1-0-110 там меню сделано по такому же принципу и добавлена работа с часами ds1307

18 shinkaruk-ivan   (02.01.2013 16:21) [Материал]
Помогите у меня не получается добавить в этот проект часы реального времени,
или на дисплее какая то ерунда (часы искаженные, или на дисплее вообще ничего не показывает

17 DM   (25.12.2012 12:08) [Материал]
ГЕНИАЛЬНО !!! С легкостью перевел это на СИ в CVAVR и работаю.

16 exersizze   (15.04.2012 10:55) [Материал]
я не имел дело с такими дисплеями, поэтому подсказать не смогу.

15 sashashemelev1   (15.04.2012 08:56) [Материал]
С построением меню разобрался. Только не получается на графическом LCD 128х64 не могу сделать меню с выделением символов инверсией. Подскажите...

14 sashashemelev1   (26.03.2012 18:12) [Материал]
Спасибо! Теперь надеюсь разберусь.

13 exersizze   (26.03.2012 09:53) [Материал]
код практически аналогичен переходу из главного меню в пункты подменю:
вход в подменю
Code
OK:
if A=13 then  
A=130
end if
return


курсор вниз

Code
DOWN:
if A=130 then
incr A
....
return

и так далее

12 sashashemelev1   (24.03.2012 17:15) [Материал]
А можно кусочек кода увидеть, а то не догоню никак... BASCOM недавно стал использовать, не всё быстро доходит. Ещё написал кусок кода меню для GLCD128х64, но не знаю как в графическом виде это всё сообразить,в смысле хотелось бы символы на экране сделать инверсными.

11 exersizze   (24.03.2012 16:44) [Материал]
можно сначала умножить переменную на 10, а затем ее инкрементировать. И тогда можно в этом пункте организовать еще 10 подпунктов (со значением переменной с 130 по 139)

10 sashashemelev1   (24.03.2012 14:45) [Материал]
Как поступить, если мне нужно например из пункта 1.3 сделать ещё меню на 8 пунктов. Всю голову сломал - не получается никак....

9 exersizze   (23.10.2011 15:40) [Материал]
Если понятен принцип того, как организовать меню, то уже дело вкуса как организован переход по пунктам. Способов на самом деле куча.

8 pchela5   (23.10.2011 14:52) [Материал]
С меню очень доступно написано, но много лишних условий.
Можно ли сделать проще?
Например, так:
'Код обработчиков внешнийх прерываний
Ok: 'обработка нажатия кнопки "OK"

If(a Mod 10) = 0 Then
Incr A
Else
A = A * 10
End If

Return

Esc: 'обработка нажатия кнопки "ESC"

If A > 100 Then
A = A / 10
Else
A = A / 10
A = Abs A ' если переменная integer то действие может быть лишним
A = A * 10
End If

Return

Down: 'обработка нажатия кнопки "DOWN"

If(a Mod 10) = 0 Then

A = A + 10
Else
Incr A
End If

Return

Up: 'обработка нажатия кнопки "UP"

If(a Mod 10) = 0 Then
A = A - 10
Else
Decr A
End If

Return

7 exersizze   (06.07.2011 23:21) [Материал]
А это все зависит от того, что в этом цикле будет выполняться. Если простенький код и без больших задержек, то и для опроса кнопок можно выделить место в главном цикле. А если в цикле задержка в секунду или более, то до момента опроса кнопок может пройти немало времени. Ну их нафиг такие кнопки, которые не реагируют на нажатия. Или еще момент, есть например в нашем цикле проверка условия, по которому будет выход из этого цикла. И тогда все, до опроса кнопок дело так может и не дойти никогда, в общем жуть))
Решением может быть применение таймера: настраиваешь любой свободный таймер на прерывание по переполнению, и в обработчике прерывания производишь опрос кнопок. В независимости от того какой код будет выполняться, будет происходить прерывание по переполнению, а значит и опрос кнопок.

6 kestrel   (06.07.2011 20:07) [Материал]
интересно, если кнопки не сажать на прерывания, а опрашивать их в основном цикле насколько это будет првильно (в плане правильности построения программы?) хотелось бы узнать ваше мнение, но это я так для себя. Да и еще если команду очистки дисплея поместить не в начале основного цикла, а в начале кода обработки нажатий кнопок Ok и Esc можно избежать неприятного моргания дисплея

5 AlekS   (06.07.2011 19:32) [Материал]
Мы за тобой следим :-)

4 exersizze   (03.07.2011 19:03) [Материал]
В планах было собрать регуль для двигателя использующий шим. Так что этот момент будет обязательно освещен в ближайшее время.

1-30 31-33
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]






авторизация