Добрый день, может кто подскажет. Использую где-то найденный код для чтения кнопок. Код нравится тем, что не зависает в цикле или задержке для исключения дребезга кнопок.
Вот файл button.h
#define BUTTON_H
//настройки параметров библиотеки
#define BTN_LOCK_TIME 20 /* время обработки дребезга в милисекундах (10-100) */
#define BTN_LONG_TIME 1000 /* время фиксации длинного нажатия в милисекундах (1000 - 2500) */
//настройка портов и линий
#define BTN_PORT PORTD /* порт кнопок */
#define BTN_PIN PIND
#define BTN_POWER (1<<0) /* линии кнопок */
#define BTN_UP (1<<5)
#define BTN_DOWN (1<<6)
//определения флагов кнопок
#define BTN_SHRT_UP (1<<0) /* флаги короткого нажатия кнопок */
#define BTN_SHRT_DOWN (1<<1)
#define BTN_SHRT_POWER (1<<2)
#define BTN_LONG_UP (1<<4) /* флаги длинного нажатия кнопок */
#define BTN_LONG_DOWN (1<<5)
#define BTN_LONG_POWER (1<<6)
//объявления функций
void BtnInit (void); //инициализация библиотеки
uint8_t BtnGet (void); //функция чтения маски нажатой кнопки
void BtnExe (void); //функция циклического опроса кнопок (вызывать с частотой 100Гц, например из прерывания)
#endif /* BUTTON_LIB_ */
и файл button.c
#include "button.h"
//-----------------------------------------------------------------------------------------------------------------------
//глобальные переменные
volatile uint8_t BtnFlags; //регистр флагов нажатых кнопок
//-----------------------------------------------------------------------------------------------------------------------
//функция инициализации портов (вызвать перед использованием библиотеки)
void BtnInit (void)
{
BTN_PORT |= (BTN_UP| BTN_DOWN | BTN_POWER);//подтяжка кнопок
}
//-----------------------------------------------------------------------------------------------------------------------
//функция чтения маски нажатых кнопок
//возвращает маску нажатых кнопок (биты 0-3 - коротк нажат, биты 4-7 - длинн нажат)
uint8_t BtnGet (void)
{
asm ("cli");
uint8_t temp = BtnFlags;
BtnFlags = 0;
asm ("sei");
return temp;
}
//-----------------------------------------------------------------------------------------------------------------------
//функция циклического опроса кнопок (вызывать с частотой 100Гц, например в прерывании)
void BtnExe (void)
{
static uint8_t BtnLockBit; //защелка (защита от дребезга)
static uint8_t BtnLockCoun; //счетчик защелки (защита от дребезга)
static uint8_t BtnLongCoun; //счетчик длинного нажатия
static uint8_t BtnMascLast; //запомнить маску нажатой кнопки для анализа после отжатия кнопки
uint8_t BtnMask = 0;
if (~BTN_PIN & BTN_UP) BtnMask = BTN_SHRT_UP;//формирование маски нажатых кнопок
if (~BTN_PIN & BTN_DOWN) BtnMask = BTN_SHRT_DOWN;
if (~BTN_PIN & BTN_POWER) BtnMask = BTN_SHRT_POWER;
//основной алгоритм обработки событий кнопки
if (BtnMask){ //клавиша нажата
BtnMascLast = BtnMask; //запоминаем для использования после отпускания кнопки
if (BtnLockCoun < (BTN_LOCK_TIME/10)){
BtnLockCoun++; //обработка дребезга
return;
}
BtnLockBit=1; //нажатие зафиксировано
if (BtnLongCoun >= (BTN_LONG_TIME/10))
return;
if (++BtnLongCoun >= (BTN_LONG_TIME/10))
BtnFlags |= (BtnMask << 4); //установка бита длинного нажатия (старшие 4 бита флагов ButtonByte)
}
else{ //клавиша отжата
if (BtnLockCoun){ //обработка дребезга
BtnLockCoun --;
return;
}
if (! BtnLockBit) //отжатие зафиксировано
return;
BtnLockBit =0;
if (BtnLongCoun < (BTN_LONG_TIME/10))
BtnFlags |= BtnMascLast; //установка бита короткого нажатия (младшие 4 бита флагов ButtonByte)
BtnLongCoun = 0;
}
}
Необходимо добавить отслеживание нажатия или отпускания кнопки POWER с учетом дребезга. В существующем коде определяется как длинное нажатие. А нужно если нажали POWER - включаем таймер, а если отпустили отключаем таймер.
Вот файл button.h
Спойлер
#ifndef BUTTON_H#define BUTTON_H
//настройки параметров библиотеки
#define BTN_LOCK_TIME 20 /* время обработки дребезга в милисекундах (10-100) */
#define BTN_LONG_TIME 1000 /* время фиксации длинного нажатия в милисекундах (1000 - 2500) */
//настройка портов и линий
#define BTN_PORT PORTD /* порт кнопок */
#define BTN_PIN PIND
#define BTN_POWER (1<<0) /* линии кнопок */
#define BTN_UP (1<<5)
#define BTN_DOWN (1<<6)
//определения флагов кнопок
#define BTN_SHRT_UP (1<<0) /* флаги короткого нажатия кнопок */
#define BTN_SHRT_DOWN (1<<1)
#define BTN_SHRT_POWER (1<<2)
#define BTN_LONG_UP (1<<4) /* флаги длинного нажатия кнопок */
#define BTN_LONG_DOWN (1<<5)
#define BTN_LONG_POWER (1<<6)
//объявления функций
void BtnInit (void); //инициализация библиотеки
uint8_t BtnGet (void); //функция чтения маски нажатой кнопки
void BtnExe (void); //функция циклического опроса кнопок (вызывать с частотой 100Гц, например из прерывания)
#endif /* BUTTON_LIB_ */
Спойлер
#include <avr/io.h>#include "button.h"
//-----------------------------------------------------------------------------------------------------------------------
//глобальные переменные
volatile uint8_t BtnFlags; //регистр флагов нажатых кнопок
//-----------------------------------------------------------------------------------------------------------------------
//функция инициализации портов (вызвать перед использованием библиотеки)
void BtnInit (void)
{
BTN_PORT |= (BTN_UP| BTN_DOWN | BTN_POWER);//подтяжка кнопок
}
//-----------------------------------------------------------------------------------------------------------------------
//функция чтения маски нажатых кнопок
//возвращает маску нажатых кнопок (биты 0-3 - коротк нажат, биты 4-7 - длинн нажат)
uint8_t BtnGet (void)
{
asm ("cli");
uint8_t temp = BtnFlags;
BtnFlags = 0;
asm ("sei");
return temp;
}
//-----------------------------------------------------------------------------------------------------------------------
//функция циклического опроса кнопок (вызывать с частотой 100Гц, например в прерывании)
void BtnExe (void)
{
static uint8_t BtnLockBit; //защелка (защита от дребезга)
static uint8_t BtnLockCoun; //счетчик защелки (защита от дребезга)
static uint8_t BtnLongCoun; //счетчик длинного нажатия
static uint8_t BtnMascLast; //запомнить маску нажатой кнопки для анализа после отжатия кнопки
uint8_t BtnMask = 0;
if (~BTN_PIN & BTN_UP) BtnMask = BTN_SHRT_UP;//формирование маски нажатых кнопок
if (~BTN_PIN & BTN_DOWN) BtnMask = BTN_SHRT_DOWN;
if (~BTN_PIN & BTN_POWER) BtnMask = BTN_SHRT_POWER;
//основной алгоритм обработки событий кнопки
if (BtnMask){ //клавиша нажата
BtnMascLast = BtnMask; //запоминаем для использования после отпускания кнопки
if (BtnLockCoun < (BTN_LOCK_TIME/10)){
BtnLockCoun++; //обработка дребезга
return;
}
BtnLockBit=1; //нажатие зафиксировано
if (BtnLongCoun >= (BTN_LONG_TIME/10))
return;
if (++BtnLongCoun >= (BTN_LONG_TIME/10))
BtnFlags |= (BtnMask << 4); //установка бита длинного нажатия (старшие 4 бита флагов ButtonByte)
}
else{ //клавиша отжата
if (BtnLockCoun){ //обработка дребезга
BtnLockCoun --;
return;
}
if (! BtnLockBit) //отжатие зафиксировано
return;
BtnLockBit =0;
if (BtnLongCoun < (BTN_LONG_TIME/10))
BtnFlags |= BtnMascLast; //установка бита короткого нажатия (младшие 4 бита флагов ButtonByte)
BtnLongCoun = 0;
}
}
