Урок 61
Модуль LCD 16×2. Работаем с кнопками
Часть 2
Продолжаем работать с модулем LCD с кнопками и регулятором контрастности.
В прошлой части занятия мы создали проект, настроили его, добавили необходимые переменные и уже написали одну функцию для определениясостояния кнопок.
Писать нам ещё много, поэтому продолжим.
Теперь напишем функцию обработки состояния кнопки и установки окончательного статуса
//———————————————————
void Read_Button_State (uint8_t b)
{
if ((button_state[b]&ST_LOCKED)!=0) return;
if (Read_Button_Press(b)==ST_UNPRESSED)
{
if (but_cnt[b]>0)
{
but_cnt[b]—;
}
else
{
if((button_state[b]&ST_PRESSED)!=0)
{
button_state[b] |= ST_UNPRESSURE;
button_state[b] &= ~ST_PRESSED;
button_state[b] |= ST_UNPRESSED;
}
}
}
else
{
if (but_cnt[b]<5)
{
but_cnt[b]++;
}
else
{
if((button_state[b]&ST_UNPRESSED)!=0)
{
button_state[b] |= ST_PRESSURE;
button_state[b] &= ~ST_UNPRESSED;
button_state[b] |= ST_PRESSED;
}
}
}
}
//———————————————————
Также для отвязыания алгоритма отслеживания статуса кнопок от основного кода можно воспользоваться таймером.
Но во избежание различных коллизий в качестве таймера у нас выступит обработчик прерываний от ADC.
Вы можете воспользоваться и штатными таймерами и системным таймером по желанию. Только у меня почему-то при их использовании появлялись висяки, может надо было настроить приоритеты, но я заморачиваться не стал.
В том же файле button.c напишем обработчик событий от нашего «самодельного» таймера
//———————————————————
void TIM_Callback(void)
{
}
Напишем на неё прототип в button.h
//————————————————
void TIM_Callback(void);
//————————————————
#endif /* BUTTON_H_ */
Так как у нас ADC1 находится на шине APB2, которая у нас работает на скорости 84 МГц.
Делитель у нас установлен 6, а одно измерение длится около 13 циклов, то получается, что обработчик прерывания работает приблизительно раз в микросекунду, а нам пробегаться по статусам кнопок вполне достаточно и раз в одну милисекунду.
Добавим в файле main.c глобальную переменную для счета циклов в обработчике прерываний от АЦП
uint16_t ADC_Data=0;
uint16_t adctim_cnt=0;
Теперь в обработчике от АЦП добавим следующий код
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc1)
{
ADC_Data = HAL_ADC_GetValue(hadc1);
if(adctim_cnt>1000)
{
adctim_cnt=0;
TIM_Callback();
}
adctim_cnt++;
}
Также не лишним будет добавить принудительное включение АЦП в обработчике, так как почему-то режим автопродолжения, который выставлен в Cube, у меня после обновления и его и Keil не заработал. То есть, если у вас будет работать и без этого, то включать не надо
ADC_Data = HAL_ADC_GetValue(hadc1);
HAL_ADC_Start_IT(hadc1);
Таким образом, мы в наш обработчик для запуска считывания состояний кнопок будем попадать приблизительно раз в милисекунду.
Добавим видимость нашего АЦП в файл button.c
uint16_t adc_value=0;
extern ADC_HandleTypeDef hadc1;
Напишем ещё одну глобальную переменную для того, чтобы до инициализации кнопок наш код в обработчике не работал
static uint8_t but_cnt[5]={0};
static uint8_t tim_stat=0;
Напишем функцию инициализации кнопок при старте программы
//———————————————————
void Buttons_Ini(void)
{
uint8_t i;
//обнулим счётчики и сбросим статусы
for (i=0;i<5;i++)
{
button_state[i] = ST_UNPRESSED;
}
tim_stat=1;
}
//———————————————————
Здесь мы установим первоначальные статусы кнопкам, а также запустим таймер.
Напишем на данную функцию прототип в файле button.h
void SysTick_Callback(void);
void Buttons_Ini(void);
Вызовем её в main()
HAL_ADC_Start_IT(&hadc1);
HAL_Delay(500);
Buttons_Ini(); //инициализируем состояние кнопок
На этом мы завершим данную часть. А уже работать с написанными функциями будем в следующей части.
Предыдущая часть Программирование МК STM32 Следующая часть
Отладочную плату можно приобрести здесь STM32F4-DISCOVERY
Смотреть ВИДЕОУРОК
Добавить комментарий