Прерывание STM32:
Прерывание — это механизм, который позволяет возникновению внешних событий или определенных условий прерывать нормальный поток выполнения программы, тем самым выполняя определенную процедуру обслуживания прерывания. Это облегчает возможность реагировать и обрабатывать внешние события в режиме реального времени. Прерывания в микроконтроллерах STM32 бывают двух типов: внутренние прерывания и внешние прерывания.
Почти каждый вывод может быть настроен на прерывание независимо. Подробную информацию можно найти в «Китайском справочном руководстве».
Ссылка: «Справочное руководство STM32F10X-на китайском языке», глава «Прерывания и события». «Руководство Wildfire STM32»
NVIC — это вложенный векторный контроллер прерываний, который управляет функциями всего чипа, связанными с прерываниями. Он тесно связан с ядром и является периферийным устройством внутри ядра.
Регистр NVIC включает в себя следующие функции:
typedef struct {
__IO uint32_t ISER[8]; // Регистр разрешения прерываний
uint32_t RESERVED0[24];
__IO uint32_t ICER[8]; // Прерывание очистки регистра
uint32_t RSERVED1[24];
__IO uint32_t ISPR[8]; // Регистр ожидания включения прерывания
uint32_t RESERVED2[24];
__IO uint32_t ICPR[8]; // Прерывание очистки ожидающего регистра
uint32_t RESERVED3[24];
__IO uint32_t IABR[8]; // Прерывание действительного битового регистра
uint32_t RESERVED4[56];
__IO uint8_t IP[240]; // Регистр приоритета прерываний (8 бит wide)
uint32_t RESERVED5[644];
__O uint32_t STIR; // Регистр прерываний, запускаемых программным обеспечением
} NVIC_Type;
Обычно используются только три регистра: ISER, ICER и IP.,ISER используется для разрешения прерываний, ICER — для отключения прерываний, а IP — для установки приоритета прерываний.。
Чем меньше значение, тем выше приоритет. В серии F103 используется только 0-4, но в принципе есть 0-255,
4 бита, используемые для выражения приоритета, сгруппированы в приоритет вытеснения и подприоритет.
Три шага:
typedef struct {
uint8_t NVIC_IRQChannel; // Источник прерывания
uint8_t NVIC_IRQChannelPreemptionPriority; // Приоритет вытеснения
uint8_t NVIC_IRQChannelSubPriority; // подприоритет
FunctionalState NVIC_IRQChannelCmd; // Включить или отключить прерывания
} NVIC_InitTypeDef;
Внешний контроллер прерываний/событий состоит из 20 детекторов фронтов, которые генерируют запросы на события/прерывания. Каждая входная линия может быть независимо настроена на тип входа (импульсный или приостановочный) и соответствующее событие запуска (нарастающий фронт или спадающий фронт, или оба фронта срабатывают). ). Каждая входная линия может быть независимо экранирована. Регистр ожидания содержит строку состояния для запросов на прерывание.
Косая черта 20 указывает, что внутри контроллера имеется 20 одинаковых сигнальных линий, а EXTI имеет всего 20 линий прерываний/событий.
Красный цвет представляет прерывание, а зеленый — событие.
Целью создания линии прерывания является ввод входного сигнала в NVIC, а затем запуск функции обслуживания прерываний для реализации функции, которая находится на программном уровне. Целью создания линии событий является передача импульсного сигнала другим периферийным устройствам для использования, и это передача сигнала на уровне схемы, то есть на аппаратном уровне.
EXTI имеет 20 линий прерываний/событий. Каждый GPIO может быть установлен как входная линия, занимающая от EXTI0 до EXTI15. Есть еще семь строк для определенных периферийных событий, см. таблицу EXTI Interrupt_Event Lines.
4 определенные периферийные линии прерываний/событий запускаются периферийными устройствами. Для конкретного использования обратитесь к конкретным инструкциям по периферийным устройствам в «STM32F10X-Китайское справочное руководство».
EXTI0–EXTI15 используются для GPIO. С помощью программного управления любой GPIO может использоваться в качестве источника входного сигнала EXTI. Из строки таблицы EXTI error_event видно, что EXTI0 можно настроить как PA0, PB0, PC0, PD0, PE0, PF0, PG0, PH0 или PI0 через биты EXTI0[3:0] регистра конфигурации внешнего прерывания AFIO 1 ( AFIO_EXTICR1).
typedef struct {
uint32_t EXTI_Line; // линия прерывания/события
EXTIMode_TypeDef EXTI_Mode; // EXTI-режим
EXTITrigger_TypeDef EXTI_Trigger; // Тип триггера
FunctionalState EXTI_LineCmd; // EXTI включить
} EXTI_InitTypeDef;
Определение макроса:
//определение контакта
#define KEY1_INT_GPIO_PORT GPIOA
#define KEY1_INT_GPIO_CLK (RCC_APB2Periph_GPIOA\
|RCC_APB2Periph_AFIO)
#define KEY1_INT_GPIO_PIN GPIO_Pin_0
#define KEY1_INT_EXTI_PORTSOURCE GPIO_PortSourceGPIOA
#define KEY1_INT_EXTI_PINSOURCE GPIO_PinSource0
#define KEY1_INT_EXTI_LINE EXTI_Line0
#define KEY1_INT_EXTI_IRQ EXTI0_IRQn
#define KEY1_IRQHandler EXTI0_IRQHandler
#define KEY2_INT_GPIO_PORT GPIOC
#define KEY2_INT_GPIO_CLK (RCC_APB2Periph_GPIOC\
|RCC_APB2Periph_AFIO)
#define KEY2_INT_GPIO_PIN GPIO_Pin_13
#define KEY2_INT_EXTI_PORTSOURCE GPIO_PortSourceGPIOC
#define KEY2_INT_EXTI_PINSOURCE GPIO_PinSource13
#define KEY2_INT_EXTI_LINE EXTI_Line13
#define KEY2_INT_EXTI_IRQ EXTI15_10_IRQn
Конфигурация NVIC
static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* КонфигурацияNVIC имеет приоритетную группу 1. */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/* Конфигурация Источник прерывания:кнопка1 */
NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ;
/* Конфигурация Приоритет вытеснения:1 */
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
/* Конфигурацияподприоритет:1 */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
/* включить канал прерываний */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Конфигурация Источник прерывания:кнопка2,Другие варианты использования, связанные с Конфигурацией выше. */
NVIC_InitStructure.NVIC_IRQChannel = KEY2_INT_EXTI_IRQ;
NVIC_Init(&NVIC_InitStructure);
}
Конфигурация прерывания EXIT
void EXTI_Key_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
/*Включаем часы кнопки GPIO порта*/
RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK,ENABLE);
/* Конфигурация NVIC Прерывать*/
NVIC_Configuration();
/*--------------------------KEY1Конфигурация---------------------*/
/* Выберите GPIO, используемый кнопкой */
GPIO_InitStructure.GPIO_Pin = KEY1_INT_GPIO_PIN;
/* Конфигурация – это плавающий ввод. */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure);
/* Выбор источника сигнала EXTI */
GPIO_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE, \
KEY1_INT_EXTI_PINSOURCE);
EXTI_InitStructure.EXTI_Line = KEY1_INT_EXTI_LINE;
/* EXTI — режим прерывания */
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
/* прерывание по нарастающему фронту */
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
/* Включить прерывания */
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
/*--------------------------KEY2Конфигурация------------------*/
/* Выберите GPIO, используемый кнопкой */
GPIO_InitStructure.GPIO_Pin = KEY2_INT_GPIO_PIN;
/* Конфигурация – это плавающий ввод. */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStructure);
/* Выбор источника сигнала EXTI */
GPIO_EXTILineConfig(KEY2_INT_EXTI_PORTSOURCE, \
KEY2_INT_EXTI_PINSOURCE);
EXTI_InitStructure.EXTI_Line = KEY2_INT_EXTI_LINE;
/* EXTI — режим прерывания */
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
/* Прерывание по заднему фронту */
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
/* Включить прерывания */
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
}
Функция обслуживания прерываний
void KEY1_IRQHandler(void)
{
//Убедимся, что EXTI сгенерирован Обрыв линии
if (EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET) {
// LED1 отрицать
LED1_TOGGLE;
//Очистим бит флага прерывания
EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);
}
}
void KEY2_IRQHandler(void)
{
//Убедимся, что EXTI сгенерирован Обрыв линии
if (EXTI_GetITStatus(KEY2_INT_EXTI_LINE) != RESET) {
// LED2 отрицать
LED2_TOGGLE;
//Очистим бит флага прерывания
EXTI_ClearITPendingBit(KEY2_INT_EXTI_LINE);
}
}
Если эта статья была для вас полезна, пожалуйста, поддержите блогера трижды!