Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Таймер в mega8515 100Гц
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Athlon128
Задача - вызывать прерывание каждые 10мс (100Гц). ATmega8515, кварц 16 МГц, таймер1.
Нужно это для замера коротких промежутков времени (~30 сек.).

Код
TIMSK=0x40; // set OCIE1A
TCCR1B=0x0C; // cl/256  16000000/256=62500
// 62500/100=625
// опрос каждые 10ms
//OCR1AH=0x02;  // прерывание как только досчитает до 625=271h
//OCR1AL=0x71;  //


В результате прерывание возникает слишком часто. В чём моя ошибка?
topkin
Цитата(Athlon128 @ May 11 2006, 16:30) *
Задача - вызывать прерывание каждые 10мс (100Гц). ATmega8515, кварц 16 МГц, таймер1.
Нужно это для замера коротких промежутков времени (~30 сек.).

Код
TIMSK=0x40; // set OCIE1A
TCCR1B=0x0C; // cl/256  16000000/256=62500
// 62500/100=625
// опрос каждые 10ms
//OCR1AH=0x02;  // прерывание как только досчитает до 625=271h
//OCR1AL=0x71;  //


В результате прерывание возникает слишком часто. В чём моя ошибка?


Причем здесь регистры OCR1AH, код не совсем понятен? Прерывание разрешили правильно, только значение загружается в регистр TCNTx, при 16 мегах и 1/256 это значение равно 0хFD8F. Само прерывание вы хотите обрабатывать в обработчике прерываний?, только не забывайте в обработчике заново инициализировать таймер.
В общем вам нужно в каком то месте программы, в зависимости от задачи, загрузить значение в счетный регистр TCNTxx и разрешить прерывание. Каждый раз при переполнении регистра будет срабатывать прерывание, ну а дальше обрабатывайте его....
Я вообще один раз написал макрос/функцию и не парюсь с насторойками.
Такие простые глюки ловятся легко в Vmlab
vet
Athlon128
в принципе, всё правильно. Только зачем закомментированы последние 2 строки?
defunct
Цитата
В результате прерывание возникает слишком часто. В чём моя ошибка?

Перед тем как разрешать прерывания (OCIE1A(TIMSK) и SEI) обязательно нужно задать значение OCR1A.
Если в OCR1A будет значение меньше 625, прерывание будет происходить чаще чем раз 10ms.

По-умолчанию при сбросе в OCR1A находится 0, т.о. с установленным флажком CTC прерывание будет генерироваться практически в каждом такте.
Переместите закоментированные строки вперед и раскоментируйте их:

Код
TCCR1B = 0;    // Выключить таймер
OCR1A = 625;    // Подготовить регистр сравнения
TIMSK = (1 << OCIE1A); // разрешить прерывание
TCCR1B = (1 << CTC1) | 4; // Запустить таймер с предделителем 256 и сбросом по достижению OCR1A
Athlon128
2topkin Вашу мысль понял, но у меня прерывание не по переполнению, а по достижению OCR1A.

2vet Вы правы, строки закоментировал по ошибке при вставке в форум. Попутный вопрос: я думал что OCR1A нужно заполнять по байту как у меня, но в итоге работает и OCR1A = 625;

2defunct Это, к сожалению, также не помогло, таймер срабатывал слишком часто, но не так чтобы в каждый такт, а примерно в 1,5-2 раза чаще, чем положено. Так же было и до перестановки OCR1A = 625;

У меня в обработчике прерывания стоит инкремент переменной и несколько проверок if. Я щас попробовал вставить TCCR1B=0x00; до инкремента и TCCR1B=0x0C; после. Замерил 1 минуту, теперь точно щёлкает. Почему это помогло я не понял.

ЗЫ: если так не понятно, приведу листинг.
vet
неплохо бы глянуть на код прерывания.
Строку OCR1A =625 компилятор разбивает на две команды.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.