Как заставить встроенный светодиод мигать с частотой 5 Гц с помощью прерываний
Задача такая: после пяти нажатий на ОК встроенный светодиод начинает мигать с частотой 5Гц с использованием прерывания. После восьмого нажатия на ОК мигание (и свечение) должно прекратиться. Почему не работает мигание
bool ledState = false;
volatile bool ledOn = true;
void setup(){
TCCR2A = 0;
TCCR2B = 0;
TIMSK2 = 0;
TCNT2 = 0;
OCR2A = 77;
TCCR2B |= (1 << CS22) | (1 << CS21) | (1 << CS20);
TIMSK2 |= (1 << OCIE2A);
pinMode(13, OUTPUT);
}
void loop(){
if(button5.buttonPressedCount >= 5 && button5.buttonPressedCount < 8){
ledState = true;
}
if(button5.buttonPressedCount > 7){
ledState = false;
}
}
ISR(TIMER2_COMPA_vect){
if(ledState){
digitalWrite(13, ledOn);
ledOn = !ledOn;
}
}
@Good York, 👍1
Обсуждение1 ответ
На Uno (микроконтроллер ATmega328P) таймеры 0 и 2 только 8-битные: они не могут считать больше 255. Таймер 1, с другой стороны, 16-битный. Это самый удобный таймер для генерации низких частот.
Кстати, о частотах... Один период светодиода включает два переключателя (включить, затем выключите). Таким образом, если вы хотите, чтобы светодиод мигал с частотой 5 Гц, переключатель действие должно происходить на частоте 10 Гц. Учитывая, что процессор работает на частоте 16 МГц, это означает, что вы должны переключать светодиод каждые 1 600 000 циклов процессора.
Если вы установите для предварительного делителя значение 1024, вам придется считать 1 600 000/1 024 = 1 562,5 цикла таймера. Вы не можете считать нецелое число кол-во тактов, но вас наверное не волнует такая точность. Если вам не все равно, установите прескалер на 256 и посчитайте 1 600 000/256 = 6250 циклов таймера, установив для регистра соответствия сравнения значение 6249.
И последнее: имейте в виду, что в обычном режиме подсчета таймер считает до своего максимального значения (65 535 или 255 на 8-битном таймере) и затем перезагружается с нуля. Если вы хотите, чтобы он подсчитывал только значение, установленное в регистр соответствия сравнения, вы должны выбрать соответствующую форму волны режим генерации: быстрый режим PWM, который позволяет вам контролировать значение TOP с OCR1A.
тогда это должно выглядеть так? TCCR1A = 0;
TCCR1B = 0;
ТИМСК1 = 0;
ТЦНТ1 = 0;
ОКР1А = 6249; // Установить значение совпадения сравнения для прескалера 256
TCCR1B |= (1 << CS12); // Установить прескалер на 256
TIMSK1 |= (1 << OCIE1A); // Разрешить прерывание при сравнении соответствия A
, @Good York
@GoodYork: прочитайте техническое описание и узнайте, как установить соответствующий режим генерации сигналов., @Edgar Bonet
примерно так: TCCR1A = (1 << WGM11) | (1 << COM1A0);
TCCR1B = (1 << WGM12) | (1 << WGM13) | (1 << CS12);
TIMSK1 = (1 << OCIE1A);
OCR1A = 6250;
, @Good York
- Как сгенерировать аппаратное прерывание в mpu6050 для пробуждения Arduino из режима SLEEP_MODE_PWR_DOWN?
- Arduino непрерывно считывает значение АЦП с помощью прерывания
- Как правильно использовать volatile переменные в Arduino?
- Как прервать функцию цикла и перезапустить ее?
- 4-битный счетчик вверх и вниз
- Включить и отключить отдельные прерывания
- Управление функцией включения на драйвере микрошагового устройства
- Захват прерывания на обоих фронтах, когда он установлен на RISING или FALLING
Почему
OCR2A = 77;
?, @Edgar BonetЗначение для получения частоты 5 Гц с делителем 1024, @Good York
Не могли бы вы объяснить в вопросе, как вы переходите от «f = 5 Гц» к «OCR2A = 77»?, @Edgar Bonet
таймер будет работать на частоте 16 МГц / 1024 = 15,625 кГц, поэтому желаемая частота прерывания = (77 + 1) * 15,625 кГц / 1024 = 5 Гц, @Good York
Этот расчет неверен., @Edgar Bonet
тогда какие должны быть значения?, @Good York
15,625 кГц / 5 Гц = 3125. Поэтому я бы установил OCR2A на 3125. Значение 77 будет примерно 203 Гц., @chrisl
Я установил 3125, если это правильный сигнал: [ссылка](https://imgur.com/a/N4wQMrl), @Good York
Не могли бы вы использовать Таймер 1 вместо Таймера 2?, @Edgar Bonet
да могу, тогда какие значения ставить?, @Good York