Урок 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
Смотреть ВИДЕОУРОК
Большое спасибо за уроки, крайне удивлен как у вас хватает времени на все это…
третий день сижу разбираю код этого урока вроде все в голове сложилось….
не могу понять почему статус кнопки ST_PRESSURE нигде не участвует и не влияет на процесс и зачем этот статус устанавливается в двух местах и нигде не обнуляется…. поправьте меня если ошибаюсь за ранее спасибо и с Наступающим Новым Годом вас и ваших близких !!!!!!! За ранее благодарен…..Андрей
Ну да, не используется, но вдруг будет использоваться. Это именно на этот случай. Может кому-то надо отследить именно момент нажатия. Не бойтесь, всё будет работать, когда будем делать меню. Проверено на AVR. Если не будет, исправим. Не привыкать.
Вам также спасибо за оценку! И с Наступающим!