Я пытаюсь использовать Timer1 на ATtiny85 (Adafruit Trinket), чтобы мигать светодиодом каждую секунду. Значение предварительного делителя — 1024, а значение регистра сравнения — 28. Я прокручиваю это 279 раз, чтобы получить задержку в 1 секунду.
С приведенным ниже кодом я получаю что-то вроде 8,5 секунд. Я установил -mmcu=attiny85 и -DF_CPU=8000000UL при компиляции. Что я мог упустить.
#include <stdint.h>
#include <avr/interrupt.h>
#define TIMER_OVERFLOW_COUNT 279
volatile uint16_t timerCount = TIMER_OVERFLOW_COUNT;
ISR(TIMER1_OVF_vect)
{
timerCount++;
}
int main(void)
{
DDRB = 1 << DDB1;
OCR1C = 28;
TIMSK = 1 << TOIE1;
sei();
TCCR1 = (1 << CS13) | (1 << CS11) | (1 << CS10);
while( 1)
{
if( timerCount >= TIMER_OVERFLOW_COUNT)
{
timerCount = 0;
PORTB ^= 1 << PORTB1;
}
}
return 0;
}
Предохранитель CKDIV8 программируется на устройствах, только что выпущенных с завода. Если вы забудете перепрограммировать этот предохранитель, устройство будет работать на 1/8 ожидаемой тактовой частоты.
Евгений Ш.
timerCount
как обработчика прерывания, так и цикла - плохая идея. У вас тут состояние гонки. Почему бы не поместить всю логику в обработчик? Это не так уж и тяжело.Арсенал
Бенс Кауликс
Суба Томас
Евгений Ш.
F_CPU
вообще нужно? Я думаю, что он используется только для некоторых библиотечных функций задержки, которые не используются в коде.Бенс Кауликс
Евгений Ш.
Суба Томас
Бенс Кауликс
OCIE1C
а неTOIE1
inTIMSK
. Насколько я помню.Суба Томас
Суба Томас
Евгений Ш.
Бенс Кауликс
OCR1C = 28
но затем используйтеOCR1A = 28;
и установитеOCIE1A
.Суба Томас
Евгений Ш.
TIMER1_COMPA
.. вы можете использовать его очень хорошо. Или вы все еще можете использовать прерывание переполнения, если каждый раз правильно вычисляете начальное значение таймера (MAX-28).Суба Томас
Евгений Ш.
Суба Томас
Бенс Кауликс
Суба Томас
RWRkeSBZ