Ночер всем добрый. осваиваю потихоньку PlatformIO. заодно изобретаю велосипед по опросу кнопок. гуру гляньте пожалуйста. может ли иметь такой способ опроса кнопок, место под солнцем? (написал все в PlatformIO, пишется намного быстрее чем в Ардуино ИДЕ, но компилирую в "родном" ардуиновском он меньше претензий предъявляет ) код по опросу кнопок Код (C++): #include <Arduino.h> uint32_t time_butt = 0; bool up_butt=0; //флаг факта нажатия кнопки вверх bool down_butt=0; // флаг нажатия кнопки вниз bool OK_butt=0; // флаг нажатия кнопки подтверждения bool cancel_butt=0; // флаг нажатия кнопки отмена //сброс флагов после выполнения действий void setup() { DDRC &= ~((1<<0)|(1<<1)|(1<<2)|(1<<3)); //A0 A1 A2 A3 вход } void loop() { uint32_t time = millis(); //считываем порт с if( (PINC & (1<<0))|| (PINC & (1<<1))||(PINC & (1<<2))||(PINC & (1<<3))&&time-time_butt>=30 )//если нажатие хоть на одну кнопку { byte A =PINC; // передаем значение в переменную А //сравниваем что было нажато и по результату взводим флаги switch (A) { case 0b00000001: up_butt=1; break; case 0b00000010: down_butt=1; break; case 0b00000100: OK_butt=1; break; case 0b00001000: cancel_butt=1; break; default: } time_butt=time; } //проверка на отжатие кнопки в принципе это и не к чему if( (~PINC & (1<<0))&& (~PINC & (1<<1))&&(~PINC & (1<<2))&&(~PINC & (1<<3))&&time-time_butt>=30 ) time_butt=time; }
А что нужно то? С первого взгляда, нет сброса переменных нажатия кнопки. Нажали кнопку - переменная перешла в 1, и осталась в 1 до выключения контроллера. Обработка дребезга - очень упрощена. Я уже писал про оптимальный, с моей точки зрения, алгоритм опроса кнопок, могу выложить еще раз, в Вашем варианте, но многие здесь его "не приветствуют" . Сложный говорят, можно "проще" через буфера. По памяти и быстродействию, думаю точно будет короче и быстрее .
Спасибо за комментарии. Хотел чтоб глянули, дичь это или нет) Значит можно) флаги будут сбрасываться после выполнения действия в другой части кода. На симуляторе вроде работает
Дефаулт это я уже здесь дописал, пришла мысль , что могут и 2 кнопки разом нажаты. Нужно все предусмотреть. Отжатие не нужно отслеживать. Долгих и двойных нажатий не планируется, так как возможно игрушкой будут пользоваться не программисты и делал чтоб было интуитивно понятным управление.
Понятно. Ваш код (без сброса флагов нажатий кнопок, и анализа одновременных нажатий): Скетч использует 670 байт (2%) памяти устройства. Всего доступно 30720 байт. Глобальные переменные используют 17 байт (0%) динамической памяти, оставляя 2031 байт для локальных переменных. Максимум: 2048 байт. Код с полноценной обработкой дребезга, независимо и параллельно, на четырех входах, сбросом флагов, и анализом одновременных нажатий (анализ отпускания кнопок закомментировал ): Код (C++): #define PIN_READ_TO 10L // 10 ms периодичность проверки входов. Оптимальным является интервал 5-10мс. соответственно в результате сигнал о нажатии будет получен через 20-40мс (в данном случае 40мс) #define PIN_IN_NUMB 4 // количество используемых входов значение от 1 до 8. //------------------ ФУНКЦИЯ УСТР. ДРЕБЕЗГА -------------------------------------- // Глобальные переменные // биты в байтах ниже взводятся обработчике дребезга, можно в в прерывании от таймера и сбрасываются программой обработчиком событий byte LATCH_ON = 0; // вход перешел в 1 //byte LATCH_OFF = 0; // вход вернулся в 0 uint8_t vc_debounce(uint8_t SWKEYS) // Verical_Couners_debounce, вызывается каждые 10 мсек, можно из таймера { // в SWKEYS состояние вводов static uint8_t SLATCH = 0; // текущее устоявшееся значение входов после устранения дребезга static uint8_t VCBIT0 = 0; // счетчик бит 0 static uint8_t VCBIT1 = 0; // счетчик бит 1 uint8_t vcmask = 0; // Маска uint8_t vctemp = 0; // vcmask = SWKEYS ^ SLATCH; // скинем счетчики для установившихся и неактивных значений VCBIT0 &= vcmask; VCBIT1 &= vcmask; // Каждая '1' в SLATCH представляет установившееся значение // каждый '0' установившееся нулевое значение SLATCH ^= (vctemp = vcmask & VCBIT0 & VCBIT1); if( vctemp ) // есть изменения входов, взведем флаги { LATCH_ON |= vctemp & SWKEYS; // взведем биты нажатых кнопок и сработавших входов. // LATCH_OFF |= vctemp & ~SWKEYS; // Биты сбрасываются в обработчиках. } VCBIT1 ^= (vcmask & VCBIT0); // инкрементируем счетчик. VCBIT0 ^= (vcmask); } void setup() { DDRC &= ~((1<<0)|(1<<1)|(1<<2)|(1<<3)); //A0 A1 A2 A3 вход } void Input_On(byte number) { // выполним действие по нажатию на кнопку. номер кнопку в переменной "number" } /* void Input_Off(byte number) { // ЕСЛИ НУЖНО! выполним действие по отпусканию кнопки. номер кнопку в переменной "number" } */ void loop() { static uint32_t LastPinReadMs = 0 ; // переменная для сохранения времени, когда были считаны значения с цифорвых входов uint8_t current_state; // переменная для текущего состояние по кнопкам byte j,i; if ((millis() - LastPinReadMs) > PIN_READ_TO) // выполняется каждые 10мс (PIN_READ_TO) { //----------------------- current_state= PINC & ((1<<0)|(1<<1)|(1<<2)|(1<<3)); // читаем значение vc_debounce(current_state); // 2) отбросим дребезг по всем входам, на основании предыдущих проверок (игнорируем состояния, держащиеся на входе менее 4 проверок подряд) LastPinReadMs = millis(); // запомним время // if (LATCH_ON != 0 || LATCH_OFF != 0 ) // Если есть изменения на входах - обработаем. if (LATCH_ON != 0 ) // Если есть изменения на входах - обработаем. { for (i=1,j=0; j < PIN_IN_NUMB; j++,i=i<<1) // пробежимся по всем входам { if (LATCH_ON & i) // Если копка была нажата или вход перешел в ON { Input_On(j); LATCH_ON &= ~i; // Обязательно сбросим бит, так как данное событие обработано } /* if (LATCH_OFF & i) // Если копка была отпущена или вход перешел в OFF ЕСЛИ НУЖНО. { Input_Off(j); LATCH_OFF &= ~i; // Обязательно сбросим бит, так как данное событие обработано } */ } } } // --------------------- // ваш код.... } Скетч использует 644 байт (2%) памяти устройства. Всего доступно 30720 байт. Глобальные переменные используют 17 байт (0%) динамической памяти, оставляя 2031 байт для локальных переменных. Максимум: 2048 байт. Код короче, по памяти столько же.
Дарю макрос, по которому можно определить состояние одного бита в регистре Код (C++): #define BitIsClear(reg, bit) ((reg & (1<<(bit))) == 0) //пример: if (BitIsClear(PORTB,1)) {...} //если бит очищен И не надо ничего никуда копировать. Устранить дребезг - вызывать функцию по таймеру. Ну раз 50 в секунду хватит. И отзывчивость сохранишь, и от дребезга избавишься. Плюсом, если внутри завести счетчик (в структуре кнопки, например), то можешь отслеживать длинные и короткие нажатия.
Макрос - не новость, толку -то от него???? Хотите все входы последовательно опрашивать, последовательно, для каждого входа, анализировать состояние - пожалуйста, флаги Вам в руки И Супермен расстроил! Одним словом, Кто как хочет, тот так и "делает" Мне так удобнее, уже говорил об этом! Многие не понимают прелести, данного варианта, ну что же тут сделаешь, может когда-нибудь поймут
так а можешь алгоритм нарисовать, а то у меня глаза в разные стороны смотрят и все коды двоятся))) Может и возьму на вооружение. Особенно, когда 10 или больше кнопок)))
Уже описал все здесь . Больше года назад. В ответ была только критика , не поняли ! Когда разобрался, лет 15 назад, честно говоря прибалдел от оптимальности, скорости и компактности. Знакомые, после объяснения, только этим вариантом и пользуются.
Это пример, это уже после устранения дребезга по всем входам. Обрабатываем установившееся значение. Его все равно нужно обрабатывать. А устранение дребезга - это 10 строчек для 8 или 16 входов одновременно. (в зависимости от разрядности регистров) Без for, и while. Я устраняю дребезг в прерывании от таймера, а флаги анализирую в main или loop
Это в дизасме 10 машиноинструкций? А то ведь в абдурино 1 строчка кода выливается в 100 машинных инструкций(((
Ну не знаю, мне так проще Какие 100 инструкций, там булевые операции... И Супермен расстроил окончательно!!! Все, надоело, "делайте" как хотите, мне все равно.
Не обижайся, чо))) Я просто хочу понять - вот в прерывании таймера мы опросили порт. Потом идёт функция проверки на дребезг. А зачем? Если между двумя прерываниями таймера выясняется, что кнопка ещё дребезжит, значит период опроса кнопок надо увеличить. И не нужны никакие функции проверки на дребезг - таймер все за нас сделал.