Проблема с таймером 0
Я делаю первые неуверенные шаги вне Arduino IDE, и у меня не очень получается с таймерами/прерываниями. Я могу настроить вывод на вывод и зажечь светодиод с регистрами, но я не могу заставить его мигать с помощью таймера. Я изучил множество руководств и очень внимательно следил за техническими данными Atmel ATmega328.
Использование платы Arduino Uno R3 & Atmel ICE (ISP.) Моя система разработки — Raspbian (Debian) с набором инструментов GNU AVR (avr-gcc, avr-objcopy, avrdude). Помимо отсутствия загрузчика, это стандартная плата болота (включая предохранители.)
Вот мой текущий код:
#include <avr/io.h>
#include <avr/interrupt.h>
ISR(TIMER0_COMPA_vect)
{
PORTB ^= (1 << PB5); // Переключить контакт Arduino № 13
}
int main (void)
{
DDRB = (1 << DDB5); // Arduino Pin #13 является выходом
cli(); // Очистить прерывания
OCR0A = (unsigned char)0xFF; // Сравнить регистр A = 255
TIMSK0 = (1 << OCIE0A); // Включить прерывание для комп. Рег. А
TCCR0A = (1 << WGM01); // Режим СТС
sei(); // Установка прерываний
TCCR0B = (1 << CS02) | (1 << CS00); // Делим на 1024 Предделитель (ВПЕРЕД!)
return 0;
}
Не знаю, то ли я чего-то не вижу, то ли я установил регистры в неправильном порядке, но это сводит меня с ума.
@Ashlyn Black, 👍5
Обсуждение2 ответа
Лучший ответ:
return 0
перезагружает устройство. Вместо этого используйте while(1);
, чтобы заставить его ждать бесконечно.
Просто чтобы уточнить, возврат из main
**не** сбрасывает устройство, как я показал в своем ответе. Я упоминаю об этом на случай, если люди прочитают этот ответ и подумают, что возврат из «основного» — это простой способ добиться перезагрузки устройства., @Nick Gammon
Возврат из main
не приводит к сбросу устройства (в этом случае оно запустится снова и повторит все заново). Он вызывает exit
, который отключает прерывания и зацикливается на неопределенный срок.
00000068 <__ctors_end>:
68: 11 24 eor r1, r1
6a: 1f be out 0x3f, r1 ; 63
6c: cf ef ldi r28, 0xFF ; 255
6e: d8 e0 ldi r29, 0x08 ; 8
70: de bf out 0x3e, r29 ; 62
72: cd bf out 0x3d, r28 ; 61
74: 0e 94 52 00 call 0xa4 ; 0xa4 <main>
78: 0c 94 61 00 jmp 0xc2 ; 0xc2 <_exit>
...
000000a4 <main>:
a4: 80 e2 ldi r24, 0x20 ; 32
a6: 84 b9 out 0x04, r24 ; 4
a8: f8 94 cli
aa: 8f ef ldi r24, 0xFF ; 255
ac: 87 bd out 0x27, r24 ; 39
ae: 82 e0 ldi r24, 0x02 ; 2
b0: 80 93 6e 00 sts 0x006E, r24
b4: 84 bd out 0x24, r24 ; 36
b6: 78 94 sei
b8: 85 e0 ldi r24, 0x05 ; 5
ba: 85 bd out 0x25, r24 ; 37
bc: 80 e0 ldi r24, 0x00 ; 0
be: 90 e0 ldi r25, 0x00 ; 0
c0: 08 95 ret
000000c2 <_exit>:
c2: f8 94 cli
000000c4 <__stop_program>:
c4: ff cf rjmp .-2 ; 0xc4 <__stop_program>
Вы можете видеть, что по адресу 0x74 он вызывает main, а затем переходит к выходу. exit
отключает прерывания.
Если прерывания отключены, ваш ISR не будет переключать контакт 13.
- AVRdude неправильно считывает значения байтов предохранителя
- Прерывание переполнения Timer0 не работает
- Изменчивая переменная не обновляется с таймера ISR
- Прерывания TIMER1 CTC не работают с avr-gcc
- ATmega328P - проблема с использованием таймера 2 для генерации тона
- Точность синхронизации Arduino nano
- Интервальный таймер на Arduino: Сомнения по поводу библиотеки TimerOne
- Запуск кода Arduino для Bluefruit LE на чистом ATMega328
return 0
не сбрасывает устройство? Попробуйтеwhile(1);
, чтобы он ждал бесконечно., @GerbenЯ буду кричать. Спасибо! (Ты делаешь ответ на вопрос или я?), @Ashlyn Black
Комментатор должен преобразовать его в ответ., @dlu