Перейти к содержанию
    

STM32F407 внешние прерывания на линии 5_9

Доброе время суток!

 

Так уж получилось, что приходится использовать Port C8 для ножки внешнего прерывания с устройства.

Я чуть не пророс, когда увидел, что порты с номерами 5,6,7,8,9 объединены в один обработчик прерывания - в Keil это функция EXTI9_5_IRQHandler().

Ранее на макете были линии 0 и 4 (на них линии и обработчики прерываний по-отдельности и о подвохах не догадывался).

 

Пока код использую такой (он рабочий).

 

Инициализация(здесь в тексте много опущено для упрощения):

GPIO_InitTypeDef gpio;
EXTI_InitTypeDef exti;
NVIC_InitTypeDef nvic;	

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);

GPIO_StructInit(&gpio);

//INPUT
//C8=>IRQ !!!
gpio.GPIO_Pin=GPIO_Pin_8;
gpio.GPIO_Mode=GPIO_Mode_IN;
gpio.GPIO_Speed=GPIO_Speed_25MHz; //!!!
gpio.GPIO_OType=GPIO_OType_PP;
gpio.GPIO_PuPd=GPIO_PuPd_NOPULL;
GPIO_Init(GPIOC,&gpio);

//IRQ C8
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,EXTI_PinSource8);

exti.EXTI_Line=EXTI_Line8;
exti.EXTI_LineCmd=ENABLE;
exti.EXTI_Mode=EXTI_Mode_Interrupt;
exti.EXTI_Trigger=EXTI_Trigger_Rising;
EXTI_Init(&exti);

nvic.NVIC_IRQChannel=EXTI9_5_IRQn;
nvic.NVIC_IRQChannelPreemptionPriority=0;
nvic.NVIC_IRQChannelSubPriority=0;
nvic.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&nvic);

 

Сам обработчик:

void EXTI9_5_IRQHandler()
{
if(EXTI_GetITStatus(EXTI_Line8)!=RESET) //Make sure that interrupt flag is set
{

  //Тут код полезной нагрузки.......


  EXTI_ClearITPendingBit(EXTI_Line8); //Clear interrupt flag
  
  return; //для надёжности - на одном сайте говорили что лучше так принудительно выходить :)
}
}

 

За CMSIS и SPL не пинайте, так как не являюсь фанатом КУБа и его HAL.

 

Вопрос вот в чём:

Я использую одну из ножек порта C - линию 8 для прерывания (настроена на ввод). Этот же порт C я использую для аппаратного SPI + ещё другие линии отдельно как GPIO на вывод.

 

Можно ли в обработчике не делать проверку:

 if(EXTI_GetITStatus(EXTI_Line8)!=RESET)......

 

а сразу приступать к полезной нагрузке? При условии что более нет прерываний на C5,6,7,9 ? И линия 8 также не используется по прерываниям.

 

И когда правильнее сбрасывать бит прерывания - ДО или ПОСЛЕ полезной нагрузки?

EXTI_ClearITPendingBit(EXTI_Line8); //Clear interrupt flag

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Можно ли в обработчике не делать проверку:

 if(EXTI_GetITStatus(EXTI_Line8)!=RESET)......

 

а сразу приступать к полезной нагрузке? При условии что более нет прерываний на C5,6,7,9 ? И линия 8 также не используется по прерываниям.

Насколько я понимаю - да. но если Вы добавите 5,6,7 или 9 - условия понадобятся.

 

И когда правильнее сбрасывать бит прерывания - ДО или ПОСЛЕ полезной нагрузки?

EXTI_ClearITPendingBit(EXTI_Line8); //Clear interrupt flag

Моё ИМХО - после нагрузки.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Насколько я понимаю - да. но если Вы добавите 5,6,7 или 9 - условия понадобятся.

 

 

Моё ИМХО - после нагрузки.

 

Не знаю как в данной библиотек ( SPL ,HAL ) но если на CMSIS то надо До, Если поставить после, то может не сбросится прерывание и будет повторный заход , чтоб этого не произошло надо еще барьер ставить тогда.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо за внимание.

 

Сделал как hd44780 написал - работает, глюки пока не обнаружены.

 

EugenPKH, прерывание по перепаду состояния, а не по уровню. Там же ТАКЖЕ сбрасывается бит ВНЕШНЕГО устройства. Так что при любом желании, оно повторно не выскочет.

 

Вот зато есть такая особенность: при включении питания прерывание срабатывает сразу в первый раз!

Приходится программно игнорировать первое вхождение:

 

static char f=0;
if(!f)f=1;
else
{
//...делаем полезное...
}

 

При этом порты инициализируются раньше, чем разрешаются прерывание.

И такое на AVR-ках тоже было.

 

Как можно это устранить?

Изменено пользователем Mister_DSP

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пока вы не разрешите прерывания от ног 5-7, 9 в регистре EXTI->IMR, они не будут выставлять свои флаги и не будут вызывать прерывание. Как это делается в SPL или кубах - понятия не имею. В обычной жизни для этого достаточно одной строки записи в регистр.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пока вы не разрешите прерывания от ног 5-7, 9 в регистре EXTI->IMR, они не будут выставлять свои флаги и не будут вызывать прерывание. Как это делается в SPL или кубах - понятия не имею. В обычной жизни для этого достаточно одной строки записи в регистр.

Так речь идет о том, что как раз я и разрешаю прерывание и оно в первый раз случается без воздействия внешнего устройства (источника прерывания).

Подозреваю, что такое поведение возникает из-за запоминания контроллером состояния перепада уровня при настройке портов.

А вот со второго раза и далее - прерывания уже идут в тему - от устройства.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так вы его очистите, прежде, чем разрешать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

EugenPKH, прерывание по перепаду состояния, а не по уровню. Там же ТАКЖЕ сбрасывается бит ВНЕШНЕГО устройства. Так что при любом желании, оно повторно не выскочет.

 

При этом порты инициализируются раньше, чем разрешаются прерывание.

И такое на AVR-ках тоже было.

 

Как можно это устранить?

 

 

Если будете сбрасывать прерывания не через библиотеку, а напрямую(EXTI->PR = EXTI_PR_PR8;) увидите двойной вхождения скорее всего. Второе вхождения происходит из-за того что не успевает флаг сбросится , а не потому что его кто то вызвал.

 

Чтоб убрать первое вхождение в прерывания при запуске - на просто перед разрешением прерывания сбросить флаг

EXTI->PR = EXTI_PR_PR8; Как через библиотеку не знаю.

 

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

всем спасибо.

 

помогла очистка флага перед разрешением прерывания: EXTI_ClearITPendingBit(EXTI_Line8);

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...