Прерывание режима CTC Arduino Uno не срабатывает
Я пытаюсь сгенерировать мигание светодиода через 4 секунды с помощью прерывания, но прерывание не срабатывает ни разу. Просьба: если у вас есть arduino uno r3, пожалуйста, проверьте на своем конце и сообщите мне результат. Я несколько раз читал раздел счетчика таймера и применял все, что мог, например: -
- Включено глобальное прерывание
- Выберите режим CTC
- Включить прерывание для OCIE0A
- Предварительное масштабирование до clk/1024
- Инициализация OCR0A
- Когда OCR0A равен TCNT0, генерируется прерывание
int var;
void setup() {
// поместите сюда код установки для однократного запуска:
SREG = SREG | (1<<7); // Глобальное прерывание разрешено
TCCR0A = TCCR0A | (1<<WGM01); // Очистить счетчик в режиме сравнения совпадений
OCR0A = 255; // при равенстве TCNT будет сгенерировано прерывание OCR0
TIMSK0 = TIMSK0 | (1<<OCIE0A); // Сравнение выходных данных соответствует разрешению прерывания
TCCR0B = TCCR0B | (1<<CS01) | (1<<CS02); // Предварительное масштабирование на 1024
DDRB = DDRB | (1<<5);
Serial.begin(9600); // Тестирование
Serial.println("Start"); // Тестирование
}
void loop() {
// поместите сюда ваш основной код для многократного запуска:
}
ISR(TIMER0_COMPA_vect){
var++;
Serial.print(var); // Тестирование
volatile long unsigned i;
if(var == 246){
PORTB = PORTB | (1<<5);
for(i=0; i<30000; i++);
PORTB = PORTB & ~(1<<5);
for(i=0; i<30000; i++);
var=0;
}
}
- часы 16 00 00 00 Гц
- Предварительное масштабирование на 1024 = 15 625
- 1 тик = 1/15625 = 0,00 00 64 сек.
- OCR0 инициализируется значением 255.
- TCNT0 — 255
- Общее время, необходимое для генерации одного прерывания = 255 * 0,00 00 64 = 0,01632 сек., что означает, что через каждые 0,01632 сек. прерывание должно генерироваться
- Сколько прерываний требуется для генерации светодиода через 4 секунды => 4/0,01632 = 246
Обновить рабочий код
int var;
void setup() {
// поместите сюда код установки для однократного запуска:
SREG = SREG | (1<<7); // Глобальное прерывание разрешено
TCCR0A =(1<<WGM01); // Очистить счетчик в режиме сравнения совпадений
OCR0A = 255; // при равенстве TCNT будет сгенерировано прерывание OCR0
TIMSK0 = (1<<OCIE0A); // Сравнение выходных данных соответствует разрешению прерывания
TCCR0B = (1<<CS00) | (1<<CS02); // Предварительное масштабирование на 1024
DDRB = DDRB | (1<<5);
Serial.begin(9600); // Инициализируем USART
Serial.println("Start"); // Пишем приветственное сообщение
}
void loop() {
// поместите сюда ваш основной код для многократного запуска:
}
ISR(TIMER0_COMPA_vect){
var++;
// Serial.print(var);
volatile long unsigned i;
if(var == 246){
PORTB = PORTB | (1<<5);
for(i=0; i<300000; i++);
PORTB = PORTB & ~(1<<5);
var=0;
}
}
@user143252, 👍0
1 ответ
Лучший ответ:
Есть несколько проблем с вашим кодом:
Во-первых, вы должны полностью перезаписать регистры управления таймером. вместо изменения отдельных битов. Например, когда вы пишете
TCCR0A = TCCR0A | (1<<WGM01); // Очистить счетчик в режиме сравнения совпадений
Вы получаете режим таймера, являющийся результатом комбинации биты, которые уже были установлены там, и те, которые вы устанавливаете. Судейство из комментария вы предполагаете, что это будет режим СТС, но это не разрешено, потому что процедура инициализации Arduino уже установила некоторые бит в этом регистре. Поскольку вы берете таймер за свой собственный использования, просто перезапишите все регистры управления:
TCCR0A = (1<<WGM01); // Очистить счетчик в режиме сравнения совпадений
то же самое для TCCR0B
и TIMSK0
.
Вторая проблема заключается в том, что вы неправильно прочитали «Clock Select Bit». Описание» из таблицы данных. Ваш таймер отсчитывается от внешний источник синхронизации на выводе T0. видимо у тебя ничего нет подключен туда, поэтому таймер не увеличивается. Вы, вероятно, имели в виду
TCCR0B = (1<<CS00) | (1<<CS02); // Предварительное масштабирование на 1024
Небольшая проблема — цикл задержки. Программа будет проще
понять, если вы вместо этого используете правильную функцию задержки. Ардуино
delay()
не будет работать, так как вы перенастроили Таймер 0, но вы можете
используйте _delay_ms()
из avr-libc, если вы #include <util/delay.h>
.
- Arduino Uno: avrdude: stk500_recv(): программатор не отвечает
- Запуск двух шаговых двигателей с двумя поворотными энкодерами
- Программирование пользовательских Arduino Mega с Arduino Uno
- Arduino 1.6.4 не показывает никаких /tty/ опций в последовательных портах
- Использование библиотеки Arduino fix_fft или arduinoFFT для фильтрации определенного звука?
- Как сгенерировать файлы .a и .so для добавления в проект arduino
- Автономный ATMega328 — нужно ли прожигать загрузчик?
- Проблемы со скоростью шагового двигателя Nema 17
Большое спасибо, вы правы, я скучаю по битам предварительного масштабирования. мой код работает сейчас, @user143252