Прерывания в PIC16F628A

Прерывания – это очень полезная вещь в микроконтроллерах, она позволяет отвлечь контроллер от выполнения основной программы, на подпрограмму при срабатывании одного из прерываний. Прерывания могу быть как внешними: изменения уровня сигнал на одном из выводов или приход сообщения в USART … , так и внутренними: при переполнении таймера или совершения операции работы с внутренней EPROM памятью …

Немного теории

За прерывания в микроконтроллерах среднего семейства PIC отвечает регистр INTCON. Он содержит биты разрешения прерываний и флаги, что прерывание произошло.

Регистр INTCON

Для начала работы с прерываниями в регистре INTCON нужно разрешить прерывания вообще, для этого бит GIE устанавливаем в единицу. Также нужно разрешить прерывания от нужных источников.

Несколько источников прерываний содержится уже в регистре INTCON, другая часть содержится в регистрах PIE/PIR, для их использования нужно в регистре INTCON разрешить прерывания от периферийных модулей – бит PEIE. Все возможные источники прерываний среднего семейства PIC микроконтроллеров представлены на следующем рисунке:

Регистры PIE/PIR

Для PIC16F628A регистр PIE выглядит следующим образом:

PIC16F628A регистр PIE

После срабатывание прерывания текущая выполняемая задача (функция) в микроконтроллере приостанавливается, и управление передаётся специальной функции — interrupt isr, которая отвечает за обработку прерываний, после обработки прерывания выполнение приостановленной функции продолжается. В этой функции можно опросив флаги возможных прерываний – определить, какое из них произошло. Обработчик прерываний должен содержать как можно меньше операций, что бы как можно быстрее вернуть управление главной функции, если конечно там что-то важное может обрабатываться.

Практика

Рассмотрим 2 варианта прерываний: по изменению уровня сигнала на RB7 и по приходу байта в модуль USART.

Соберём небольшую схему, которая будет содержать: кнопку, приёмник USART и 2 светодиода индикации.

Схема

Задача: загорание на некоторое время первого светодиода по пришествии байта в USART и загорание ненадолго второго светодиода по нажатию кнопки.

Для начала нужно эти источники прерываний инициализировать:

INTCON=0b11001000;	//	Разрешены прерывания, разрешены прерывания от периферии, разрешить прерывания от PORTB< 4:7>
RCIE=1;				// Разрешить прерывания от приёмника USART

Ниже приведена функция обработки прерываний — interrupt isr . В ней нужно опросить флаги возможных источников прерываний, выполнить нужные действие и в заключение сбросить флаги произошедших прерываний. Если эти флаги не сбросить то по прекращению обработки этой функции управление вернётся не к приостановленной функции, а обратно к обработчику прерываний.

void interrupt isr(void)
{
if(RBIF)	//	Обрабатываем прерывания на входах PORTB< 4:7>
{
	if(RB7==0)
	{
		LP_ON;
		LP_time=1000;
	}
	RBIF=0;	//	сбрасываем флаг
}
if(RCIF)	//	Обрабатываем прерывания от приёмника USART
{
	getch_Usart();
	LU_ON;
	LU_time=1000;
}
}

В свою очередь в функции проверяем, какое прерывание произошло, включаем соответствующий светодиод и задаём время, которое он будет гореть, далее сбрасываем флаги произошедших прерываний.
т.к. обрабатываем только приход байта в USART, то заодно в обработчике прерываний очищаем входной буфер этого модуля, так же имея 4 входа в обработчике RBIF, проверяем только нужный.

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

Скачать исходники, прошивку, проект в proteus

Статья обновлена 02.07.2011

6 комментариев на « Прерывания в PIC16F628A»

  1. Роман пишет 27.06.2011 в 20:26 #

    Небольшое замечание ради справедливости ) . Флаг прерывания RCIF программно сбросить нельзя , он сбрасывается сам после чтения байта из буфера . В данном случае после getch_Usart(); он уже сброшен . И строка : RCIF=0; не нужна , тем более бесполезна см.выше .

  2. Alex_EXE пишет 02.07.2011 в 04:12 #

    Для надёжности сбрасывал 🙂 . Убрал, спасибо.

  3. ИЛЬЯ пишет 14.08.2013 в 19:57 #

    Скажите а как включить внешний кварц,или как изменять биты регистра управления?

  4. Виктор пишет 26.09.2016 в 17:27 #

    Может быть я ошибаюсь , но :
    Разве так, как указано в примере RBIF возможно сбросить?
    Мне казалось, что сперва необходимо программе прочитать PORT B, а затем сбрасывать флаг.
    if(RBIF)
    {
    if(RB7==0)
    {
    LP_ON;
    LP_time=1000;
    }
    PORT B ; // читаем порт
    RBIF=0; // сбрасываем флаг
    }

  5. Medved пишет 18.01.2022 в 08:51 #

    Смею заметить, что не все компиляторы С самостоятельно выполняют сохранение регистров при уходе в обработку прерывания. Т.е. в программе обработки прерывания перво-наперво мы должны выполнить сохранение важных регистров (цитата из даташита):
    ——————————————————
    — сохранить регистр W;
    — сохранить регистр STATUS в банке памяти 0;
    — выполнить код обработки прерываний;
    — восстановить регистр STATUS (с восстановлением текущего банка);
    — восстановить регистр W.
    ……………..
    — В конкретных приложениях может потребоваться сохранять и другие специальные регистры (например, FSR,
    PCLATH).
    ————————————————————-
    У вас же об этом не упомянуто даже вскользь. Т.е. надо читать доки на сам компилятор, умеет ли он по умолчанию в сохранение регистров или нет.
    Проясню ситуацию — я не гуру, я просто самостоятельно разбираюсь в программировании МК PIC для решения нужной мне задачи, и на эти грабли с регистрами я только что звонко наступил.

  6. Alex_EXE пишет 21.01.2022 в 07:51 #

    Ассемблер конечно хорошо, но тут приподнялись на уровень повыше, на C, что бы облегчить себе работу и уйти от прямой работы с регистрами контроллера.
    В программировании PIC контроллеров я применял компилятор HITECH, какой уже не вспомню. Компилятор, который идёт в комплекте с MPLAB X IDE должен это поддерживать.
    В статье приведенное замечание не упоминается, т.к. видимо об него, когда самостоятельно изучал в свой время PIC контроллеры не споткнулся и не подозревал о нём.

Комментарии RSS

Оставьте отзыв