|
PIC16F74 непонятки с прерыванием, хаотичная ошибка прерывания по таймеру |
|
|
|
Oct 28 2015, 15:13
|
Участник

Группа: Участник
Сообщений: 20
Регистрация: 28-10-15
Пользователь №: 89 059

|
Здравствуйте. Столкнулся с непонятным явлением при обработке прерывания по переполнению таймера1. Исходные данные: сделаны часы на PIC16F74, используется статическая индикация и контроллер выбран просто из-за большого количества выводов быстродействие не требуется абсолютно, поэтому установлен LP режим и кварц на 32768 при данной частоте и использовании предделителя, период переполнения таймера1 составляет 64 сек поэтому данный таймер использован для подсчёта минутных интервалов разрешено единственное прерывание по его переполнению, в процедуре обработки сначала старший байт таймера перезагружается значением 10Н (чтоб сократить период до 60 сек), затем увеличивается регистр минут, часов, напоследок сбрасывается флаг прерывания основная программа просто непрерывно по кругу выводит часы и минуты в сегментном коде на порты и проверяет кнопки управления Проблема такая: в сутки хаотично добавляется от 5 до 20 минут все попытки как то программно отследить происходящее эффекта не дали рассматривался и вопрос ложных прерываний от другово источника (в обработчик вставлялась проверка флагов и вывод на индикацию если будет обнаруже отличный от переполнения таймера), и помехи по кнопкам управления (они просто выкидывались из исходного кода) нет, происходит именно хаотичное двойное увеличение счетчика при обработке, такое впечатление что иногда не сбрасывается флаг и после выполнения RETFIE прерывание тут же вызывается снова Проблема в принципе решена: в итоге прерывание было просто запрещено, в обработчике RETFIE заменено на обычный RETURN, в начало обработчика вставлена проверка бита переполнения и выход если бит не обнаружен, во все циклы основной программы просто натыканы CALL 4 т.е. реализовано тоже самое прерывание, только тупо программной имитацией все сбои сразу исчезли Вопрос: куда копать то? задача текущая конечно закрыта, но надо на будущее как то понять всё же
|
|
|
|
|
 |
Ответов
|
Oct 28 2015, 16:35
|
Участник

Группа: Участник
Сообщений: 20
Регистрация: 28-10-15
Пользователь №: 89 059

|
Цитата(Herz @ Oct 28 2015, 21:09)  если этого не делать, то повторный вызов практически гарантирован, имхо хмммм.........., я вас понял, проверю но я не понял какая разница за сколько команд до RETFIE сбрасывать флаг? главное сбросить до ну а если обаботчик, допустим, вообще состоял бы из 2-3 коменд? допустим по прерыванию просто сбросить бит в каком-либо порту и всё это как то некорректно и обработчик должен быть не менее, допустим, 15 команд? бррррр................ есть какие то ссылки на аппноты по данной теме? Код org 4
movwf buf1 movf STATUS,w movwf buf2 clrf STATUS
movlw 16 movwf TMR1H
incf min,f movlw 60 subwf min,w btfss STATUS,C goto iend
clrf min incf hour,f movlw 24 subwf hour,w btfsc STATUS,C clrf hour end clrf PIR1 movf buf2,w movwf STATUS movf buf1,w retfie
Сообщение отредактировал ddd-ekb - Oct 28 2015, 16:39
|
|
|
|
|
Oct 29 2015, 04:58
|
Местный
  
Группа: Участник
Сообщений: 211
Регистрация: 18-03-13
Из: Питер
Пользователь №: 76 081

|
Цитата(ddd-ekb @ Oct 28 2015, 20:35)  есть какие то ссылки на аппноты по данной теме? Дык, п. 6.4 даташита. Подозреваю, что проблема именно в атомарности операции. В более современных чипах (например 887) эта проблема решена аппаратно, а в старых приходилось изгаляться. P.S.: Кстати, насколько помню, рекомендовалось таймер, при этом, вообще выключать (в примере этого нет).
|
|
|
|
|
Oct 29 2015, 06:03
|
Участник

Группа: Участник
Сообщений: 20
Регистрация: 28-10-15
Пользователь №: 89 059

|
Цитата(Smen @ Oct 29 2015, 09:58)  Дык, п. 6.4 даташита. Подозреваю, что проблема именно в атомарности операции. В более современных чипах (например 887) эта проблема решена аппаратно, а в старых приходилось изгаляться. P.S.: Кстати, насколько помню, рекомендовалось таймер, при этом, вообще выключать (в примере этого нет). не понял, п 6.4 посвещён внешнему счёту вроде как ------------------ 6.4 Timer1 Operation in Asynchronous Counter Mode If control bit T1SYNC (T1CON<2>) is set, the external clock input is not synchronized. The timer continues to increment asynchronous to the internal phase clocks. The timer will continue to run during SLEEP and can generate an interrupt on overflow, which will wake-up the processor. However, special precautions in software are needed to read/write the timer (Section 6.4.1). In Asynchronous Counter mode, Timer1 cannot be used as a time-base for capture or compare operations ----------------------- тут же таймер используется с внутренней osc/4 и предделителем :8 T1CON инициализирован "00110101", согласно страницей даташита выше, бит 2 ( синхронизация внешней частоты ) игнорируется, если бит 1 = 0 (использование внутренней частоты ) ------------------- bit 7-6 Unimplemented: Read as ‘0’ bit 5-4 T1CKPS1:T1CKPS0: Timer1 Input Clock Prescale Select bits 11 = 1:8 Prescale value 10 = 1:4 Prescale value 01 = 1:2 Prescale value 00 = 1:1 Prescale value bit 3 T1OSCEN: Timer1 Oscillator Enable Control bit 1 = Oscillator is enabled 0 = Oscillator is shut-off (the oscillator inverter is turned off to eliminate power drain) bit 2 T1SYNC: Timer1 External Clock Input Synchronization Control bit TMR1CS = 1: 1 = Do not synchronize external clock input 0 = Synchronize external clock input TMR1CS = 0: This bit is ignored. Timer1 uses the internal clock when TMR1CS = 0. bit 1 TMR1CS: Timer1 Clock Source Select bit 1 = External clock from pin RC0/T1OSO/T1CKI (on the rising edge) 0 = Internal clock (FOSC/4) bit 0 TMR1ON: Timer1 On bit 1 = Enables Timer1 0 = Stops Timer1 ---------------------- да даже и в этом случае, ну пусть сбои счёта происходили какие то, но не двойное же выполнение прерывания зы: пока играюсь дальше с прошивкой, вроде вырисовывается зависимость, но опять же дурацкая какая то
Сообщение отредактировал ddd-ekb - Oct 29 2015, 06:05
|
|
|
|
|
Oct 29 2015, 06:44
|

Местный
  
Группа: Свой
Сообщений: 206
Регистрация: 17-03-07
Из: Москва
Пользователь №: 26 266

|
Цитата(ddd-ekb @ Oct 29 2015, 09:03)  ... По поводу предделителя и буквой "i" я тоже так прикинул, как вы потом и написали. По поводу таймера и п.6.4, там действительно несколько строчек, которые меня тоже насторожили, но имеется ввиду (в п. 6.4. и потом), что если во время записи произойдет переполнение таймера, результат может быть непредсказуемым. Если вы от нас ничего не скрываете (вы не обижайтесь, я немножко отклонюсь: приходят сюда, значит, [не]определенные товарищи и подбрасывают всякие казусы. Мы начинаем здесь ломать копья, стрелы, организуем интеллектуальные [и не очень] битвы титанов, и наконец, где-то на десятой странице обсуждения, когда чуть ли не мы уже подрались здесь всем форумом, приходит топик стартер и такой, "а вот и не угадали! у меня MCLR был не подключен, вот и болтался в воздухе, вот и происходили случайные сбросы." и ставит три улыбочки, для подчеркивания эффекта.), значит нужно посмотреть другое: Судя по вашим продуманным (в общем) действиям, с железом у вас все в порядке. Но не помешало бы, еще раз перепроверить. Потом. Это действительно старый процессор. Я смотрю, вы весь PIR1 обнуляете. Но это - только периферийные прерывания. Есть еще и в INTCON-е. Не забывайте, что, например Таймер0 нельзя отключить, он всегда работает, даже и если настроить его брать такт с T0CKI. Но! Самый главный подводный камень - по-страничная организация памяти. Если у вас осуществляется переход (типа goto, return, retlw и т.д.) из одной страницы на другую, то это вам нужно позаботиться правильно переключить биты RP0 и RP1 в STATUS-е. Скорее всего это именно ваш случай. Таким образом вы можете попасть аккурат в середину обработчика прерываний и он исполнится. Другая очень часто встречаемая ошибка - табличное чтение. Если при чтении из таблицы (вычисляемый офсетный переход), вы проскочите и попадете в пустую область, программный счетчик просто перелопатит всю программную память и вернется на адрес 0. Опять со всеми вытекающими. Для этого перед табличным чтением всегда нужно проверять аргумент функции - не превышает ли его значение количество объектов в таблице. Также, имейте ввиду (хотя, это вряд ли ваш случай), при переполнении или при попытке уменьшать указатель стека ниже ноля, происходит сброс. Это может случится, например, если по какой-то причине не сбросился флаг прерываний (IF). Так что - посмотрите все очень внимательно и если есть новые соображения - спрашивайте.
--------------------
УЭР
|
|
|
|
Сообщений в этой теме
ddd-ekb PIC16F74 непонятки с прерыванием Oct 28 2015, 15:13   evc Цитата(ddd-ekb @ Oct 28 2015, 19:35)... Oct 28 2015, 18:58    ddd-ekb Цитата(evc @ Oct 28 2015, 23:58) Каждый р... Oct 28 2015, 19:07      ddd-ekb по порядку
1 ничего не скрываю, разработкой всякой... Oct 29 2015, 11:36     Smen Цитата(ddd-ekb @ Oct 29 2015, 10:03)... Oct 29 2015, 08:54 ViKo Думаю, ошибка в прерывании. Не могу вникать-вспоми... Oct 29 2015, 12:05 ddd-ekb Цитата(ViKo @ Oct 29 2015, 17:05) swapf -... Oct 29 2015, 12:20  ViKo Цитата(ddd-ekb @ Oct 29 2015, 15:20)... Oct 29 2015, 12:27   ddd-ekb Цитата(ViKo @ Oct 29 2015, 17:27) В прогр... Oct 29 2015, 12:41 evc ddd-ekb, слово "скрываете" я использовал... Oct 29 2015, 12:41  ddd-ekb Цитата(evc @ Oct 29 2015, 17:41) именно а... Oct 29 2015, 13:03   evc Цитата(ddd-ekb @ Oct 29 2015, 16:03)... Oct 29 2015, 13:11    ddd-ekb Цитата(evc @ Oct 29 2015, 18:11) из-за эт... Oct 29 2015, 15:39     evc Цитата(ddd-ekb @ Oct 29 2015, 19:39)... Oct 29 2015, 16:28      ddd-ekb Цитата(evc @ Oct 29 2015, 21:28) Нет, тол... Oct 29 2015, 16:36
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|