Таблица данных AVR ATmega32 неверна?

В настоящее время я использую ATmega32, чтобы следить за временем, поэтому я внимательно прочитал техническое описание и настроил Таймер 1 для генерации прерывания каждую секунду.

Согласно следующей формуле в даташите, используя тактовую частоту 16 МГц, прескалер 256 и OCR1A = 31249, я должен получить частоту 1 Гц в режиме CTC:

ф О С н А "=" ф с л к _ я / О 2 Н ( 1 + О С р н А )

Эта формула доступна на странице 99 таблицы данных ATmega32 .

Я настроил Таймер 1 следующим образом:

TCCR1A = 0;
TCCR1B = (1<<WGM12)|(1<<CS12);
OCR1A = 31249;
TIMSK = (1<<OCIE1A);

Вот код прерывания

ISR(TIMER1_COMPA_vect){
    sec++;
}

Затем я использую ЖК-дисплей для непрерывной печати значения sec и получаю тайминг 0,5 секунды. Другими словами, за каждую прошедшую секунду таймер генерирует два прерывания.

Сначала я подумал, может быть, я ошибся с предохранителями, но, похоже, это не так, так как задержки работают нормально. Во всяком случае, вот как я настроил предохранители:

-U lfuse:w:0xff:m -U hfuse:w:0x99:m

Я совершенно не понимаю, что происходит, я все перепроверил, попробовал другой ATmega32, попробовал другой кварцевый генератор на 16 МГц, и все равно получаю тот же результат.

Даташит неправильный или я что-то пропустил?

TL;DR Ответ: Нет. Нет, это не так. ;-)

Ответы (2)

Если системные часы 16 МГц , а прескалер 256 , ваш таймер будет работать на 16 М ЧАС г 256 "=" 62500 ЧАС г , так что будет приращение в каждом 1 62500 ЧАС г "=" 16 мю с . Прерывание будет сгенерировано, когда значение счетчика станет равным 31249 . Если рассчитать это время: 16 мю с × 31250 т я с к с "=" 0,5 с , что является точно таким же результатом, который у вас есть.

Уравнение в таблице данных предназначено для другой цели:

Для генерации выходного сигнала в С Т С режим, О С 1 А вывод можно настроить на переключение своего логического уровня при каждом совпадении сравнения, установив биты режима вывода сравнения в режим переключения. ( С О М 1 А 1 : 0 "=" 1 ) . О С 1 А значение не будет отображаться на выводе порта, если направление данных для вывода не установлено на вывод ( Д Д р О С 1 А "=" 1 ) . Сгенерированный сигнал будет иметь максимальную частоту ф О С 1 А "=" ф с л к я / О / 2 когда О С р 1 А устанавливается равным нулю ( 0 Икс 0000 ) . Частота сигнала определяется следующим уравнением: (...)

Если бы вы измерили частоту конкретного вывода, я думаю, что это будет 1 Гц.


Чтобы достичь 1 с , 16 мю с × 62500 "=" 1 с генерации прерывания вам нужно 62500 тиков и так как счетчик начинается с 0, установите OCR1A на 31250 × 2 1 "=" 62499 , а поскольку Timer1 является 16-битным таймером, это значение не слишком велико (< 65535, 2 16 1 ).

На самом деле это 62499, и вам нужно добавить 1 перед умножением на период часов.
Ой! Я чувствую себя таким глупым прямо сейчас, я не заметил, что он переключил булавку, поэтому я просто предположил, что это та же самая формула! Итак, если мне нужна ровно 1 секунда (с точностью до кристалла), я должен использовать OCR1A = 62499, верно? Согласно формуле (теперь опуская 2), это должно дать мне ровно 1 секунду.

Эта формула предназначена для выходной частоты вывода OCnA («Для генерации выходного сигнала в режиме CTC выход OC1A можно настроить на переключение своего логического уровня при каждом совпадении сравнения, установив биты режима вывода сравнения в режим переключения (COM1A1: 0 = 1). [...] Частота сигнала определяется следующим уравнением:"). Поскольку вместо этого вы используете прерывание, вы получите два сравнения за период. Отбросьте 2 из знаменателя, чтобы вычислить частоту прерывания.