STM8S GPIO и прерывания от внешнего источника(External interrupt).
Что бы не уходить далеко от темы GPIO решил сразу написать статью, как использовать внешние прерывания на выводах контроллера. Все функции(вектора) прерываний находятся в файле stm8s_it.c он должен быть добавлен в проект, будем описывать на примере использования прерывания на порту GPIOB пин 7, контроллер STM8S903K3.
Для удобства давайте перенесем эту функцию в код нашей программы, просто скопируйте и вставьте как обычную функцию, прописывать в начале кода ее не надо, но удалите ее здесь а то вылетит ошибка что она продублирована.
Теперь будем использовать SPL, с начало нужно настроить порт и пин, вариантов тут два GPIO_MODE_IN_FL_IT(болтающийся вход) или GPIO_MODE_IN_PU_IT(подтянут через резистор к питанию), выбираем второй.
GPIO_Init( GPIOB, GPIO_PIN_7, GPIO_MODE_IN_PU_IT);
Теперь нужно установить приоритет прерывания от GPIOB, это нужно для того, что бы при возникновении одновременно двух прерываний было обработано главное, по вашему мнению потом остальные, установить конкретному выводу нельзя только всему порту.
Всего есть четыре приоритета:
ITC_PRIORITYLEVEL_0-Самый низкий, используется контроллером для выполнения программы и других нужд, поэтому его использовать нельзя.
ITC_PRIORITYLEVEL_1-Выше нулевого.
ITC_PRIORITYLEVEL_2-Выше первого.
ITC_PRIORITYLEVEL_3-Самый высокий и установлен по умолчанию.
Устанавливаем функцией ITC_SetSoftwarePriority( IrqNum, PriorityValue), PriorityValue это и есть наши приоритет а вот IrqNum источник которому будет присвоен, в нашем случае следующие варианты, порты A,B,C,D и E:
ITC_IRQ_PORTA
ITC_IRQ_PORTB
ITC_IRQ_PORTC
ITC_IRQ_PORTD
ITC_IRQ_PORTE
ITC_SetSoftwarePriority(ITC_IRQ_PORTB, ITC_PRIORITYLEVEL_1);
Необходимо установить как от чего или какого события должно срабатывать прерывание, следующие варианты:
EXTI_SENSITIVITY_FALL_LOW-Спад уровня с высокого на низкий или будет срабатывать постоянно пока будет низкий уровень.
EXTI_SENSITIVITY_RISE_ONLY-Переход с низкого к высокому уровню.
EXTI_SENSITIVITY_FALL_ONLY-Переход с высокого на низкий.
EXTI_SENSITIVITY_RISE_FALL-Переход с низкого к высокому или с высокого на низкий.
Будем делать это функцией EXTI_SetExtIntSensitivity( Port, SensitivityValue) где SensitivityValue выше варианты а Port:
EXTI_PORT_GPIOA
EXTI_PORT_GPIOB
EXTI_PORT_GPIOC
EXTI_PORT_GPIOD
EXTI_PORT_GPIOE
EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOB, EXTI_SENSITIVITY_FALL_ONLY);
Осталось включить глобальные прерывания.
enableInterrupts();
И конечно не большой пример, в котором при подключение пин 7 GPIOB к земле будет срабатывать прерывание и вызывать функцию обработчик в которой будем менять уровень на противоположный(включать, выключать GPIOD пин 0).
#include "stm8s.h"
int main( void ){
GPIO_Init(GPIOB, GPIO_PIN_7, GPIO_MODE_IN_PU_IT);
GPIO_Init(GPIOD, GPIO_PIN_0, GPIO_MODE_OUT_PP_LOW_SLOW);
ITC_SetSoftwarePriority(ITC_IRQ_PORTB, ITC_PRIORITYLEVEL_1);
EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOB, EXTI_SENSITIVITY_FALL_ONLY);
enableInterrupts();
while(1){
}
}
INTERRUPT_HANDLER(EXTI_PORTB_IRQHandler, 4)
{
GPIO_WriteReverse( GPIOD, GPIO_PIN_0);
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line)
{
while (1){}
}
#endif
Хочу обратить ваше внимание таки выводы на которых есть в Pin name дополнительное назначение TLI, это означает что эти выводы будут иметь всегда наивысший приоритет для прерывания, менять его нельзя.
Таких тут два PC3 и PD7, для установки на них прерывания нужно применить следующую функцию
EXTI_SetTLISensitivity(SensitivityValue), SensitivityValue имеет два варианта:
EXTI_TLISENSITIVITY_FALL_ONLY-Срабатывает при спаде уровня, на пинах где включено прерывание.
EXTI_TLISENSITIVITY_RISE_ONLY-Срабатывает при подъеме уровня.
EXTI_SetTLISensitivity( EXTI_TLISENSITIVITY_FALL_ONLY);
Для обработки прерывания использовать особый обработчик INTERRUPT_HANDLER(TLI_IRQHandler, 0), пример ниже.
#include "stm8s.h"
int main( void ){
GPIO_Init( GPIOD, GPIO_PIN_0, GPIO_MODE_OUT_PP_LOW_SLOW);
/*Сначала настраиваем прерывание только потом включаем.*/
EXTI_SetTLISensitivity( EXTI_TLISENSITIVITY_FALL_ONLY);
/*Включаем прерывание от TLI.*/
GPIO_Init( GPIOD, GPIO_PIN_7, GPIO_MODE_IN_PU_IT);
enableInterrupts();
while(1){
}
}
INTERRUPT_HANDLER( TLI_IRQHandler, 0)
{
GPIO_WriteReverse( GPIOD, GPIO_PIN_0);
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line)
{
while (1){}
}
#endif
У этих видов прерываний отсутствуют флаги срабатывания, поэтому если установлено более одного прерывания на один порт или TLI(PC3 и PD7 одновременно) нужно будет проверять пины в обработчике например вот так.
if(GPIO_ReadInputPin( GPIOD, GPIO_PIN_7)){
//Тут то, что надо выполнить если на пине высокий уровень.
}
if(!GPIO_ReadInputPin( GPIOD, GPIO_PIN_7)){
//Тут то, что надо выполнить если на пине низкий уровень.
}
Я думаю этой информации будет достаточно для освоения внешних прерыванияь.