Я пытаюсь использовать прерывания смены контактов, чтобы обнаружить нажатые кнопки. До сих пор я никогда не работал с такими прерываниями, и есть некоторые проблемы, поэтому я хочу убедиться, что это правильное использование.
Если я правильно понял таблицу, для использования прерывания смены штифта необходимо сделать следующее:
- Установите, какие PIN-коды вы хотите контролировать в реестре PCMSK
- Включите регистр ПИН-кодов для управления прерыванием смены пинов (PCICR)
- Включить прерывания
- Используйте соответствующий вектор прерывания
Проект: Простой Moodlamp, Цвета управляются с помощью 4 кнопок.
Настроить:
- Atmega168A-PU
- 4 мини кнопочных переключателя
- МОП-транзисторы для управления моим 3-ваттным светодиодом RGB
Вот код, который я использую, который не работает должным образом:
#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define BUTTON1 (1<<PC5)
#define BUTTON2 (1<<PC4)
#define BUTTON3 (1<<PC3)
#define BUTTON4 (1<<PC2)
#define GREEN (1<<PB1)
#define BLUE (1<<PB2)
#define RED (1<<PB3)
void init() {
// enable LED
DDRB |= GREEN;
DDRB |= BLUE;
DDRB |= RED;
// button pullups
PORTC |= BUTTON1;
PORTC |= BUTTON2;
PORTC |= BUTTON3;
PORTC |= BUTTON4;
// pin change interrupts for buttons
PCMSK1 |= PCINT13;
PCMSK1 |= PCINT12;
PCMSK1 |= PCINT11;
PCMSK1 |= PCINT10;
// enable pin change for buttons
PCICR |= PCIE2;
sei();
}
ISR(PCINT2_vect) {
PORTB = BLUE;
}
void ledTest() {
PORTB ^= RED;
_delay_ms(250);
PORTB ^= RED;
_delay_ms(250);
PORTB ^= RED;
_delay_ms(250);
PORTB ^= RED;
PORTB ^= BLUE;
_delay_ms(250);
PORTB ^= BLUE;
_delay_ms(250);
PORTB ^= BLUE;
_delay_ms(250);
PORTB ^= BLUE;
PORTB ^= GREEN;
_delay_ms(250);
PORTB ^= GREEN;
_delay_ms(250);
PORTB ^= GREEN;
_delay_ms(250);
PORTB ^= GREEN;
}
int main() {
init();
ledTest();
_delay_ms(500);
PORTB |= GREEN;
while(1) {
_delay_ms(100);
}
}
Примечание: кнопки должны быть отменены. Так как я пытаюсь сделать это шаг за шагом, и это не должно иметь значения для включения светодиода, я проигнорировал это здесь.
Вопрос: правильно ли я пытаюсь использовать прерывания?
Проблемы с моей настройкой:
- Кнопки 1-3 полностью игнорируются.
- Button4 запускает сброс Atmega
Вещи, которые я проверил:
- Кнопки никак не связаны с ПИН-кодом сброса
- Кнопки правильно подключены к GND при нажатии
- Кнопки не подключены к GND, если не нажаты
Кнопки работают хорошо, если я использую их без прерывания, например:
if (! (PINC & BUTTON4)) {PORTB ^ = СИНИЙ; }
- 16 МГц внешний кристалл / внутренний кристалл
- Любые ошибки в маршрутизации
- Я использую 100 нФ конденсатор между PWR и GND на Atmega
- VCC (7), GND (8), GND (22), AVCC (20) подключены (так как мне не нужен AREF, он не подключен)
источник
Ответы:
Прерывания смены контактов, как правило, не являются хорошим способом определения действий кнопок. Это происходит потому, что механические кнопки отскакивают, и вы получите много бессмысленных прерываний, а затем вам все равно придется делать отладку в любом случае.
Лучшим способом является периодическое прерывание, например, каждые 1 мс (частота 1 кГц). На большинстве процессоров это длительное время, поэтому доля времени, затрачиваемого на прерывание, будет небольшой. Просто выберите состояние кнопки для каждого прерывания. Объявите новое состояние кнопки, если вы видели новое состояние 50 мс подряд. 50 мс длиннее, чем большинство кнопок отскакивают, но все еще достаточно коротки, чтобы люди не замечали или не заботились о задержке.
Обратите внимание, что таким образом вы также можете обрабатывать несколько кнопок в одном периодическом прерывании в 1 мс. Все, что вам нужно, это один счетчик для каждой кнопки.
Подробнее о времени отклика:
Иногда, как и в этом случае, кто-то говорит, что 50 мс - это слишком длительное время отката. Это не относится к обычным кнопкам, нажимаемым людьми. Это может быть проблемой, возможно, в очень критичных по времени приложениях, таких как секундомер, но до сих пор я не сталкивался с ними. Я проверял это в начале 1980-х, и многие другие тоже.
Это правда, что типичное время отскока кнопки составляет около 10 мс, а почти все устанавливаются на 25 мс. Ограничивающим фактором времени отклика является человеческое восприятие. 50 мс немного короче, чем когда люди начинают замечать задержку, когда они ее не ищут. Даже тогда, это занимает намного больше времени, чтобы это раздражало. В некоторых случаях человек может обнаружить разницу между задержкой в 50 мс и 0 мс, если он специально ищет ее , но это совсем не то, что нажать кнопку и увидеть, что что-то происходит, и не думать о задержке.
Таким образом, 50 мс - это хорошее время отказов, поскольку задержка ниже предела восприятия в обычных приложениях, намного ниже предела раздражения и значительно превышает время отказов большинства коммутаторов. Я нашел переключатели, которые отскакивали почти так долго, так что вы могли бы также перейти к пределу восприятия, поскольку терять нечего.
Я сделал много продуктов с кнопками, отсеиваемыми прошивкой, используя время ожидания 50 мс. Ни разу клиент не упомянул даже о задержке. Они все приняли кнопки как работающие без проблем.
источник
Прерывания смены булавки - лучший способ отменить, чем опрос. Прерывание обычно проходит через некоторую логику, такую как D-Flip Flop или D-Latch. Хотя это действительно так, реализовать эту процедуру отладки с помощью компиляторов более высокого уровня сложнее. Как только прерывание происходит, флаг прерывания не очищается, и разрешение прерывания очищается до тех пор, пока не произошла задержка. Как только задержка произошла, проверяется состояние контакта, и если он все еще находится в заданном состоянии, которое вызвало прерывание, состояние кнопки изменяется, и флаг прерывания очищается, и устанавливается разрешение прерывания. Если не в состоянии, которое вызвало инициирование, устанавливается разрешение прерывания, и состояние остается тем же. Это освобождает процессор для других задач. Периодическое прерывание тратит время в программе.
источник
Неправильно. ПК INT является лучшим вариантом. Если вы используете опрос для проверки состояния кнопки, большую часть времени ничего не будет выполнено. Вы тратите много драгоценного процессорного времени. ПК INT позволяет выполнять действия только по запросу.
Правильно о подпрыгивании. Тем не менее, вы НИКОГДА не должны отсоединять кнопку / переключатель внутри процедуры прерывания (та же самая причина: потеря процессорного времени). ISR должны быть очень короткими и эффективными с точки зрения кода. Просто используйте аппаратный дебасинг. Держите свое программное обеспечение в чистоте!
Аппаратная отладка более удобна, см. Здесь / RC debouncing + триггер Шмитта для справки. Я использовал его для ПК бесчисленное количество раз, он никогда не подводил.
Так что да, вы можете (и должны) использовать ПК INT для получения состояния кнопки. Но вы также должны использовать правильное аппаратное устранение неполадок.
источник