STM Урок 61. Модуль LCD 16×2. Работаем с кнопками. Часть 3

 

 

 

 

Урок 61

 

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

 

Часть 3

 

 

В прошлой части занятия мы написали практически все служебные функции для отслеживания изменения состояний кнопок.

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

Но прежде нам нужно закончить ещё одну функцию.

Вернёмся в button.c и напишем тело нашего обработчика

 

void TIM_Callback(void)
{
 if(tim_stat==0) return;

 HAL_ADC_Stop_IT(&hadc1);
 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);
 HAL_ADC_Start_IT(&hadc1);

}

 

АЦП на время работы функции лучше вообще останавливать, во-первых потому что он все равно нам не нужен, у нас уже всё измерено, а во-вторых, если его не останавливать, то у меня фунция могла обработать только вызовы двух кнопок, если добавлял третий, всё повисало.

 

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

 

//———————————————————
void ResetButtonState(uint8_t b, uint8_t st)
{
        button_state[b]  &= ~st;
}
//———————————————————
void SetButtonState(uint8_t b, uint8_t st)
{
        button_state[b]  |= st;
}
//———————————————————

void Buttons_Ini(void)

 

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

 

void Buttons_Ini(void);
void ResetButtonState(uint8_t b, uint8_t st);
void SetButtonState(uint8_t b, uint8_t st);

 

Подключим в файле main.c голобальную переменную

 

/* Private variables ———————————————————*/
extern uint8_t button_state[5];
uint16_t ADC_Data=0;

 

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

 

  while (1)
  {
  adc_value=ADC_Data;//занесём результат преобразований в переменную
  LCD_SetPos(0,0);//спозиционируем курсор
  sprintf(str1,"%d   ",adc_value);//преобразуем результат в строку
  LCD_String(str1);
  LCD_SetPos(0, 1);
  if (button_state[Button_Right]&ST_UNPRESSURE)
  {
      //предотвратим обращение к кнопке из таймера во время выполнения обработчика
      SetButtonState(Button_Right,ST_LOCKED);
      LCD_String("RIGHT KEY ");
      ResetButtonState(Button_Right,ST_UNPRESSURE);
      SetButtonState(Button_Right,ST_PRESSURE);
      ResetButtonState(Button_Right,ST_LOCKED);
  }
  HAL_Delay(50);//задержка перед следующим циклом

  /* USER CODE END WHILE */

 

Проверим код, собрав его и прошив контроллер. Если всё работает и на отжатие правой кнопки мы получаем сообщение на дисплее, то пишем дальше.

Определим статус ещё одной кнопки

 

   ResetButtonState(Button_Right,ST_LOCKED);
  }
  if (button_state[Button_Up]&ST_UNPRESSURE)
  {
   //предотвратим обращение к кнопке из таймера во время выполнения обработчика
   SetButtonState(Button_Up,ST_LOCKED);
   LCD_String("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);
   LCD_String("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);
   LCD_String("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);
   LCD_String("SELECT KEY");
   ResetButtonState(Button_Select,ST_UNPRESSURE);
   SetButtonState(Button_Select,ST_PRESSURE);
   ResetButtonState(Button_Select,ST_LOCKED);
  }

 

Соберём код, прошьём контроллер и проверим реакцию на все кнопки. Реакция должна быть именно на отжатие

 

image06

 

Чтобы код в бесконечном цикле не выглядел так громоздко, организуем его несколько по-другому.

Создадим счётчик и массив строк в main();

 

 uint16_t adc_value=0;
 uint8_t i=0;
 char str2[5][11] =
 {
  "RIGHT KEY ",
  "UP KEY    ",
  "DOWN KEY  ",
  "LEFT KEY  ",
  "SELECT KEY"
 };

  /* USER CODE END 1 */

 

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

 

  while (1)
  {
  adc_value=ADC_Data;//занесём результат преобразований в переменную
  LCD_SetPos(0,0);//спозиционируем курсор
  sprintf(str1,"%d   ",adc_value);//преобразуем результат в строку
  LCD_String(str1);
  LCD_SetPos(0, 1);
  for (i=0;i<5;i++)
  {

   if (button_state[i]&ST_UNPRESSURE)
   {
    //предотвратим обращение к кнопке из таймера во время выполнения обработчика
    SetButtonState(i,ST_LOCKED);
    LCD_String(str2[i]);
    ResetButtonState(i,ST_UNPRESSURE);
    SetButtonState(i,ST_PRESSURE);
    ResetButtonState(i,ST_LOCKED);
   }
  }
  HAL_Delay(50);//задержка перед следующим циклом
  /* USER CODE END WHILE */

 

Ещё раз соберём код, прошьём контроллер и проверим работу.

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

 

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

 

Исходный код

 

 

Отладочную плату можно приобрести здесь STM32F4-DISCOVERY

Дисплей с кнопками можно приобрести здесь Дисплей LCD 16×2 с кнопками

 

 

Смотреть ВИДЕОУРОК (нажмите на картинку)

 

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

2 комментария на “STM Урок 61. Модуль LCD 16×2. Работаем с кнопками. Часть 3
  1. Александр:

    Обучаюсь у вас программированию STМ с использованием Cube. Все достаточно толково (по крайней мере для тех кто в курсе). Но по данному уроку есть нюансы…
    1. Интересный подход для работы с клавиатурой, НО
    — избыточное количество флагов. Можно было состояние нажато и не нажато отслеживать одним флагом и т.д.
    — такой подход не дает вешать на одну кнопку несколько ф-ций (например по длительному нажатию с наблюдением за состоянием…).
    2. В объяснении часто присутствуют ошибки (во многих примерах), которые получается вылавливать только при рассмотрении исходного кода из примера (если это, конечно не является элементом обучения).
    А так большое спасибо… И удачи вам…

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

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

*