SPL: внешние прерывания

    Краткое описание: Прерывание это сигнал который сообщает процессору о том что наступило некое событие, в ответ на которе требуется выполнить определенное действие. В этот момент происходит остановка выполнения основной программы, сохраняется состояние системы и выполняется подпрограмма, выполняется она в обработчике прерывания. Прерывания бывают внешними, например от кнопки (такой случай мы рассмотрим в этой статье) и могут генерироваться при наступлении определенного события в самом процессоре: переполнение таймера, получение данных по UART и так далее.

     Для настройки работы внешних прерываний требуется сделать:


1)Выбрать и настроить нужный ножки на работу в режиме входа 
2)Функция SYSCFG_EXTILineConfig(), дает возможность выбрать порт и ножку в качестве источника внешних прерываний
3)Настроить поля структуры EXTI_InitTypeDef настройки прерывания 
4)Настроить поля структуры NVIC_InitTypeDef приоритетного контроллера прерываний

     Обслуживание прерываний происходит через приоритетный контроллер NVIC, поэтому кроме настроек прерываний нужно настроить и приоритетный контроллер.

     Задача: Требуется написать с использованием библиотеки StdPeriph код. В основном цикле программы и в функции обработки прерывания производить поочередное переключение пользовательских светодиодов. Прерывание должно происходить при нажатии пользовательской кнопки.

#include "stm32f30x.h"
#include "stm32f30x_gpio.h"
#include "stm32f30x_rcc.h"
#include "stm32f30x_exti.h"
#include "stm32f30x_syscfg.h"
#include "stm32f30x_misc.h"

GPIO_InitTypeDef gpio; //Объявляем переменную gpio типа GPIO_InitTypeDef
EXTI_InitTypeDef exti; //Объявляем переменную exti типа EXTI_InitTypeDef
NVIC_InitTypeDef nvic; //Объявляем переменную nvic типа NVIC_InitTypeDef

int i; //Переменная для цикла задержки

void initAll() //Функция инициализации
{
    RCC_HSICmd(ENABLE); //Включаем тактирование от внутреннего источника
    RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI); //Подаем тактовый сигнал на системную шину
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE); //Включаем тактирование порта С
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); //Включаем тактирование SYSCFG

    gpio.GPIO_Mode = GPIO_Mode_IN; //Выбираем режим работы пинов: ВХОД
    gpio.GPIO_Pin = GPIO_Pin_0; //Выбираем нужный пин
    GPIO_Init(GPIOC, &gpio); //Инициализируем структуру с настройками

    gpio.GPIO_Mode = GPIO_Mode_OUT; //Выбираем режим работы пинов: ВЫХОД
    gpio.GPIO_Pin = GPIO_Pin_6; //Выбираем нужный пин
    GPIO_Init(GPIOC, &gpio); //Инициализируем структуру с настройками

    gpio.GPIO_Mode = GPIO_Mode_OUT; //Выбираем режим работы пинов: ВЫХОД
    gpio.GPIO_Pin = GPIO_Pin_7; //Выбираем нужный пин
    GPIO_Init(GPIOC, &gpio); //Инициализируем структуру с настройками

    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource0); //Подключает линию внешних прерываний EXTI к порту GPIOС пину 0

    exti.EXTI_Line = EXTI_Line0; //Выбор линии прерывания
    exti.EXTI_Mode = EXTI_Mode_Interrupt; //Выбор типа реакции прерывание/событие: прерывание
    exti.EXTI_Trigger = EXTI_Trigger_Rising; //Срабатывание по нарастающему фронту: из 0 в 1
    exti.EXTI_LineCmd = ENABLE; //Включаем прерывание
    EXTI_Init(&exti); //Инициализируем структуру с настройками

    nvic.NVIC_IRQChannel = EXTI0_IRQn; // Назначает источник прерывания
    nvic.NVIC_IRQChannelPreemptionPriority = 0; //Выставляет приоритет прерывания
    nvic.NVIC_IRQChannelSubPriority = 0; //Выставляет уровень подчинённости
    nvic.NVIC_IRQChannelCmd = ENABLE; //Включаем приоритетный контроллер прерывания
    NVIC_Init(&nvic); //Инициализируем структуру с настройками
}

int main()
{
    __enable_irq(); //Разрешаем прерывания
    initAll(); //Вызываем функцию инициализации

    while (1) {
        GPIO_ResetBits(GPIOC, GPIO_Pin_6); //Выключаем красный светодиод
        GPIO_SetBits(GPIOC, GPIO_Pin_7); //Включаем зеленый светодиод
    }
}

void EXTI0_IRQHandler() //Функция обработчика прерываний
{
    EXTI_ClearFlag(EXTI_Line0); //Очищаем флаг прерывания

    GPIO_ResetBits(GPIOC, GPIO_Pin_7); //Выключаем зеленый светодиод
    GPIO_SetBits(GPIOC, GPIO_Pin_6); //Включаем красный светодиод
    for (i = 0; i < 90000; i++); //Немного ждем перед прекращением работы обработчика
}

     Скомпилируйте программу нажав кнопку Build, прошейте микроконтроллер, нажмите RESET. Должен гореть зеленый светодиод. Нажмите на кнопку, если все сделано правильно то ненадолго загорится красный светодиод и снова загорится зеленый.

     ВНИМАНИЕ: Приведенный листинг кода не является единственной и оптимальной реализацией поставленной задачи. Пример опубликован с демонстрационной целью. Также автор во избежание переписывания чужих статей, пропускает теоретические основы необходимые для понимания примера, связывая это с тем что всю необходимую информацию можно найти в интернете.

Комментариев (0)

Написать комментарий

Имя *
E-mail
Введите комментарий *
Капча
12 + ? = 14