Всем привет! Поставил себе задачу разобраться с кнопками, для этого взял две библиотеки “класс титановый велосипед” и GyverButton - обе понял как работают, но со второй проблема не могу её скомпилировать, поэтому и прошу помощи и заранее извиняюсь что по ней обращаюсь сюда, знаю что на форуме не любят тут темы гайвера, МНЕ НУЖНА ПОМОЩЬ С КЛАССОМ. Конечно пишу я не в Arduinщ IDE, а в Atmel Studio 7 и переиначил библиотеку немного.
При компиляции выдает ошибку, не пойму что и где пропустил
Спойлер
Severity Code Description Project File Line
Error expected '=', ',', ';', 'asm' or '__attribute__' before '{' token atmega328P_LCD7565_433MHz_UART D:\Downloads\TvOut_atmega328+433 (1)\atmega328P_LCD7565_433MHz_UART_v.2.1\TVout_atmega328p\button.h 78
Error unknown type name 'class' atmega328P_LCD7565_433MHz_UART D:\Downloads\TvOut_atmega328+433 (1)\atmega328P_LCD7565_433MHz_UART_v.2.1\TVout_atmega328p\button.h 78
button.h
Спойлер
#ifndef GyverButton_h
#define GyverButton_h
#include "main.h"
#pragma once
#if defined(__AVR__)
#define _buttonRead() bool(*_pin_reg & _bit_mask)
#else
#define _buttonRead() digitalRead(_PIN)
#endif
#pragma pack(push,1)
typedef struct {
bool btn_deb: 1;
bool hold_flag: 1;
bool counter_flag: 1;
bool isHolded_f: 1;
bool isRelease_f: 1;
bool isPress_f: 1;
bool step_flag: 1;
bool oneClick_f: 1;
bool isOne_f: 1;
bool inv_state: 1;
bool mode: 1;
bool type: 1;
bool tickMode: 1;
bool noPin: 1;
bool counter_reset: 1; //Добавлен
} GyverButtonFlags;
#pragma pack(pop)
#define BTN_NO_PIN -1
#define HIGH_PULL 0
#define LOW_PULL 1
#define NORM_OPEN 0
#define NORM_CLOSE 1
#define MANUAL 0
#define AUTO 1
// Варианты инициализации:
// GButton btn; // без привязки к пину (виртуальная кнопка) и без указания типа (по умолч. LOW_PULL и NORM_OPEN)
// GButton btn(пин); // с привязкой к пину и без указания типа (по умолч. HIGH_PULL и NORM_OPEN)
// GButton btn(пин, тип подключ.); // с привязкой к пину и указанием типа подключения (HIGH_PULL / LOW_PULL) и без указания типа кнопки (по умолч. NORM_OPEN)
// GButton btn(пин, тип подключ., тип кнопки); // с привязкой к пину и указанием типа подключения (HIGH_PULL / LOW_PULL) и типа кнопки (NORM_OPEN / NORM_CLOSE)
// GButton btn(BTN_NO_PIN, тип подключ., тип кнопки); // без привязки к пину и указанием типа подключения (HIGH_PULL / LOW_PULL) и типа кнопки (NORM_OPEN / NORM_CLOSE)
class GButton {
public:
GButton(int8_t pin = BTN_NO_PIN, bool type = HIGH_PULL, bool dir = NORM_OPEN); // конструктор кнопки, принимает PIN пин, тип type (HIGH_PULL / LOW_PULL) и направление dir (NORM_OPEN / NORM_CLOSE)
// HIGH_PULL - кнопка подключена к GND, пин подтянут к VCC, pinMode - INPUT_PULLUP (по умолчанию)
// LOW_PULL - кнопка подключена к VCC, пин подтянут к GND, pinMode - INPUT
// NORM_OPEN - кнопка по умолчанию разомкнута (по умолчанию)
// NORM_CLOSE - кнопка по умолчанию замкнута
void setDebounce(uint16_t debounce); // установка времени антидребезга (по умолчанию 80 мс)
void setTimeout(uint16_t new_timeout); // установка таймаута удержания (по умолчанию 300 мс)
void setClickTimeout(uint16_t new_timeout); // установка таймаута между кликами (по умолчанию 500 мс)
void setStepTimeout(uint16_t step_timeout); // установка таймаута между инкрементами (по умолчанию 400 мс)
void setType(bool type); // установка типа кнопки (HIGH_PULL - подтянута к питанию, LOW_PULL - к gnd)
void setDirection(bool dir); // установка направления (разомкнута/замкнута по умолчанию - NORM_OPEN, NORM_CLOSE)
void setTickMode(bool tickMode); // (MANUAL / AUTO) ручной или автоматический опрос кнопки функцией tick()
// MANUAL - нужно вызывать функцию tick() вручную
// AUTO - tick() входит во все остальные функции и опрашивается сама
void tick(); // опрос кнопки
void tick(boolean state); // опрос внешнего значения (1 нажато, 0 не нажато) (для матричных, резистивных клавиатур и джойстиков)
boolean isPress(); // возвращает true при нажатии на кнопку. Сбрасывается после вызова
boolean isRelease(); // возвращает true при отпускании кнопки. Сбрасывается после вызова
boolean isClick(); // возвращает true при клике. Сбрасывается после вызова
boolean isHolded(); // возвращает true при удержании дольше timeout. Сбрасывается после вызова
boolean isHold(); // возвращает true при нажатой кнопке, не сбрасывается
boolean state(); // возвращает состояние кнопки
boolean isSingle(); // возвращает true при одиночном клике. Сбрасывается после вызова
boolean isDouble(); // возвращает true при двойном клике. Сбрасывается после вызова
boolean isTriple(); // возвращает true при тройном клике. Сбрасывается после вызова
boolean hasClicks(); // проверка на наличие кликов. Сбрасывается после вызова
uint8_t getClicks(); // вернуть количество кликов
uint8_t getHoldClicks();// вернуть количество кликов, предшествующее удерживанию
boolean isStep(byte clicks = 0); // возвращает true по таймеру setStepTimeout, смотри пример
void resetStates(); // сбрасывает все is-флаги и счётчики
private:
GyverButtonFlags flags;
uint8_t _PIN = 0;
uint16_t _debounce = 60;
uint16_t _timeout = 500;
uint16_t _click_timeout = 500;
uint16_t _step_timeout = 400;
uint8_t btn_counter = 0, last_counter = 0, last_hold_counter = 0;
uint32_t btn_timer = 0;
bool btn_state = false;
bool btn_flag = false;
#if defined(__AVR__)
volatile uint8_t *_pin_reg;
volatile uint8_t _bit_mask;
#endif
};
#endif
button.ccp
Спойлер
#include "button.h"
// ==================== CONSTRUCTOR ====================
GButton::GButton(int8_t pin, bool type, bool dir) {
if (pin != BTN_NO_PIN) {
_PIN = (uint8_t)pin;
flags.noPin = false;
} else {
flags.noPin = true;
}
setType(type);
flags.mode = false;
flags.tickMode = false;
flags.inv_state = dir;
}
// ==================== SET ====================
void GButton::setDebounce(uint16_t debounce) {
_debounce = debounce;
}
void GButton::setTimeout(uint16_t new_timeout) {
_timeout = new_timeout;
}
void GButton::setClickTimeout(uint16_t new_timeout) {
_click_timeout = new_timeout;
}
void GButton::setStepTimeout(uint16_t step_timeout) {
_step_timeout = step_timeout;
}
void GButton::setType(bool type) {
flags.type = type;
if (!flags.noPin) {
if (type) pinMode(_PIN, INPUT);
else pinMode(_PIN, INPUT_PULLUP);
// #if defined(__AVR__)
// _pin_reg = portInputRegister(digitalPinToPort(_PIN));
// _bit_mask = digitalPinToBitMask(_PIN);
// #endif
}
}
void GButton::setDirection(bool dir) {
flags.inv_state = dir;
}
void GButton::setTickMode(bool tickMode) {
flags.tickMode = tickMode;
}
// ==================== IS ====================
bool GButton::isPress() {
if (flags.tickMode) GButton::tick();
if (flags.isPress_f) {
flags.isPress_f = false;
return true;
} else { return false; }
}
bool GButton::isRelease() {
if (flags.tickMode) GButton::tick();
if (flags.isRelease_f) {
flags.isRelease_f = false;
return true;
} else { return false; }
}
bool GButton::isClick() {
if (flags.tickMode) GButton::tick();
if (flags.isOne_f) {
flags.isOne_f = false;
return true;
} else { return false; }
}
bool GButton::isHolded() {
if (flags.tickMode) GButton::tick();
if (flags.isHolded_f) {
flags.isHolded_f = false;
return true;
} else { return false; }
}
bool GButton::isHold() {
if (flags.tickMode) GButton::tick();
if (flags.step_flag) { return true;
} else { return false; }
}
bool GButton::state() {
if (flags.tickMode) GButton::tick();
return btn_state;
}
bool GButton::isSingle() {
if (flags.tickMode) GButton::tick();
if (flags.counter_flag && last_counter == 1) {
// last_counter = 0;
// flags.counter_flag = false;
flags.counter_reset = true;
return true;
} else { return false; }
}
bool GButton::isDouble() {
if (flags.tickMode) GButton::tick();
if (flags.counter_flag && last_counter == 2) {
// flags.counter_flag = false;
// last_counter = 0;
flags.counter_reset = true;
return true;
} else { return false; }
}
bool GButton::isTriple() {
if (flags.tickMode) GButton::tick();
if (flags.counter_flag && last_counter == 3) {
// flags.counter_flag = false;
// last_counter = 0;
flags.counter_reset = true;
return true;
} else { return false; }
}
bool GButton::hasClicks() {
if (flags.tickMode) GButton::tick();
if (flags.counter_flag) {
// flags.counter_flag = false;
flags.counter_reset = true;
return true;
} else { return false; }
}
uint8_t GButton::getClicks() {
// byte thisCount = last_counter; // Исключено 14.01.2021
// last_counter = 0;
flags.counter_reset = true;
return last_counter; // return thisCount; (замена) 14.01.2021
}
uint8_t GButton::getHoldClicks() {
if (flags.tickMode) GButton::tick();
return last_hold_counter; //return flags.hold_flag ? last_hold_counter : 0; (Замена) 14.01.2021
}
bool GButton::isStep(uint8_t clicks) {
if (flags.tickMode) { GButton::tick();
if (btn_counter == clicks && flags.step_flag && (millis0() - btn_timer >= _step_timeout)) {
btn_timer = millis0();
return true;
}
} else { return false; }
}
void GButton::resetStates() {
flags.isPress_f = false;
flags.isRelease_f = false;
flags.isOne_f = false;
flags.isHolded_f = false;
flags.step_flag = false;
flags.counter_flag = false;
last_hold_counter = 0;
last_counter = 0;
}
// ==================== TICK ====================
void GButton::tick(bool state) {
flags.mode = true;
btn_state = state ^ flags.inv_state;
GButton::tick();
flags.mode = false;
}
void GButton::tick() {
// читаем пин
if (!flags.mode && !flags.noPin) { btn_state = !_buttonRead() ^ (flags.inv_state ^ flags.type); }
uint32_t thisMls = millis0();
// нажатие
if (btn_state && !btn_flag) {
if (!flags.btn_deb) {
flags.btn_deb = true;
btn_timer = thisMls;
} else {
if (thisMls - btn_timer >= _debounce) {
btn_flag = true;
flags.isPress_f = true;
flags.oneClick_f = true;
}
}
} else {
flags.btn_deb = false;
}
// отпускание
if (!btn_state && btn_flag) {
btn_flag = false;
if (!flags.hold_flag) btn_counter++;
flags.hold_flag = false;
flags.isRelease_f = true;
btn_timer = thisMls;
if (flags.step_flag) {
last_counter = 0;
btn_counter = 0;
flags.step_flag = false;
}
if (flags.oneClick_f) {
flags.oneClick_f = false;
flags.isOne_f = true;
}
}
// кнопка удерживается
if (btn_flag && btn_state && (thisMls - btn_timer >= _timeout) && !flags.hold_flag) {
flags.hold_flag = true;
last_hold_counter = btn_counter;
//btn_counter = 0;
//last_counter = 0;
flags.isHolded_f = true;
flags.step_flag = true;
flags.oneClick_f = false;
btn_timer = thisMls;
}
// обработка накликивания
if ((thisMls - btn_timer >= _click_timeout) && (btn_counter != 0) && !btn_state) { //И здесь еще добавлен !btn_state
last_counter = btn_counter;
btn_counter = 0;
flags.counter_flag = true;
}
// сброс накликивания //Добавлено
if (flags.counter_reset) {
last_counter = 0;
flags.counter_flag = false;
flags.counter_reset = false;
}
}
main.h
Спойлер
#ifndef MAIN_H_
#define MAIN_H_
#define F_CPU 16000000UL
#define XTAL 16000000UL
#define SREG _SFR_IO8(0x3F)
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
#include "ftoa.h"
#include "millis_micros.h"
/*------Пины на которые подключим дисплей GMG12864-06D ST7565----*/
#define DISPLAY_CLK_DIR DDRD //SCL
#define DISPLAY_CLK_PORT PORTD
#define DISPLAY_CLK_PIN 5
#define DISPLAY_DATA_DIR DDRD //SI
#define DISPLAY_DATA_PORT PORTD
#define DISPLAY_DATA_PIN 4
#define DISPLAY_CS_DIR DDRB //CS
#define DISPLAY_CS_PORT PORTB
#define DISPLAY_CS_PIN 0
#define DISPLAY_DC_DIR DDRD //data comand = RS
#define DISPLAY_DC_PORT PORTD
#define DISPLAY_DC_PIN 6
#define DISPLAY_RESET_DIR DDRD //RSE
#define DISPLAY_RESET_PORT PORTD
#define DISPLAY_RESET_PIN 7
#define P_CPU_NS (1000000000UL / F_CPU) //Для дисплея
#define GET_UTF8_WIDTH u8g2_GetUTF8Width(&u8g2, lcd_buf) //+1
typedef bool boolean;
typedef uint8_t byte;
#define HIGH 0x1
#define LOW 0x0
#define INPUT 0x0
#define OUTPUT 0x1
#define INPUT_PULLUP 0x2
void pinMode(uint8_t pin, uint8_t mode);
void digitalWrite(uint8_t pin, uint8_t val);
int digitalRead(uint8_t pin);
#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )
#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )
#define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) )
#define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + (P))) )
#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) )
#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_mode_PGM + (P))) )
#define NOT_A_PIN 0
#define NOT_A_PORT 0
#define NOT_AN_INTERRUPT -1
#ifdef ARDUINO_MAIN
#define PA 1
#define PB 2
#define PC 3
#define PD 4
#define PE 5
#define PF 6
#define PG 7
#define PH 8
#define PJ 10
#define PK 11
#define PL 12
#endif
#define NOT_ON_TIMER 0
#define TIMER0A 1
#define TIMER0B 2
#define TIMER1A 3
#define TIMER1B 4
#define TIMER1C 5
#define TIMER2 6
#define TIMER2A 7
#define TIMER2B 8
#define TIMER3A 9
#define TIMER3B 10
#define TIMER3C 11
#define TIMER4A 12
#define TIMER4B 13
#define TIMER4C 14
#define TIMER4D 15
#define TIMER5A 16
#define TIMER5B 17
#define TIMER5C 18
#include "wiring_private.h"
#include "button.h"
#endif /* MAIN_H_ */