Регистрация | Вход
[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
Страница 1 из 41234»
Модератор форума: demanik 
Форум Picbasic.ru » Программирование МК » Proton PicBasic » Работа с прерываниями
Работа с прерываниями
tesla88 Дата: Чт, 31.07.2014, 13:06  |                                                                                                                Сообщение # 1
Группа: Проверенные
Ранг:  Продвинутый
Сообщений: 121
Репутация: 0   ±
Замечания:   ±
На сайте с 20.11.2010

Статус: Offline

Всем доброго времени суток дорогие друзья!!!
Возник тут один интересный вопрос - как реализовать переход в нужную часть программы из обработчика прерываний? приведу простой пример программы - 

Device = 16F628A
Xtal = 4   ' Частота осциллятора  20 МГц

All_Digital = On                 ' Все порты цифровые ( Аналоговые )
'конфигурация портов\\\\
     
TRISA = %00000000   ' настройка порта ( 1 вход или 0 выхзод - 1 или 0 ) 
TRISB = %00000001     ' настройка порта ( 1 вход или 0 выхзод - 1 или 0 ) 
               
PORTB = %00000000         ' Сброс порта при включение ( выставление рабочего положения )
PORTA = %00000000          ' Сброс порта при включение ( выставление рабочего положения )

Dim X As Byte
X = 1

On_Interrupt GoTo OBRABOTCHIK    ' Если приозошло прирывание то перейти к указаной метке

    Symbol INTE = INTCON.4 ' Бит разрешения прерывания по PORTB.0(INT)
    Symbol GIE = INTCON.7 ' Бит глобального разрешения прерываний
    Symbol INTF = INTCON.1 ' Флаг внешнего прерывания по PORTB.0(INT)
    
    OPTION_REG = %10000000 ' Фронт прерывания - передний, отключим PULLUP
    GIE = 1          ' ращрешить глобальное прирываени 

Symbol DT1 = PORTA.2    
Symbol LED1 = PORTB.3 
Symbol LED2 = PORTA.2
DelayMS 1000
PORTA.3 = 1
LED1 = 1
DelayMS 1000 
LED1 = 0
GoTo MAIN

OBRABOTCHIK:
Context Save
If INTF = 1 Then  'Если было прерывание по INT  
  INTF = 0        'сбросим флаг прерывания от INT
  INTE = 0        ' сбросим Бит разрешения прерывания по PORTB.0(INT)
X = 0
End If
Context Restore
 Retfie

MAIN:
INTE = 1
LED1 = 0
LED2 = 0
If X = 0 Then time
GoTo MAIN

time:
For X = 0 To 15
INTE = 0
If X > 5 Then INTE = 1
LED1 = 1
LED2 = 1
DelayMS 500
LED2 = 0
DelayMS 500
Next
GoTo MAIN

End

данный пример не является критичным, задача именно разобраться с самим методом перехода, необходимо перейти к определённой подпрограмме после установки факта прерывания, 9 по умолчанию в какой бы части программы не произошло прерывание, после его обработки происходит возврат в то же место, а это не всегда уместно. Подскажите как быть? book
ЯНДЕКС Дата: 31.07.2014
shaman Дата: Чт, 31.07.2014, 13:45  |                                                                                                                Сообщение # 2
Группа: Проверенные
Ранг:  Могу и подсказать
Сообщений: 179
Репутация: 5   ±
Замечания:   ±
На сайте с 07.11.2011

Статус: Offline

День добрый , вот ссылка может немного прояснит  как Вам делать программу
http://www.picbasic.ru/publ/preryvanie_po_ljubomu_portu_mk/2-1-0-74
cheh Дата: Чт, 31.07.2014, 15:28  |                                                                                                                Сообщение # 3
Группа: Проверенные
Ранг:  Новенький
Сообщений: 4
Репутация: 0   ±
Замечания:   ±
На сайте с 27.12.2011

Статус: Offline

Цитата tesla88 ()
данный пример не является критичным, задача именно разобраться с самим методом перехода, необходимо перейти к определённой подпрограмме после установки факта прерывания, 9 по умолчанию в какой бы части программы не произошло прерывание, после его обработки происходит возврат в то же место, а это не всегда уместно. Подскажите как быть?
Не совсем понятно куда вы хотите переходить после обработки прерывания, программа в любом случае будет возвращаться к месту прерывания..
tesla88 Дата: Чт, 31.07.2014, 16:43  |                                                                                                                Сообщение # 4
Группа: Проверенные
Ранг:  Продвинутый
Сообщений: 121
Репутация: 0   ±
Замечания:   ±
На сайте с 20.11.2010

Статус: Offline

вот в том то и дело, что возврат к исходной точке не всегда необходим, порой при сработке прерывания нужно немедленно перейти в конкретную подпрограмму ( к примеру произошло прерывание и надо незамедлительно произвести подсчёт импульсов на входе мк, но но делоть это в теле программы обработки прерывания нежелательно , так как в ней нельзя находиться долгое время, а ждать пока пройдут все процедуры от выхода из обработчика прерываний и до нужной подпрограммы проходя через час общего листинга , это слишком долго.
MiXaS Дата: Чт, 31.07.2014, 18:22  |                                                                                                                Сообщение # 5
Группа: Проверенные
Ранг:  Разобрался
Сообщений: 618
Репутация: 26   ±
Замечания:   ±
На сайте с 02.10.2010

Статус: Offline

Так в протене есть 2 обработчика прерывания: аппаратный и программый!
Программный пишется On Interrupt, On_Interrupt или On_Hardware_Interrupt.

Цитата tesla88 ()
вот в том то и дело, что возврат к исходной точке не всегда необходим, порой при сработке прерывания нужно немедленно перейти в конкретную подпрограмму ( к примеру произошло прерывание и надо незамедлительно произвести подсчёт импульсов на входе мк, но но делоть это в теле программы обработки прерывания нежелательно , так как в ней нельзя находиться долгое время, а ждать пока пройдут все процедуры от выхода из обработчика прерываний и до нужной подпрограммы проходя через час общего листинга , это слишком долго.


В этом и фишка аппаратного прерывания. Выполняется основная программа до тех пор, пока не произойдет одно из событий прерывания: таймеры, USART, USB, mssp, portb и т.д (все зависит от настройки камня). Как только прилетел пакет данных или portb изменил свое состояние, происходит прерывание и код выполняется подрограммы, где вы можете незамедлительно считать импульсы, или принимать данные от переферии по шинам данных. Как только посчитали или приняли, можно отправляться в основную программу и обрабатывать полученные данные. если у вас несколько прерываний, то сначало нужно определить причину прерывания, прочитав соотв. флаги, а потом уже читать данные или считывать пакеты.

Если у Вас простая задача, например, просто считать импульсы или еще что, то обычно загоняется код в бесконечный цикл с выходом по условию. Так проще.
tesla88 Дата: Чт, 31.07.2014, 18:41  |                                                                                                                Сообщение # 6
Группа: Проверенные
Ранг:  Продвинутый
Сообщений: 121
Репутация: 0   ±
Замечания:   ±
На сайте с 20.11.2010

Статус: Offline

да это то всё понятно, я всегда так и делал, но вот если стоит такая задача - выплняется программа - пришло прерывание - происходит обработка прерывания и выполнение каких либо действий, а в это время надо ждать другие прерывания, а он не может этого сделать , так как он и так в подпрограмме прерывания, для этого и надо перейти в в другую конкретную подпрограмму в которой будет выполняться полезное действие  и ожидать новых прерываний. я говорю не про преведёный выше листинг - это просто пример  - хотя даже в нём надо перейти из обработчика сразу к метке time: минуя main: , вот как это правильно сделать , что бы не терять лишнее время  в основной программе?
MiXaS Дата: Чт, 31.07.2014, 21:49  |                                                                                                                Сообщение # 7
Группа: Проверенные
Ранг:  Разобрался
Сообщений: 618
Репутация: 26   ±
Замечания:   ±
На сайте с 02.10.2010

Статус: Offline

я вижу это так: либо выбрать преоритеты в настройках, если есть либо в подпрограмме постоянно проверять флаги других прерываний
tesla88 Дата: Чт, 31.07.2014, 22:36  |                                                                                                                Сообщение # 8
Группа: Проверенные
Ранг:  Продвинутый
Сообщений: 121
Репутация: 0   ±
Замечания:   ±
На сайте с 20.11.2010

Статус: Offline

то есть более демократичного варианта нет? опрашивать постоянно флаги в теле основной программы это как раз тот вариант которы я всегда использую, но если по пути поподается какая небудь пауза, тогда время реакции выполнения подпрограммы естественно увеличевается, а это порой недопустимо
xvovanx Дата: Пт, 01.08.2014, 09:31  |                                                                                                                Сообщение # 9
Группа: Проверенные
Ранг:  Помогаю всем
Сообщений: 262
Репутация: 12   ±
Замечания:   ±
На сайте с 02.05.2013

Статус: Offline

Если честно, то я так и не понял сути проблемы. Если использовать не програмные прерывания, а именно железные, то и пауза ваша будет рваться и переходить в обработку прерываний, а по возвращению кусок паузы продлится. Только не забываем в железном прерывании сначала сохранять, а в конце восстанавливать состояния регистров. Хоть сделайте 10 сек паузу, а в прерывании (железном) моргание светодиода, и он бедет моргать. Или для полной ясности опишите, как вы хотите, чтоб работало ваше железо.
Сообщение отредактировал xvovanx - Пт, 01.08.2014, 09:36
MiXaS Дата: Пт, 01.08.2014, 10:17  |                                                                                                                Сообщение # 10
Группа: Проверенные
Ранг:  Разобрался
Сообщений: 618
Репутация: 26   ±
Замечания:   ±
На сайте с 02.10.2010

Статус: Offline

Цитата tesla88 ()
то есть более демократичного варианта нет? опрашивать постоянно флаги в теле основной программы это как раз тот вариант которы я всегда использую, но если по пути поподается какая небудь пауза, тогда время реакции выполнения подпрограммы естественно увеличевается, а это порой недопустимо


Нет! Я же говорю, что есть программная обработка прерываний, а есть аппаратная! Программная - это как раз о чем Вы пишите. Вы хотите использовать аппаратную, но не совсем понимаете как она работает. Я постараюсь на пальцах объяснить.

Напрмер, Ваша основная программа занимается миганием LED. 500мс горит, 500 не горит. Задачи принять данные через usart по протоколу, допустим модбас, и сформировать ответ незамедлительно, так как протокол жестко регламентирован по времени. При этом на portb.0 привязаны кнопки для управления чето-то еще, тоже через прерывание.

Происходит прерывание (какое-то, мы еще не знаем какое). Выполнение основного кода останавливается и идет переход к метке обработки прерывания. Как только мы попали в обработку прерывания сразу сохраняем контекст (понятно, что надо выключить глобальные....) проверяем какое событие нас сюда позвало.
ЕСЛИ ФЛАГ ВНЕШНЕГО ПРЕРЫВАНИЯ, ТО ИНКРЕМЕНТИРОВАТЬ КАКУЮ-ТО ПЕРЕМЕННУЮ.
ЕСЛИ ФЛАГ USART (НОВЫЙ ПАКЕТ), ТО ПРИНИМАЕМ ВСЕ БАЙТЫ ПО ОЧЕРЕДИ И ЗАПИСЫВАЕМ ИХ В БУФЕР.
отвечаем мастеру на запрос.

ПОСЛЕ сбрасывается флаг прерывания, включаются глобальные и остальные разрешения и восстанавливается контекст.

И сразу же после слов восстановление контекста основной код начнет выполняться ровно с того места, с которого его сдернуло прерывание.
Нужно отметить, что либо объявить директиву либо прописать регистр о разрешении сохранении контекста. Declare FSR_CONTEXT_SAVE = On

Допустим, что есть несколько событий прерывания и одни очень важные, например, быстрый подсчет импульсов, а есть не очень важные, например, обработка кнопок, то для этих целей в 18 серии PIC(может и в некоторых 16 есть, но мне не попадались) есть такое понятие, как приоритет прерываний. У вас 2 события прерывания, но так как настроен приоритет на подстчет импульсов, то остальные проигнарируются.

Лично опробовано на 16 серии пик такая ситуация. 2 таймера и USART. Все работали через прерывание. Думаю если вы сильно спешите, что то измерять, нужно каменюку по-сложнее и кварц по-быстрее или PLL использовать. Кстати очень веселая штука.

Сообщение отредактировал MiXaS - Пт, 01.08.2014, 10:24
tesla88 Дата: Пт, 01.08.2014, 18:29  |                                                                                                                Сообщение # 11
Группа: Проверенные
Ранг:  Продвинутый
Сообщений: 121
Репутация: 0   ±
Замечания:   ±
На сайте с 20.11.2010

Статус: Offline

MiXaS большое спасибо за разъяснение, тоесть как вывод - выйти из обработчика прерывания в какое то конкретное место нельзя, так как он возвращается к точке прерывания, хорошо, это понятно, тогда такой вопрос - сколько времени можно находиться в обработчике? ( считать импульсы по входу, принимать пакеты данных и тд.) есть ли какие то ограничения ( просто читал в какойто статье на данном форуме, что использование паущ и длительное пребывание в обработчике не есть хорошо).
MiXaS Дата: Сб, 02.08.2014, 11:02  |                                                                                                                Сообщение # 12
Группа: Проверенные
Ранг:  Разобрался
Сообщений: 618
Репутация: 26   ±
Замечания:   ±
На сайте с 02.10.2010

Статус: Offline

tesla88, действительно, использование пауз не желательно в подпрограмме, я лично испытал на себе это. По поводу долго находиться нельзя, мне кажется это заблуждение. Сколько надо, столько и будете считать свои импульсы, хоть вечно. я проверял, написал такой жеский код, что контроллер тратил около секунды в подпрограмме, а потом выходил.Я при изу2чении прерываний использовал светодиоды, и тогда стало ясно где находится точка программы. У меня тоже была нужда из под программы отправиться куда–нибудь, но я не помню чем это кончилось.
tesla88 Дата: Сб, 02.08.2014, 20:36  |                                                                                                                Сообщение # 13
Группа: Проверенные
Ранг:  Продвинутый
Сообщений: 121
Репутация: 0   ±
Замечания:   ±
На сайте с 20.11.2010

Статус: Offline

Всем спасибо, думаю тему можно закрыть! smile
ADMIN Дата: Пн, 04.08.2014, 05:46  |                                                                                                                Сообщение # 14
Администратор
Группа: Администраторы
Ранг:  Специалист
Сообщений: 1109
Репутация: 24   ±
Замечания:   ±
На сайте с 20.08.2007

Статус: Offline

Я подозреваю, что каким-то образом можно использовать для этого счетчик программной памяти. Хотя, скорее всего, ошибаюсь.
xvovanx Дата: Чт, 23.10.2014, 21:10  |                                                                                                                Сообщение # 15
Группа: Проверенные
Ранг:  Помогаю всем
Сообщений: 262
Репутация: 12   ±
Замечания:   ±
На сайте с 02.05.2013

Статус: Offline

Добрый вечер!
Прочитал ветку, но так конкретно не нашел: можно ли из обработчика прерываний перейти на подпрограмму в теле программы и затем вернуться обратно в обработчик в то место откуда был переход? При этом флаг прерывания скинем до выхода на подпрограмму, чтоб из самого тела программы не попасть опять в начало обработчика прерываний.

Добавлено (23.10.2014, 21:10)
---------------------------------------------
Вопрос снят, гораздо проще обойтись диодами на вывод INT (как в ссылке выше), схема работает нормально. А то у меня сигнал INT в схеме приходил чуть раньше других сигналов и все глючило, а теперь сами сигналы "делают для себя" нужный им INT.

Сообщение отредактировал xvovanx - Чт, 23.10.2014, 21:05
Форум Picbasic.ru » Программирование МК » Proton PicBasic » Работа с прерываниями
Страница 1 из 41234»
Поиск: