Разбираюсь с работой таймера ATTiny13. Написал код, но работает не так, как задумывалось. Не могу понять - почему. Режим работы таймера CTC, но продолжительность импульсов на PB3 не изменяется при изменении начального значения OCR0A. Получается, что прерывание срабатывает не при достижении равенства значения счётчика и значения OCR0A, а при переполнении счётчика (т.е. счёт идёт постоянно до 255). Заход, в функцию обработки прерываний, происходит. Что-то не так написал в коде, или что-то не дописал? Помогите, пожалуйста, разобраться.
Код:
#include <avr/io.h> #include <avr/interrupt.h>
void setup() { TCCR0A = 0x10; // режим CTC TCCR0B = 0x01; //предделитель тактовой частоты CLK/1 TCNT0 = 0; // начальное значение счётчика OCR0A = 100; // начальное значение регистра совпадения A
DDRB |= (1 << PB3); // output на PB3 PORTB &= ~(1 << PB3); // низкий уровень на PB3
//устанавливаем бит разрешения прерывания 0-ого счетчика по совпадению с OCR0A TIMSK0 |= (1 << OCIE0A);
sei();// Разрешаем прерывания глобально }
byte a = 0;
ISR(TIM0_COMPA_vect) // обработка прерывания при совпадении счётчика с OCR0A {
if (a == 0) { PORTB |= (1 << PB3); // высокий на PB3 ++a; } else { PORTB &= ~(1 << PB3); // низкий на PB3 a = 0; } }
_________________ Платы для HLDI - установки лазерной засветки фоторезиста. ФоторезистOrdyl Alpha 350 Жидкое олово для лужения плат (видео) - самое лучшее и только у меня. Паяльные маски XV501T-4 и KSM-S6189 (5 цветов). Заказ печатных плат - pcbsmac@gmail.com
Вопрос снимается. Нашёл ошибку в коде: значение режима задал не в тех единицах. Нужно было или 2 (в десятичной), или 0b10 (в двоичной), или 0x02 (в шестнадцатиричной), или так: TCCR0A |= (2 << WGM00); То есть, в коде я выставил режим просто счётчика. Непонятно только: почему этот обработчик прерывания срабатывал?
Последний раз редактировалось alsav22 Чт дек 04, 2025 17:25:34, всего редактировалось 1 раз.
На выводе РВ3 светодиод. При старте значение регистра OCR0A = 200. При замыкании вывода РВ4 на GND, в данный регистр запишется значение 100. По миганию светодиода это хорошо будет видно.
alsav22 Гибрид ардуино - стиля (возможно и самой ардуиноIDE) и Си??? Так в варианте ардуинки второй генератор таймерной сетки на Т0 совсем иначе делается.
Я не понимаю Си, но в каком месте вы изменяете значение регистра OCR0A?
А зачем мне его изменять (при работе кода я его не меняю, менял в тексте,перед сборкой)?.Цели такой не было. Просто разбирался с регистрами таймера: куда, что, и как нужно прописывать. Результат работы смотрел логическим анализатором на пине вывода.
alsav22 Гибрид ардуино - стиля (возможно и самой ардуиноIDE) и Си??? Так в варианте ардуинки второй генератор таймерной сетки на Т0 совсем иначе делается.
Ардуинка, насколько понял, свои настройки таймера автоматом может прописывать (например, при вызове analogWrite()). Долго не мог понять: делаю настройки таймера, потом использую analogWrite(), мои настройки не работают. А с таким синтаксисом всё видно. В общем, разбираюсь (как могу).
TCCR0A = 0x10; // режим CTC TCCR0B = 0x01; //предделитель тактовой частоты CLK/1 TCNT0 = 0; // начальное значение счётчика OCR0A = 100; // начальное значение регистра совпадения A
Сделал бы (в мнемокодах) TCCR0B <- 0 //стоп таймера TCNT0 <- 0 // начальное значение счётчика TCCR0A <- 1<<WGM01 // режим CTC OCR0A <- 100 // начальное значение регистра совпадения A
TIMSK0 <- 1 << OCIE0A TIFR0 <- 1 << OCF0A TCCR0B <- 1<<CS00 //старт с тактовой частотой CLK/1 SEI
... Ардуинка, насколько понял, свои настройки таймера автоматом может прописывать (например, при вызове analogWrite()). Долго не мог понять: делаю настройки таймера, потом использую analogWrite(), мои настройки не работают. А с таким синтаксисом всё видно. В общем, разбираюсь (как могу).
Ежли работаете с ардуино - извольте соблюдать правила "референса". Надо хоть немножко понимания иметь о том, что автоматически добавляется к каждому "СКОТчу" в качестве "системных функций" самой средой по умолчанию. Иначе будет достаточно много всякого рода "непонятных ошибок". Таймер Т0 используется в адуринках на АВРках в качестве "генератора системных часов" - по факту 1 миллисекундного интервала. Можно и свой добавочный генератор добавить (для "параллельного процесса" на основе прерывания по OCR0A, но то прерывание также будет с интервалом 1 миллисекунда, единственно смещено относительно основного (обычно ставится 0х127). А уже на его основе строятся свои программные счетчики. Насчет работ с адуриньями рекомендую посмотреть раскиданные по viewtopic.php?f=62&t=156720 заметки и раздел "уроков" у Гайвера: https://alexgyver.ru/
Для того, чтобы совсем "влияния не оказывалось" надо программу писать "за пределами ардуиноIDE" - в любой другой IDE. Максимум что можно "нейтрализовать" изменяя основную страничку исходника - это убрать работу уарт (и то там проще делается). Да и зачем? Неуж то "в рамках референса" средств недостаточно? Собственно вариант окна симулятора к примеру: Спойлер зачем еще раз то же самое дублировать?
Прерывание не будет правильно подключено и будет казаться, что таймер срабатывает только при переполнении
---
не TCCR0A = 0x10; // режим CTC - ето бит COM0B0, а не бит WGM01 а TCCR0A = (1 << WGM01); // режим CTC
Поскольку режим CTC включен неправильно, таймер работает в Normal Mode. В Normal Mode прерывание OCR0A не возникает, но прерывание по переполнению может быть вызвано.
Последний раз редактировалось veso74 Пт дек 05, 2025 11:14:42, всего редактировалось 2 раз(а).
Пока что не совсем понятно с какой средой разработки топикстартер дело имеет. Он же не объявлял, что под ардуино IDE работает. Да и в самой IDE платформ с Тинькой 13ой минимум 2 - их ещё и устанавливать дополнительно надо (в списке "по умолчанию" их нет- надо вручную добавлять). Может топикстартер пытается копировать "стиль ардуино" в АВРстудио (микрочип студио)... Так что подождем уточнений... OKF, ну не "матрешки" же делать - вкладывать повторно то же самое в то же самое. Обычно достаточно от loop избавиться. И то лишь для гурманов (изврата). Да и авр студии никто не отменял...
Если для АВР студии или чистого GCC это одно, а ежли в ардуино IDE - то "матрешка". Пока ведь неизвестно в какой среде/IDE топикстартер программку делает. Я принял исходник alsav22 за работу в ардуиноIDE поскольку его программа не имеет по факту явно объявленного зацикливания в loop(){} как обычно только для ардуино скотчей (в loop зацикливание установлено средствами IDE, также самой IDE выполняется и инициализация Т0, правда не во всех платформах - у некоторых имеются опционные вкладки для разрешения/запрета работы функций времени у "малолапых" АВРок). Собственно с такой точки зрения и все мои ответы были.
Продолжение. Atmel Studio 7, код на ассемблере, отладка в режиме симулятора. Не заходит в обработчик прерывания в режиме сравнения. Если выставить режим переполнения, то в обработчик прерывания при переполнении заходит. Что не так в коде?
Код:
.include "tn13def.inc";
.def temp = r16
.cseg .org 0
; инциализация стека ldi temp, low(RAMEND); out SPL, temp ; Set Stack Pointer to top of RAM
rjmp Start;
/*; обаработчик прерывания при переполнении счётчика TIM0_OVF: nop; reti;*/
; обаработчик прерывания при сравнении TIM0_COMPA: nop reti
Start: clr temp ; режим сравнения (CTC) ldi temp, 0b00000010; out TCCR0A, temp
clr temp; out TCNT0, temp; начальное значение счётчика
;устанавливаем биты разрешения прерывания 0-ого счетчика ldi temp, 0b00000100; прерывание при совпадении с OCR0A out TIMSK0, temp;
;значение для сравнения clr temp; ldi temp, 0x1E; out OCR0A, temp;
Смотри ограничения/документацию по симулятору IDE для данного МК. Симулятор имеет версии и отличия/ограничения в зависимости от того, какая версия указана активной для проекта. С меня под ассемблером и АВР студио 4.19 хватает... более старшие увы... не ставил.
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения