AVR УРОК 36. Модуль LCD 16×2. Продолжаем работать с кнопками. Часть 3

 

 

 

Урок 36

Часть 3

 

Модуль LCD 16×2 .Продолжаем работать с кнопками

 

 

В части 1 и части 2 занятия мы настроили проект, также содали проект для протеуса, настроили таймер и добавили некоторые макроподстановки для хранения определённых статусов, также написали ряд функций для обеспечения отслеживания данных статусов

Сегодня мы продолжим это дело и попытаемся уже реализовать в работающий процесс

Напишем код для определения статуса пока одной кнопки в функции-обработчике прерывания от таймера

 

ISR (TIMER0_OVF_vect)

{

        Read_Button_State(Button_Right);

        Read_Button_State(Button_Up);

        Read_Button_State(Button_Down);

        Read_Button_State(Button_Left);

        Read_Button_State(Button_Select);

}

 

Напишем две функции для сброса и установки статуса кнопки

 

//——————————————

void ResetButtonState(unsigned char b, unsigned char st)

{

        button_state[b]  &= ~st;

}

//——————————————

void SetButtonState(unsigned char b, unsigned char st)

{

        button_state[b]  |= st;

}

//——————————————

void Buttons_Ini(void)

Добавим прототипы данных функций

void Buttons_Ini(void);

void ResetButtonState(unsigned char b, unsigned char st);

void SetButtonState(unsigned char b, unsigned char st);

//——————————————-

#endif /* BUTTON_H_ */

 

Теперь в бесконечном цикле удалим часть старого кода попытаемся определить статус одной кнопки и среагируем на него, также не забываем про флаги. Можно убавить задержку

.

        while(1)

        {

                setpos(0,1);

                if (button_state[Button_Right]&ST_UNPRESSURE)

                {

                        //предотвратим обращение к кнопке из таймера во время выполнения обработчика

                        SetButtonState(Button_Right,ST_LOCKED);

                        str_lcd("RIGHT KEY ");

                        ResetButtonState(Button_Right,ST_UNPRESSURE);

                        SetButtonState(Button_Right,ST_PRESSURE);

                        ResetButtonState(Button_Right,ST_LOCKED);

                }

                _delay_ms(50);

}

 

Скомпилируем код, проверим его пока в протеусе. Сообщение о кнопке должно появляться именно в момент отжатия кнопки.

Определим статус ещё одной кнопки и попробуем также в протеусе понажимать их по очереди

 

                        ResetButtonState(Button_Right,ST_LOCKED);

                }

                 if (button_state[Button_Up]&ST_UNPRESSURE)

                 {

                         //предотвратим обращение к кнопке из таймера во время выполнения обработчика

                         SetButtonState(Button_Up,ST_LOCKED);

                         str_lcd("UP KEY    ");

                         ResetButtonState(Button_Up,ST_UNPRESSURE);

                         SetButtonState(Button_Up,ST_PRESSURE);

                         ResetButtonState(Button_Up,ST_LOCKED);

                 }

 

 

Можно, в принципе, попробовать и на живом контроллере, вдруг не пойдёт. Если всё нормально, то добавим теперь обработчики недостающих трёх кнопок и проверим работу также и в протеусе и на настоящем дисплее и контроллере.

 

                         ResetButtonState(Button_Up,ST_LOCKED);

                 }

                if (button_state[Button_Down]&ST_UNPRESSURE)

                {

                        //предотвратим обращение к кнопке из таймера во время выполнения обработчика

                        SetButtonState(Button_Down,ST_LOCKED);

                        str_lcd("DOWN KEY  ");

                        ResetButtonState(Button_Down,ST_UNPRESSURE);

                        SetButtonState(Button_Down,ST_PRESSURE);

                        ResetButtonState(Button_Down,ST_LOCKED);

                }

                if (button_state[Button_Left]&ST_UNPRESSURE)

                {

                        //предотвратим обращение к кнопке из таймера во время выполнения обработчика

                        SetButtonState(Button_Left,ST_LOCKED);

                        str_lcd("LEFT KEY  ");

                        ResetButtonState(Button_Left,ST_UNPRESSURE);

                        SetButtonState(Button_Left,ST_PRESSURE);

                        ResetButtonState(Button_Left,ST_LOCKED);

                }

                if (button_state[Button_Select]&ST_UNPRESSURE)

                {

                        //предотвратим обращение к кнопке из таймера во время выполнения обработчика

                        SetButtonState(Button_Select,ST_LOCKED);

                        str_lcd("SELECT KEY");

                        ResetButtonState(Button_Select,ST_UNPRESSURE);

                        SetButtonState(Button_Select,ST_PRESSURE);

                        ResetButtonState(Button_Select,ST_LOCKED);

                }

 

Немного усовершенствуем наш код, а то как-то он устрашающе-громоздко смотрится. Создадим счётчик и массив из строк в функции main()

 

int main(void)

{

        unsigned char i=0;

        char str1[5][11] =

        {

                "RIGHT KEY ",

                "UP KEY    ",

                "DOWN KEY  ",

                "LEFT KEY  ",

                "SELECT KEY"

        };

        port_ini(); //инициализируем порты

 

Исправим код в бесконечном цикле

 

        while(1)

        {

                setpos(0,1);

                for (i=0;i<5;i++)

                {

                        if (button_state[i]&ST_UNPRESSURE)

                        {

                                //предотвратим обращение к кнопке из таймера во время выполнения обработчика

                                SetButtonState(i,ST_LOCKED);

                                str_lcd(str1[i]);

                                ResetButtonState(i,ST_UNPRESSURE);

                                SetButtonState(i,ST_PRESSURE);

                                ResetButtonState(i,ST_LOCKED);

                        }

                }

                _delay_ms(50);

        }

 

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

 

Предыдущая часть Программирование МК AVR Следующий урок

 

Исходный код

 

Программатор и дисплей можно приобрести здесь:

Программатор (продавец надёжный) USBASP USBISP 2.0

Дисплей LCD 16×2 с кнопками

 

 

Смотреть ВИДЕОУРОК

 

AVR Модуль LCD 16x2. Продолжаем работать с кнопками

 

2 комментария на “AVR УРОК 36. Модуль LCD 16×2. Продолжаем работать с кнопками. Часть 3
  1. Andrej_zav:

    Большое спасибо за уроки, крайне удивлен как у вас хватает времени на все это…

    третий день сижу разбираю код этого урока вроде все в голове сложилось….

    не могу понять почему статус кнопки ST_PRESSURE нигде не участвует и не влияет на процесс и зачем этот статус устанавливается в двух местах и нигде не обнуляется…. поправьте меня если ошибаюсь за ранее спасибо и с Наступающим Новым Годом вас и ваших близких !!!!!!! За ранее благодарен…..Андрей

    • admin:

      Ну да, не используется, но вдруг будет использоваться. Это именно на этот случай. Может кому-то надо отследить именно момент нажатия. Не бойтесь, всё будет работать, когда будем делать меню. Проверено на AVR. Если не будет, исправим. Не привыкать.

      Вам также спасибо за оценку! И с Наступающим!

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*