Организация простого меню для МК

Просмотров: 35755Комментарии: 6
Электроника. СхемотехникаМикроконтроллеры AVR

Понадобилась мне как-то простая менюшка. Посидел чуток и кое-чего получилось. Сейчас попробую рассказать как ее реализовать, если понадобится. 

Идея такая:

На ЖКИ отображается какая то информация. И тут мы хотим что-нибудь подстроить и вызываем меню. На экране появляются пункты меню, которые мы можем пролистывать и устанавливать то что нам нужно. Когда все настройки закончились, нажимаем выход и на экране снова отображается нужные данные.

Схема подключения кнопок и ЖКИ приведена на рисунке

см. Подключение библиотеки символьного ЖКИ в WinAVR

Обвязка микроконтроллера по питанию не показана.
Т.е. у нас есть 4 кнопки - Menu, Exit, Left, Right.
Menu - вызов меню и вход в подменю
Exit - выход из меню и из подменю
Left, Right - листаем пункты меню

Чтобы двигаться дальше, нам нужна блок схема программы организации меню. Откровенно говоря, когда делал меню никакой блок схемы программы не было. Но для статьи решил нарисовать ее. В итоге получилась такая вот блок схема.

Немного страшновато выглядит, но легко реализуется. На схеме выделено, какие функции что выполняют в коде программы. Каждому пункту меню соответствует свой count. При переходах между подменю count умножается на 10. При переходах по пунктам в одном подменю, count прибавляется или вычитается (Right, Left соответственно). Также есть регистр в котором сохраняю последнюю операцию. Т.е. если мы нажимаем Left тогда установкой нужного бита записываем что была операция вычитания, если нажимаем Right тогда была операция сложения. Для чего это сделано? Если, например, вы листаете вправо и доходите до последнего меню, а дальше если нажать вправо будет снова прибавление count, но это было последний пункт в этом подменю и когда мы это определяем нам нужно вернуться на предыдущий пункт. Для этого смотрим бит последней операции и делаем с count противоположную.

В общем рассмотрим кратко функции программы с комментариями. В конце статьи можно скачать проект в Proteus'e и исходник в WinAVR (сильно не заморачивался с задержками для четкого отображения, поэтому картинка на экране будет моргать). При работе с установкой и сбросом бита поставил числа в виде 0b..., мне кажется, так наглядней какой бит изменяем. Итак:

[br]
1. Объявляю глобальные переменные
// Глобальные переменные
unsigned int menu;//код нажатой кнопки 
unsigned int count=0;
//массив строк с названиями пунктов меню 
char* str[]={"menu 1", "menu 2", "menu 3", "menu 1_1",
"menu 1_2","menu 1_3", "menu 2_1", "menu 2_2", "menu 3_1", "menu 1_1_1", "menu 1_1_2"};
unsigned char MDCR=0;//регистр в котором 6-й бит будет определять последнюю операцию (+ или -)
[br]
2. Функции для работы с меню
//Функция изменения активной шины кнопок (у нас их две)
void fChangeButton();
//Функция возвращает код выбранной кнопки
unsigned char fSelButton();
//Функция в зависимости от count отображает пункт меню
void fDisplayMenu(unsigned int countmenu)
{        
        unsigned char tempmenu;                         
        switch(countmenu)
        {//Главное меню
                case 1: { LCDstring(str[countmenu-1], 6); break;}
                case 2: { LCDstring(str[countmenu-1], 6); break;}
                case 3: { LCDstring(str[countmenu-1], 6); break;}
        //Подменю первого пункта главного меню
                case 10: { LCDstring(str[3], 8); break;} 
                case 11: { LCDstring(str[4], 8); break;} 
                case 12: { LCDstring(str[5], 8); break;} 
        .
      .
      .                 
        //Если не попал ни в один пункт меню       
                default
                {   
                        //если не попал ни в один пункт меню тогда проверяю бит 6 на последнюю операцию 
                        //и делаю противоположную                        
                        if((tempmenu=(MDCR&0b01000000))==0b01000000)//последняя операция +
                                count--;
                        if((tempmenu=(MDCR&0b01000000))==0b00000000)//последняя операция -
                                count++;                            
                        break;
                }
        }              
}
//Функция опроса клавиатуры
void fMenu()
{                          
        count=1;
        while(1)
        {       
                _delay_ms(10);
                LCDclr();              
                fChangeButton();
                menu=fSelButton();
                //Menu
                if(menu==0x06)
                {    
                        count*=10;          
                }
                //если выбран пункт меню Left
                if(menu==0x05)
                {
                        count--; 
                        //сбрасываю бит 6 - значит последняя операция была - 
                        MDCR&=0b10111111;
                }
                //выбран пункт меню Right
                if(menu==0x09)
                {      
                        count++; 
                        //выставляю бит 6 в единицу,  - значит последняя операция была +
                        MDCR|=0b01000000;         
                }
                //если выбран Exit
                if(menu==0x0A)
                {     
                        if(count<10)
                                break;
                        if(count>=10)
                        {                  
                                count/=10
                        }
                }
                //функция отображения пункта меню в зависимости от значения count                
                fDisplayMenu(count);                        
        };
}
[br]
Кратко можно описать так: идет опрос клавиатуры, нажимаем кнопку, в зависимости от нажатой кнопки делаем соответствующую операцию с count, в зависимости от полученного значения выводим пункт меню.
На этом буду заканчивать. Надеюсь все понятно. Если что задавайте вопросы в комментариях.
[br]

Комментариев: 6 RSS

1 Аноним 12-04-2011 19:25

а как реализовать такое меню на codevisinavr??

2 Dmitry 12-04-2011 21:47

так же точно, только заменить функцию вывода строки на экран LCDstring() на функцию из codevision, вроде lcd_puts(). вот здесь реализовано именно на codevision - http://samou4ka.net/page/velosipednyj-spidometr-na-avr

3 Игорь 13-05-2011 23:15

Здравствуйте.

В протеусе прога работает нормально, но в железе на ЖКИ выводит поочередно Hello!, потом набор левых символов. При входе в меню экран заполняется разными символами. В чем может быть проблема?

ЖКИ - RC1602A (HD44780)

4 Dmitry 14-05-2011 01:39

набор левых символов скорее всего выводит из-за того, что в функции вывода строки на экран стоит вывод больше символов, чем длина строки. нужно поставить там sizeof(строка). По поводу заполнения разными символами так сразу не скажу. Вы ничего не меняли в коде?

5 Игорь 14-05-2011 03:24

Нет, в коде ни чего не менял. Собрал все верно, "Hello!" выводит еще более менее понятно, но при нажатии на любую кнопку получаем бред на ЖКИ.

6 Сергей 08-08-2011 18:57

Спасибо за идею, я ей воспользуюсь. Думаю лучше перейти на 16-ричную СС с заменой умножения и деления на битовые сдвиги, так как это позволит увеличить максимальное число подпунктов с 10 до 16.

Оставьте комментарий!

grin LOL cheese smile wink smirk rolleyes confused surprised big surprise tongue laugh tongue rolleye tongue wink raspberry blank stare long face ohh grrr gulp oh oh downer red face sick shut eye hmmm mad angry zipper kiss shock cool smile cool smirk cool grin cool hmm cool mad cool cheese vampire snake excaim question

Используйте нормальные имена. Ваш комментарий будет опубликован после проверки.

Вы можете войти под своим логином или зарегистрироваться на сайте.

(обязательно)