26.03.2016, 03:25
|
|
Частый гость
Регистрация: 26.03.2016
Сообщений: 18
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Прерывания в PIC16F8x
Доброго всем здоровья
Подскажите пожалуйста, почему программа не переводит контроллер в режим прерывания?
Тестирую в MPLAB и в ISIS. Программа проходит без ошибок и замыкается в цикле _int. Только ручное выставление в MPLAB бита INTF=1 переводит на прерывание.
Подозреваю косяк в неправильном определении PORTB и OPTION_REG.
Но я уже перепробовал разные комбы сигналов и ни разу не смог автоматом запустить прерывание
Запуск прерывания должен происходить низким сигналом от кнопки, что я и попытался сделать
:
Код:
|
;-----------------MAIN PROGRAM----------------------------------------
main ; метка основного цикла
bcf INTCON,7 ; запрет прерываний
movlw b'11111111' ;здесь выставляю разреш. на
movwf PORTB ;внешнее управление.
bsf STATUS,5 ;На ножке RB0 висит кнопка
;включения прерывания
movwf b'11111101' ;RB1 - диод мигающий в прерывании
movwf TRISB ;на остальных ножках будут gthtrk.xfntkb
;триггеры
bsf STATUS,5
bcf OPTION_REG,6 ; Выставляю внеш.
;прерывания по спаду
;сигнала т.е. прерывание
;если RB0=0
bcf STATUS,5
clrf INTCON ;очищаю INTCON и разрешаю
;прерывания
bsf INTCON,4
bsf INTCON,7
;----------------------------------------------------------------------------
_int NOP ; Жду прерывание, а его нет
GOTO _int |
Последний раз редактировалось Vasil133; 26.03.2016 в 03:29.
Причина: удобочитаемость
|
|
|
|
26.03.2016, 04:39
|
|
Супер-модератор
Регистрация: 09.06.2011
Сообщений: 2,686
Сказал спасибо: 74
Сказали Спасибо 1,807 раз(а) в 654 сообщении(ях)
|
Re: Прерывания в PIC16F8x
Vasil133, в программе явная ошибка: 5-я строчка, вместо movlw b'11111101' у Вас movwf b'11111101', поэтому в железе светодиод на линии RB1 не загорается, так как эта линия в итоге конфигурируется как вход (следующей командой в регистр TRISB записывается значение '11111111', оставшееся в WREG от последней команды movlw).
А вообще, программы с использованием внешних прерываний нужно тестировать в "Протеусе", а не в MPLAB-е. Удачи!
|
|
|
|
26.03.2016, 07:09
|
|
Заблокирован
Регистрация: 07.09.2014
Адрес: В Кремле!
Сообщений: 4,486
Сказал спасибо: 396
Сказали Спасибо 2,221 раз(а) в 1,319 сообщении(ях)
|
Re: Прерывания в PIC16F8x
Вот они, первые последствия видеоуроков от mplasek... STATUS,5, INTCON,4 . А я фик знает, что такое INTCON,4, я просто не помню номеров битов.
Да и прога составлена неправильно. Конфигурация входов-выходов должна быть вне основного цикла, ведь в этой проге она (кнфигурация входов-выходов) постоянна, не меняется.
Ну и да, INT - это прерывание от внешнего сигнала на ножке INT. Чтобы оно возникло, надо изменить состояние на входе INT.
|
|
|
|
26.03.2016, 08:28
|
|
Супер-модератор
Регистрация: 09.06.2011
Сообщений: 2,686
Сказал спасибо: 74
Сказали Спасибо 1,807 раз(а) в 654 сообщении(ях)
|
Re: Прерывания в PIC16F8x
Сообщение от NewWriter
|
Да и прога составлена неправильно.
|
Ну, не то, чтобы неправильно... Бездумно, скорее. Взять, например, хотя бы это:
Код:
|
main ; метка основного цикла
bcf INTCON,7 ; запрет прерываний |
А собственно, зачем? После старта МК этот разряд и так будет =0.
Далее, зачем-то дважды даётся команда " bsf STATUS,5". Возможно, ТС решил "на всякий случай" ещё раз включить 1-й банк регистров перед записью в OPTION_REG ?..
Ну и, наконец:
Код:
|
clrf INTCON ; очищаю INTCON и разрешаю
; прерывания
bsf INTCON,4
bsf INTCON,7 |
А вот здесь, раз уж мы так любим заменять нормальные имена регистров цифрами, можно было бы написать:
Код:
|
movlw 0x90 ; Разрешаем прерывание по RB0.
movwf INTCON |
(Только просьба не кидать в меня тапками, я всего лишь призываю быть последовательным! )
..
Сообщение от NewWriter
|
Конфигурация входов-выходов должна быть вне основного цикла, ведь в этой проге она (кнфигурация входов-выходов) постоянна, не меняется.
|
А "main" - это у него не основной цикл, а как раз конфигурация, похоже.
Основной цикл у него вот:
Код:
|
_int NOP ; Жду прерывание, а его нет
GOTO _int |
|
|
|
|
26.03.2016, 14:06
|
|
Частый гость
Регистрация: 26.03.2016
Сообщений: 18
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: Прерывания в PIC16F8x
Сообщение от RECTO
|
Vasil133, в программе явная ошибка: 5-я строчка, вместо movlw b'11111101' у Вас movwf b'11111101', поэтому в железе светодиод на линии RB1 не загорается, так как эта линия в итоге конфигурируется как вход (следующей командой в регистр TRISB записывается значение '11111111', оставшееся в WREG от последней команды movlw).
А вообще, программы с использованием внешних прерываний нужно тестировать в "Протеусе", а не в MPLAB-е. Удачи!
|
Спасибо!
Тестирую в Протеусе, да, он же ISIS Professional.
Сообщение от NewWriter
|
Да и прога составлена неправильно. Конфигурация входов-выходов должна быть вне основного цикла, ведь в этой проге она (кнфигурация входов-выходов) постоянна, не меняется.
Ну и да, INT - это прерывание от внешнего сигнала на ножке INT. Чтобы оно возникло, надо изменить состояние на входе INT.
|
Эммм... Вообще-то меняется, по крайней мере должна (я так полагаю).
По идее должно быть так:
RB0 - кнопочка разрешающая прерывание.
RB2,RB3 - принимают сигналы с датчиков, меняющих состояние порта с лог.1 на лог.0.
RB1 - моргает диодом, соответственно диод должен сохранить своё начальное состояние.
Жму кнопку, запускаю прерывание, перехожу в программу прерывания и считываю сигналы с RB1,RB2 в отдельный регистр.
Т.е. после прерывание RB1,RB2 надо вернуть лог.1, поэтому прога конфигурирует порт заново.
Я уже чувствую, что так не делается, но это моя первая программа и опыта пока нет ?
Сообщение от RECTO
|
Ну, не то, чтобы неправильно... Бездумно, скорее. Взять, например, хотя бы это:
Код:
|
main ; метка основного цикла
bcf INTCON,7 ; запрет прерываний |
А собственно, зачем? После старта МК этот разряд и так будет =0.
|
Насчет названия портов всё понял, исправил у себя. Лишние куски кода вырезал.
Нули в INTCON в начале конфигурации впихнул, т.к. прочитал в каком-то обсуждении, что это обязательно нужно и без этого вообще никак. В общем перестраховался. Думаю тот кто советовал боялся, что прерывание запустится прямо в конфигурации. Удалил.
|
|
|
|
26.03.2016, 14:30
|
|
Частый гость
Регистрация: 26.03.2016
Сообщений: 18
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: Прерывания в PIC16F8x
Сейчас вот так выглядит:
В протеусе RB0 получает лог.0, но прерывание не происходит
Код:
|
movlw b'11111101'
movwf PORTB
bsf STATUS,5
movlw b'11111101'
movwf TRISB
bcf OPTION_REG,INTEDG
bcf STATUS,5
clrf INTCON
bsf INTCON,INTE
bsf INTCON,GIE
_int NOP
GOTO _int |
Схема в Протеусе
В покое
Кнопка зажата
Последний раз редактировалось Vasil133; 26.03.2016 в 14:34.
|
|
|
|
26.03.2016, 15:02
|
|
Прописка
Регистрация: 19.02.2008
Адрес: г. Иркутск
Сообщений: 277
Сказал спасибо: 218
Сказали Спасибо 171 раз(а) в 79 сообщении(ях)
|
Re: Прерывания в PIC16F8x
Нашел свои старые программы, делал так и все работало.
int_rb0.txt
Последний раз редактировалось andron007; 26.03.2016 в 15:04.
|
|
|
|
26.03.2016, 15:07
|
|
Прописка
Регистрация: 19.02.2008
Адрес: г. Иркутск
Сообщений: 277
Сказал спасибо: 218
Сказали Спасибо 171 раз(а) в 79 сообщении(ях)
|
Re: Прерывания в PIC16F8x
Подтягивающего резистора на RB0 нет. Поставь его и будет счастье.
Последний раз редактировалось andron007; 26.03.2016 в 15:09.
|
|
|
|
26.03.2016, 15:07
|
|
Заблокирован
Регистрация: 07.09.2014
Адрес: В Кремле!
Сообщений: 4,486
Сказал спасибо: 396
Сказали Спасибо 2,221 раз(а) в 1,319 сообщении(ях)
|
Re: Прерывания в PIC16F8x
ну и раз уж на то пошло, то
Сообщение от Vasil133
|
почему программа не переводит контроллер в режим прерывания?
|
- а потому, что программа и не обязана переводить контроллер в режим прерываний.
Режим прерываний - это как раз такой режим, который прерывает (если разрешено) обычное исполнение программы по реакции на какое-то событие. Конкретно в этом случае - INT - реакция на изменение уровня входного сигнала на ножке RB0/INT.
Конечно очень желательно параллельно проштудировать доки на микроконтроллер, чтобы понимать, что такое вообще прерывание.
И кстати, для такой задачи можно в принципе не использовать само прерывание, а проверять только выставление флага запроса прерывания INTF. Этот флаг будет выставлен при наступлении события, в частности, переход уровня сигнала с "1" в "0" на входе RB0/INT.
Программу, в принципе, можно записать вот так:
Код:
|
list p=PIC16F84A
include ‹P16F84A.INC›
org 0x00
;-- Инициализация МК -----------------
Initial_MCU:
clrf PORTB ;начальная очистка порта
bsf STATUS, RP0 ;‹‹Bank1››
bcf TRISB, 1 ;выход для светодиода
bcf OPTION_REG, INTEDG ;срабатывание по -\_ на INT
bcf STATUS, RP0 ;‹‹Bank0››
bsf PORTB, 1 ;включение светодиода
bcf INTCON, INTF ;страховочный сброс флага прерывания
;-- Основной цикл -----------------------
Wait_INT:
btfss INTCON, INTF ;ожидание появления флага от -\_ на INT
goto Wait_INT ;если нету флага, повторить ожидание
;.. Реакция на нажатую кнопку и выполнение действий ..........
bcf INTCON, INTF ;сброс флага программно
movf PORTB, W ;чтение входов порта
andlw b'00001100' ;отфильтровывание ненужных сигналов
movwf 0x20 ;запись в регистр с адресом 0х20 состоян.датчиков
bcf PORTB, 1 ;гашение светодиода
..тут должна помещаться программная задержка на сотню-две миллисек.
bsf PORTB, 1 ;включение обратно светодиода
goto Wait_INT ;возврат к ожиданию нажатия кнопки |
Ну и касательно схемы - просто жизненно необходимо на ножку RB0/INT через подтягивающий резистор (модель PULLUP в протеусе) подать лог.1, иначе при отпущенной кнопке на входе будет неопределенный уровень.
Сообщение от Vasil133
|
Т.е. после прерывание RB1,RB2 надо вернуть лог.1, поэтому прога конфигурирует порт заново.
|
Проблема в понимании логики. Давай, во-первых, не перепутывать нумерацию выводов (то одно, то другое получается с RB1), а во-вторых, давай прочтем в доках, что что такое порты микроконтроллера, какие состояния у них могут быть (входы, выходы), а в-третьих, нарисуем на листочке схематично то, что должна делать программа - в виде схемки из квадратиков и стрелочек.
Типа такого (только графически):
- начальное состояние - такое-то, RB0/INT - вход, RB1 - выход светодиода, и он горит (лог.1 на выходе), RB2, RB3 - входы сигналов. Ожидается прерывание по -\_ (спаду) на RB0/INT.
- кнопку нажали, на RB0/INT устанавливается лог.0, выполняем действия:
..читаем порт, отфильтровываем ненужные сигналы, записываем состояние в регистр, мигаем светодиодом на RB1, сбрасываем программно флаг INTF и возвращаемся к ожиданию нажатия
То есть, как видишь, тут нет переконфигурирования направления порта (вход/выход) и нет других начальных установок.
Сообщение от Vasil133
|
Нули в INTCON в начале конфигурации впихнул, т.к. прочитал в каком-то обсуждении, что это обязательно нужно и без этого вообще никак. В общем перестраховался. Думаю тот кто советовал боялся, что прерывание запустится прямо в конфигурации.
|
в целом, логично, но надо не в начале конфигурации, а в конце, перед самым разрешением прерываний. Причина проста - начальный конфиг может быть длинным и занимать продолжительное время, за время которого может произойти какое-то прерывание, еще до выхода МК в нормальный (рабочий) режим, и при разрешении прерываний произойдет сразу реакция на них, а это может быть не запланировано и нежелательно.
Последний раз редактировалось NewWriter; 26.03.2016 в 15:40.
|
|
|
|
26.03.2016, 19:06
|
|
Супер-модератор
Регистрация: 09.06.2011
Сообщений: 2,686
Сказал спасибо: 74
Сказали Спасибо 1,807 раз(а) в 654 сообщении(ях)
|
Re: Прерывания в PIC16F8x
Сообщение от Vasil133
|
Жму кнопку, запускаю прерывание, перехожу в программу прерывания и считываю сигналы с RB1,RB2 в отдельный регистр.
Т.е. после прерывание RB1,RB2 надо вернуть лог.1, поэтому прога конфигурирует порт заново.
|
Что-то я совершенно не улавливаю полёт Вашей мысли... Для чего и каким образом Вы хотите "вернуть" туда лог. "1"? Если RB1 и RB2 у Вас настроены на вход и читают сигналы датчиков, то никакая запись в порт (точнее, в выходную защёлку порта) не изменит состояние этих линий (потому что соответствующие TRISB = "1"). Теперь вопрос - зачем? Значение, которое Вы читаете из PORTB, всегда будет соответствовать уровням сигналов, которые реально присутствуют на этих линиях. То есть, если Вы думаете, что при чтении PORTB эти данные там как-то "защёлкиваются" - то это не так...
Сообщение от Vasil133
|
RB1 - моргает диодом, соответственно диод должен сохранить своё начальное состояние.
|
И насчёт светодиода... Да, его надо возвращать в первоначальное положение. Но делать это нужно не в обработчике прерывания, иначе не увидите, как он моргнул.
Тут NewWriter уже советовал Вам воспользоваться программной задержкой. Я бы сделал задержку по таймеру, примерно так:
- при конфигурации: настраиваем предделитель и разрядность таймера таким образом, чтобы его цикл соответствовал времени свечения светодиода, например 1/2 секунды, обнуляем флаг прерывания таймера.
- в прерывании: зажигаем светодиод, сбрасываем таймер, запускаем таймер.
- в основном цикле: проверяем флаг прерывания таймера. Если он установлен, то гасим светодиод, останавливаем таймер, обнуляем флаг прерывания таймера.
Сообщение от Vasil133
|
Насчет названия портов всё понял, исправил у себя. Лишние куски кода вырезал.
|
Не все. Скажите, зачем у Вас дважды присутствует команда " movlw b'11111101'"? Полагаете, значение из W куда-то могло исчезнуть?..
И кстати, вот здесь-то можно было бы ограничиться командой " bcf TRISB,1" вместо " movwf TRISB", т.к. состояние этого регистра после сброса = "11111111" и нужно изменить только 1 бит. А вот с регистром PORTB так делать никогда не стоит! Команды чтения-модификации-записи с этим портом могут сработать неправильно - как раз потому, что читаются реальные значения на линиях порта (не важно, настроены они на ввод или на вывод), а запись производится в выходные защёлки.
Сообщение от Vasil133
|
Нули в INTCON в начале конфигурации впихнул, т.к. прочитал в каком-то обсуждении, что это обязательно нужно и без этого вообще никак. В общем перестраховался. Думаю тот кто советовал боялся, что прерывание запустится прямо в конфигурации.
|
Не "нули" Вы туда впихнули, а обнулили только один разряд - INTCON,GIE. На кой - не понятно. Если Вы до этого нигде его не устанавливали =1, то он после сброса так и останется =0. "Перестраховываться" в данном случае нет никакого смысла.
Сообщение от Vasil133
|
В протеусе RB0 получает лог.0, но прерывание не происходит
|
Так даже в Протеусе видно, что при отпущенной кнопке состояние вывода не определено (индикатор имеет серый цвет). Вас это не насторожило разве?..
В общем, подтяните эту линию к + через резистор, либо включите внутреннюю подтяжку на порту В, всё должно заработать.
..
Последний раз редактировалось RECTO; 26.03.2016 в 21:48.
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 03:45.
|
|