AVR: как работает регистр флагов прерываний?

Обсуждаем контроллеры компании Atmel.
Ответить
Друг Кота
Аватара пользователя
Сообщения: 3459
Зарегистрирован: Ср сен 27, 2006 16:18:57

Сообщение Барсик »

Из даташита было не всё понятно. Поставил несколько смелых экспериментов с ATtiny13 и регистром таймера TIFR0. Получилось примерно так:

1. Соответствующий бит регистра устанавливается в 1 всегда, когда выполнилось условие прерывания. Независимо от того, разрешено или запрещено прерывание.
2. Этот бит остаётся 1 до тех пор, пока программа не уйдёт на обработчик прерывания. Как только начнётся обработка прерывания, бит будет сброшен в 0. Т.е. если даже обработка прерывания ещё не закончилась, этот бит уже будет установлен в 0.
3. Если прерывание запрещено, неважно как - глобально или по маске, то бит сохраняет значение 1 сколь угодно долго.
4. Этот бит можно принудительно установить в 0, если записать в регистр флагов на его место 1 (а вовсе не ноль, как казалось! попытка записать туда 0 ничего не даёт - бит остаётся равным 1). Тогда, если прерывание разрешено, оно обработано не будет.
5. Но если условие прерывания вдруг выполнится опять, бит будет снова установлен в 1.

Я ничего не напутал? Что скажут специалисты?
Реклама
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

Ну все верно, а что касается:
Барсик писал(а): 4. Этот бит можно принудительно установить в 0, если записать в регистр флагов на его место 1 (а вовсе не ноль, как казалось! попытка записать туда 0 ничего не даёт - бит остаётся равным 1). Тогда, если прерывание разрешено, оно обработано не будет.
Так во описании всех флагов в даташите так и написано "Флаг можно сбросить программно, записав туда лог.1"...
Реклама
Друг Кота
Аватара пользователя
Сообщения: 3459
Зарегистрирован: Ср сен 27, 2006 16:18:57

Сообщение Барсик »

С этим то было ясно. Просто очень чуднО выглядит. Чтобы бит в регистре установить в 0, надо записать туда 1 :) :) Интересно, это только у AVR-ов так, или у других микроконтроллеров то же самое?
Мудрый кот
Аватара пользователя
Сообщения: 1815
Зарегистрирован: Пн янв 12, 2009 01:59:20
Откуда: Россия.

Сообщение SERJ »

Барсик писал(а): Чтобы бит в регистре установить в 0, надо записать туда 1
Не установить, а сбросить флаг. :)
Думаю вот это Вам странным не кажется.

"Что бы сбросить триггер К561ТМ2 в ноль, нужно на вход "R" подать единицу."

Или вот так понятнее? :)

Изображение
Реклама
Эиком - электронные компоненты и радиодетали
Встал на лапы
Аватара пользователя
Сообщения: 110
Зарегистрирован: Чт янв 14, 2016 14:42:05
Откуда: City

Сообщение CATяра »

[uquote="Барсик",url="/forum/viewtopic.php?p=1500664#p1500664"]Из даташита было не всё понятно. Поставил несколько смелых экспериментов с ATtiny13 и регистром таймера TIFR0......
....
Я ничего не напутал? Что скажут специалисты?[/uquote]

У меня правильно в отладчике заработало только так:

Код: Выделить всё

	
.def     A=R21
......
.....

IN		 A, TIFR0
COM		A
SBR		A, 4		 ;уст БИТ в регистре. ПРИНУДИТЕЛЬНО УСТАНОВИТЬ БИТ (OCF0A В ФЛАГЕ TIFR0) В ЕДЕНИЦУ, 
                    ;ЧТОБЫ СБРОСИТЬ ФЛАГ ПРЕРЫВАНИЯ ПО COPMARE OCF0A
OUT		TIFR0, A	;УСТРАНЕНИЕ НАЛОЖЕНИЯ ДВУХ ПРЕРЫВАНИЙ от PCINT и TIM0_COMPA .......
....
....
[/b]

Понадобилась побитовая инверсия, чтобы сбросить только один бит (2 - OCF0A)
В отладчике заработало как надо, остальные биты остаются на месте и не меняются у регистра TIFR0

Огромное спасибо за разъяснения!
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18678
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

CATяра писал(а):Понадобилась побитовая инверсия, чтобы сбросить только один бит (2 - OCF0A)
чтобы сбросить один бит OCF0A надо всего лишь 2 команды, никакой инверсии, чтение регистра флагов тоже не требуется:
LDI A, (1<<OCF0A)
OUT TIFR0, A
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 110
Зарегистрирован: Чт янв 14, 2016 14:42:05
Откуда: City

Сообщение CATяра »

[uquote="ARV",url="/forum/viewtopic.php?p=3794346#p3794346"]...
чтобы сбросить один бит OCF0A надо всего лишь 2 команды, никакой инверсии, чтение регистра флагов тоже не требуется:
LDI A, (1<<OCF0A)
OUT TIFR0, A
[/uquote]
Огромное спасибо (пригодиться в копилку знаний )

P.S. Считывание мне нужно было для определения "нахлёста" прерываний (для отладки)
Делал схему на 2 МосФетах "обратный симистор" с 0 В до угла поворота резистора и в нужном месте выключение нагрузки
И иногда возникал импульс в целый полупериод сетевого напряжения (это были два прерывания друг за другом, понял когда разобрался)
Здесь мне и понадобилась проверка флага в одном прерывании, чтобы отследить наступающее второе при завершении первого.

Огромное спасибо всем Котам, за ценную информацию! :beer:
Друг Кота
Сообщения: 9175
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

Сообщение roman.com »

[uquote="Барсик",url="/forum/viewtopic.php?p=1500664#p1500664"]Что скажут специалисты?[/uquote]
Специалисты скажут, что доклад не полный))

6. Что будет если сработают сразу несколько прерываний ? INT0, INT1, INT2... и т.д. Как будут обрабатываться прерывания ?
Барсик писал(а):Чтобы бит в регистре установить в 0, надо записать туда 1 Интересно, это только у AVR-ов так, или у других микроконтроллеров то же самое?
Это справедливо не только для AVR-ов, но для других устройств.
Например в радиомодулях (типа nRF24L01 и т.д.) тоже самое: чтобы бит в регистре установить в 0, надо записать туда 1.
Например в Ethernet модулях (типа W5500 и т.д.) тоже самое: чтобы бит в регистре установить в 0, надо записать туда 1.
И т.д.
Логика работы у всех одинаковая.
Грызет канифоль
Сообщения: 285
Зарегистрирован: Вс сен 05, 2010 15:35:50

Сообщение protoder »

[uquote="Барсик",url="/forum/viewtopic.php?p=1500664#p1500664"]Из даташита было не всё понятно. Поставил несколько смелых экспериментов с ATtiny13 и регистром таймера TIFR0. Получилось примерно так:

1. Соответствующий бит регистра устанавливается в 1 всегда, когда выполнилось условие прерывания. Независимо от того, разрешено или запрещено прерывание.
2. Этот бит остаётся 1 до тех пор, пока программа не уйдёт на обработчик прерывания. Как только начнётся обработка прерывания, бит будет сброшен в 0. Т.е. если даже обработка прерывания ещё не закончилась, этот бит уже будет установлен в 0.
3. Если прерывание запрещено, неважно как - глобально или по маске, то бит сохраняет значение 1 сколь угодно долго.
4. Этот бит можно принудительно установить в 0, если записать в регистр флагов на его место 1 (а вовсе не ноль, как казалось! попытка записать туда 0 ничего не даёт - бит остаётся равным 1). Тогда, если прерывание разрешено, оно обработано не будет.
5. Но если условие прерывания вдруг выполнится опять, бит будет снова установлен в 1.

Я ничего не напутал? Что скажут специалисты?[/uquote]

Все супер!
1 для сброса используют, что бы можно было обнулять маской. Ну, то есть надо скинуть бит 2 и 3, кидаете в порт (1 << 2) | (1 << 3).
Ну, может им конечно так было просто проще сделать :) Но получилось в целом удобно.
Ответить

Вернуться в «AVR»