Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ATmega AVR
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.62/78: Рейтинг темы: голосов - 78, средняя оценка - 4.62
OBB
1

Вызов подпрограммы из обработчика события

28.03.2016, 15:01. Показов 14825. Ответов 53
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день!

Пишу простенькую программу "мигающий светодиод".

Реализовал с использованием таймера 0.

Код
.def temp = r16 ;рабочая переменная
.def counter = r17 ;счетчик
.def max_counter_value = r18 ;счетчик
.def currentValue = r19 ;результат
;============ прерывания ============
rjmp RESIT ;RESIT External Pin, Power-on Riset, Brown-out Riset, Watchdog Riset
reti ;INT0 External Ymtirrupt Request 0
reti ;PCINT0 Pin Change Ymtirrupt Request 0
reti ;TIMER1_COMPA Timer/Counter1 Compare Match A
reti ;TIMER1_OVF Timer/Counter1 Overflow
rjmp TIMER0_OVF;TIMER0_OVF Timer/Counter0 Overflow
reti ;EE_RDY EEPROM Ready
reti ;ANA_COMP Analog Comparator
reti ;ADC ADC Conversion Complete
reti ;TIMER1_COMPB Timer/Counter1 Compare Match B
reti ;TIMER0_COMPA Timer/Counter0 Compare Match A
reti ;TIMER0_COMPB Timer/Counter0 Compare Match B
reti ;WDT Watchdog Time-out
reti ;USI_START USI START
reti ;USI_OVF USI Overflow

RESIT: ;начальная инициализация
ldi temp,low(ROMEND) ;загрузка указателя стека
out SPL,temp

LDI currentValue, $00

ldi temp, $05
out TCCR0B,temp

ldi max_counter_value, $33

CLR temp
OUT SREG, temp

LDI temp, $FF
OUT DDRB, temp

clr counter ;очищаем счетчик
clr temp
ldi temp,(1<<TOIE0) ;разр. прерывания Timer0
out TIMSK,temp

sei ;разрешаем прерывания

Gcykle: ;основной пустой цикл
rjmp Gcykle

TIMER0_OVF:;обработчик прерывания Timer0
yms counter ;в каждом прерывании увеличиваем на 1
CP counter, max_counter_value
BRSH ChangeState
;некий код который надо выполнить даже в случае перехода на ChangeState
reti ;конец обработки прерывания таймера

ChangeState:
LDI counter, $00
COM currentValue
OUT PORTB, currentValue
reti
Собственно все работает, но возник вопрос с ветвлением. После выполнения ChangeState программа возвращается в пустой цикл. А если требуется возврат в обработчик прерывания в то же место откуда произошел вызов, то как это реализовать?
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
28.03.2016, 15:01
Ответы с готовыми решениями:

Вызов обработчика события
есть два обработчика события button1.Click и button2.Click . Как из button1.Click вызвать...

Вызов обработчика события.
Можно ли из одного обработчика события, например: void __fastcall TForm1::Button1Click(TObject...

Ручной вызов обработчика события
Здравствуйте, никак не могу разобраться с вызовом метода. void Grid_ManipulationStarting(object...

Косвенный вызов DoEvents() из обработчика события?
В одном приложении столкнулся со следующим явлением : программа сработала так, как если бы событие...

53
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 3,044
29.03.2016, 17:52 21
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от YTYOUT
Во-общето я просто сократил шапку обработчика прерывания.
Я это предположил. Но в запарке можно было и забыть. Ладно, считаем, что и правда сократил. :))) Но ты учитывай, что твои примеры начинающие читают. И так как меня попросили высказаться яснее, я потоптался на твоем примере.

Цитата Сообщение от YTYOUT
то и его пихаем до сравнения ( кстати я почти знаю что в нем)
Тоже предположил это. Но так как мы точно не знаем, исходим из того что есть.
0
0 / 0 / 0
Регистрация: 02.10.2012
Сообщений: 1,946
29.03.2016, 22:56 22
Ну раз потоптался , давай исправляй код так , чтобы там совсем не было меток. :)) Что вполне себе возможно. Дашь пример для начинающих.
0
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 3,044
29.03.2016, 23:15 23
Цитата Сообщение от YTYOUT
Ну раз потоптался , давай исправляй код так , чтобы там совсем не было меток. :)) Что вполне себе возможно. Дашь пример для начинающих.
1 - Ты зря так не любишь метки. Лично мне в лом открывать систему команд и вспоминать, сколько тактов занимает та или иная команда. Основные команды знаю и ладно. Стиль "rjmp +- лапоть" не приемлю, так как такая программа не читабельна.
2 - А смысл? Если все уже перетерли. Пагранист показал пример с вызовом подпрограммы. Я показал пример с джампами. Сидеть, вникать, ужать пару тактов-байтов мне и лень и некогда, не до того. Обдумывал и твой предложенный вариант. Выполнить таинственный код до проверки. Но кто его знает, что там автору нужно? Примеров начинающему в этой теме дали достаточно, чтобы он продолжал дальше.
0
0 / 0 / 0
Регистрация: 02.10.2012
Сообщений: 1,946
30.03.2016, 01:52 24
Ну ты занудой стал :)) Я предлагал проабгрейдить только этот кусок
Код
CP counter, max_counter_value  //Сравниваем
BRSH ChangeState  // Если больше или равно топаем на  ChangeState
reti //
0
1 / 1 / 0
Регистрация: 09.08.2014
Сообщений: 96
30.03.2016, 09:31 25
Цитата Сообщение от YTYOUT
Я предлагал проабгрейдить только этот кусок
Код:
CP counter, max_counter_value //Сравниваем
BRSH ChangeState // Если больше или равно топаем на ChangeState
reti //
Ага ага, и то что вот на это завязано "CP counter, max_counter_value" тоже. Плюсовать counter и занимать под константу max_counter_value регистр не самое изящное решение.
0
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 3,044
30.03.2016, 10:20 26
Цитата Сообщение от Пагранист
Плюсовать counter и занимать под константу max_counter_value регистр не самое изящное решение.
А если у автора так и задумано, сравнивать с задаваемым параметром, только в выложенном коде это не показано?
0
OBB
30.03.2016, 12:36 27
Спасибо за ответы и за обсуждение.

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

Сейчас встала задача собрать с четырех датчиков сигналы в виде синусоиды частотой от 0 до 2.5кГц с пока не известной амплитудой (предположительно на низких частотах будет порядка десятков милливольт, а на высоких -до вольта-двух (но это только предположение), посчитать частоту, рассчитать среднюю.

Задачка не сложная, плюс со старых времен осталась одна mega8 и пять tiny25. Вот и начал вспоминать и оценивать чего достаточно для решения.

Надо собственно с входящим сигналом разбираться. Будут помехи, так что не уверен что компаратором получится обойтись.
0 / 0 / 0
Регистрация: 02.10.2012
Сообщений: 1,946
30.03.2016, 12:58 28
Цитата Сообщение от dymyurk1978
Цитата Сообщение от Пагранист
Плюсовать counter и занимать под константу max_counter_value регистр не самое изящное решение.
А если у автора так и задумано, сравнивать с задаваемым параметром, только в выложенном коде это не показано?

CP заменить на CPSE
0
1 / 1 / 0
Регистрация: 09.08.2014
Сообщений: 96
30.03.2016, 14:11 29
Цитата Сообщение от YTYOUT
CP заменить на CPSE
Не. Заменить надо направление счёта. Тогда операцию сравнения вообще можно выкинуть нахер.
Цитата Сообщение от dymyurk1978
Цитата Сообщение от Пагранист
Плюсовать counter и занимать под константу max_counter_value регистр не самое изящное решение.
А если у автора так и задумано, сравнивать с задаваемым параметром, только в выложенном коде это не показано?
Дык ни кто и не против задумки автора. Просто я сильно возражаю против пустой траты целого регистра и лишней команды на сравнеие.

Как делает автор
Код
; заводит будильник
clr r17 ; обнуляет счётчик
ldi r18,$33 ; загружает для него максимальное значение ТРАТИТ РЕГИСТР ПОПУСТУ

; а тут он считает прерывания
TIMER0_OVF:;обработчик прерывания Timer0
yms r17 ;в каждом прерывании увеличиваем на 1
CP counter, max_counter_value ; сравнивает ИМХО ЛИШНЯЯ КОМАНДА+ЛИШНИЙ РЕГИСТР
BRSH ChangeState ; условие (больше или равно) хотя лучше бы просто BREQ для ясности
;некий код который надо выполнить даже в случае перехода на ChangeState
reti ;конец обработки прерывания таймера
Я же предлагаю немножко не так
Код
ldi r17,$33 ; зачем считать ДО, когдаможно считать ОТ
; на этом месте получил свободу прозябающий от безделия регистр

; а тут я считаю прерывания
TIMER0_OVF:;обработчик прерывания Timer0
dec r17 ;в каждом прерывании мы отнимаем еденицу
BREQ ChangeState; и с нетерпением ждём флага нуля не сравнивая счётчик ни с чем
;некий код который надо выполнить даже в случае перехода на ChangeState
reti ;конец обработки прерывания таймера
Как то так.
0
OBB
31.03.2016, 10:24 30
"BREQ ChangeState; и с нетерпением ждём флага нуля не сравнивая счётчик ни с чем"

Спасибо, теперь понятно почему в одном примере видел уменьшение на единицу. Тогда не понял для чего обратный счет, а не прямой.
0 / 0 / 0
Регистрация: 02.10.2012
Сообщений: 1,946
31.03.2016, 12:08 31
А ещё лучше привыкнуть использовать команду subi вместо dec.

К вопросу про cpse

Код
;некий код который надо выполнить даже в случае перехода на ChangeState
CPSE counter, max_counter_value  //Сравниваем
reti
LDI counter, $00
COM currentValue
OUT PORTB, currentValue
reti
0
0 / 0 / 0
Регистрация: 28.06.2010
Сообщений: 211
04.04.2016, 00:00 32
Цитата Сообщение от oomomstir
dymyurk1978, наверное, надо всё-таки учить людей, начиная с языков высокого уровня, чтобы jmp из одной подпрограммы в другую даже в голову не приходил (а если и придёт - думали бы "ну, это высокая нигия seniorов, мне так нельзя").
Цитата Сообщение от dymyurk1978
Автору: ассемблер сильно деформирует мышление. Всегда есть риск скатиться следить за мелочами, но не видеть целой картины.
«Зачем вы так ассемблер-то,
Ведь он совсем не виноват».
Как-то так схоже звучит в какой-то песенке.
Думаю, проблема не в ассемблере, а в отсутствии хорошего описания, как писать на ассемблере. Отсюда начинающие пишут нехорошо.
Можно взять плохо написанную начинающим программу на ЯВУ и утверждать: «ЯВУ сильно деформирует мышление».
Цитата Сообщение от OBB
Добрый день!
А если требуется возврат в обработчик прерывания в то же место откуда произошел вызов, то как это реализовать?
Думаю, это порочная практика. В прерывании устанавливается только программный флаг и, в особых случаях, экстренная реакция. Обработка прерывания лучше проводить в основной программе на верхнем уровне.
Цитата Сообщение от dymyurk1978
Тщательно продумывать программу. Если чувствуете, что начинается лапша и путаница из переходов, нужно пересматривать задачу. По сути написание программы на асме - игра в кубики. Иногда нужно полностью снести всю конструкцию, чтобы получить нужный результат…
Если вы прыгаете в подпрограмму, то должны тщательно отслеживать, чтобы не сорвать стек.
Это все для начинающих.
У имеющих некоторый опыт - никакой лапши и путаницы, никакой «игры с кубиками», никаких сносов всей конструкции, никаких «тщательных отслеживаний срыва стека» и т.д.
Все проще. Надо только соблюдать некоторые правила написания программы.
0
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 3,044
04.04.2016, 17:55 33
Цитата Сообщение от Otixomdr_1
Это все для начинающих.
У имеющих некоторый опыт - никакой лапши и путаницы, никакой «игры с кубиками», никаких сносов всей конструкции, никаких «тщательных отслеживаний срыва стека» и т.д.
Все проще. Надо только соблюдать некоторые правила написания программы.
Вы либо вообще на асме не пишете, либо небольшой опыт, либо маленькие проектики.
0
1 / 1 / 0
Регистрация: 09.08.2014
Сообщений: 96
05.04.2016, 00:19 34
Цитата Сообщение от Otixomdr_1
Думаю, это порочная практика. В прерывании устанавливается только программный флаг и, в особых случаях, экстренная реакция. Обработка прерывания лучше проводить в основной программе на верхнем уровне.
Думаю не стоит так категорично. Подходы могут быть разные. На то он и ассемблер, что бы не зажиматься в рамках постулатов, а использовать гибкость языка. Простой пример. Тахометр с выводом на ЖК. Импульс с движка - прерывание. Чего ради мне городить огород с флагами, когда я определенно знаю что интервала между импульсами мне за глаза хватит оттарабанить весь алгоритм обсчёта этого самого интервала и и "перевести" его в формат ЖК. А потом уже вылезти из прерывания и оставшееся время отдать ЖК, кнопкам и т.п.
Т.е. в программах где интервал между прерываниями гарантировано длиннее времени вычисления того что требуется обсчитать, можно не торопится вылезать из прерывания. Тем более под прерывание пихают как раз тот код который требует большего приоритета по отношению к остальному коду.
0
0 / 0 / 0
Регистрация: 02.10.2012
Сообщений: 1,946
05.04.2016, 01:14 35
Увеличивается время реакции на внешние события всей системы. Флаг , вылез из прерывания , обрабатывай. Зато не пропустишь если возникнет прерывание с высшим приоритетом
0
0 / 0 / 0
Регистрация: 28.10.2010
Сообщений: 893
05.04.2016, 03:21 36
Однозначно не скажешь, может увеличивается, а как правило нет. До анализа флага еще дойти нужно. Про "пропуск" прерывания тоже не совсем точное выражение, особенно если речь идет о другом прерывании, а не повторном том же самом. Тут правильнее говорить о соблюдении приоритетности, причем не той аппаратной, заложенной конструкторами таблицы, а той котороя нужна конкретно тебе.
0
1 / 1 / 0
Регистрация: 09.08.2014
Сообщений: 96
05.04.2016, 08:40 37
инкер Однозначно не скажешь, может увеличивается, а как правило нет. До анализа флага еще дойти нужно. Про "пропуск" прерывания тоже не совсем точное выражение, особенно если речь идет о другом прерывании, а не повторном том же самом. Тут правильнее говорить о соблюдении приоритетности, причем не той аппаратной, заложенной конструкторами таблицы, а той котороя нужна конкретно тебе.
Хорошо сказано. Однако люди то ли не могут выйти за рамки стереотипов, то ли меньше чем windows под AVR проекты не делают. Просто какая то зашоренность.
0
0 / 0 / 0
Регистрация: 28.10.2010
Сообщений: 893
05.04.2016, 10:22 38
Приемов миллион, когда нет жестких требований по времени или памяти можно ограничиться десятком и все будет работать. Когда-то нужно было сэкономить драгоценные байты и пришлось сделать выход из нескольких прерываний не классически, а прыжком в хвост одного из них. В результате сэкономились десяток байт, которые тратились на POPы при возврате по стандартному варианту.
0
0 / 0 / 0
Регистрация: 02.10.2012
Сообщений: 1,946
05.04.2016, 10:24 39
Просто какая то зашоренность.
Вашем случае использовать прерывание , вообще нонсенс. Тем более что времени на всё хватает
0
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 3,044
05.04.2016, 10:54 40
[QUOTE="YTYOUT"][QUOTE="Цитата:[/QUOTE]
Просто какая то зашоренность.
Вашем случае использовать прерывание , вообще нонсенс. Тем более что времени на всё хватает
Не факт. Не каждая итерация основного цикла выполняется строго определенное время. Сложились условия, выполнили быстро. Сложились другие условия, выполнились долгие задачи.
А так да, анализируем выполнение каждой функции. Если времени вагон, от прерываний можно отказаться.
0
05.04.2016, 10:54
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
05.04.2016, 10:54
Помогаю со студенческими работами здесь

Вызов единственного обработчика события при переопределении
Все привет! Вопрос по теории. Можно ли как-то сделать так, чтобы при перекрытии обработчика события...

Вызов обработчика события после вывода изображения на оси
Доброго времени суток! Подскажите, пожалуйста, как вызвать функцию обработчика нажатия на оси...

Вызов обработчика кнопки из другого обработчика.
Есть кнопка, есть у ней обработчик, который делает нечто полезное. Как вызвать выполнения...

Создание объекта-события и обработчика события
Допустим у меня есть следующий класс: public class Example { private boolean bool; public...

Выход из обработчика события
Подскажите пожалуйста как в С++ (Visual Studio 2008) выйти из обработчика событий. Конкретно:...

Создание обработчика события
Пытаюсь создатьобработчик события для динамически созданного элемента. В unit.cpp void __fastcall...

Подключение обработчика события
Привет всем, подскажите пожалуйста, как подключить событие к блочному елементу div используя JS?...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru