Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32F407 внешние прерывания на линии 5_9
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Mister_DSP
Доброе время суток!

Так уж получилось, что приходится использовать Port C8 для ножки внешнего прерывания с устройства.
Я чуть не пророс, когда увидел, что порты с номерами 5,6,7,8,9 объединены в один обработчик прерывания - в Keil это функция EXTI9_5_IRQHandler().
Ранее на макете были линии 0 и 4 (на них линии и обработчики прерываний по-отдельности и о подвохах не догадывался).

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

Инициализация(здесь в тексте много опущено для упрощения):
CODE
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
hd44780
Цитата(Mister_DSP @ Dec 17 2016, 12:38) *
Можно ли в обработчике не делать проверку:
Код
if(EXTI_GetITStatus(EXTI_Line8)!=RESET)......


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

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

Цитата(Mister_DSP @ Dec 17 2016, 12:38) *
И когда правильнее сбрасывать бит прерывания - ДО или ПОСЛЕ полезной нагрузки?
Код
EXTI_ClearITPendingBit(EXTI_Line8); //Clear interrupt flag

Моё ИМХО - после нагрузки.
EugenPKH
Цитата(hd44780 @ Dec 17 2016, 12:45) *
Насколько я понимаю - да. но если Вы добавите 5,6,7 или 9 - условия понадобятся.


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


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

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

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

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

CODE

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


При этом порты инициализируются раньше, чем разрешаются прерывание.
И такое на AVR-ках тоже было.

Как можно это устранить?
Сергей Борщ
Пока вы не разрешите прерывания от ног 5-7, 9 в регистре EXTI->IMR, они не будут выставлять свои флаги и не будут вызывать прерывание. Как это делается в SPL или кубах - понятия не имею. В обычной жизни для этого достаточно одной строки записи в регистр.
Mister_DSP
Цитата(Сергей Борщ @ Dec 17 2016, 14:51) *
Пока вы не разрешите прерывания от ног 5-7, 9 в регистре EXTI->IMR, они не будут выставлять свои флаги и не будут вызывать прерывание. Как это делается в SPL или кубах - понятия не имею. В обычной жизни для этого достаточно одной строки записи в регистр.

Так речь идет о том, что как раз я и разрешаю прерывание и оно в первый раз случается без воздействия внешнего устройства (источника прерывания).
Подозреваю, что такое поведение возникает из-за запоминания контроллером состояния перепада уровня при настройке портов.
А вот со второго раза и далее - прерывания уже идут в тему - от устройства.
ViKo
Так вы его очистите, прежде, чем разрешать.
EugenPKH
Цитата(Mister_DSP @ Dec 17 2016, 14:45) *
EugenPKH, прерывание по перепаду состояния, а не по уровню. Там же ТАКЖЕ сбрасывается бит ВНЕШНЕГО устройства. Так что при любом желании, оно повторно не выскочет.

При этом порты инициализируются раньше, чем разрешаются прерывание.
И такое на AVR-ках тоже было.

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



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

Чтоб убрать первое вхождение в прерывания при запуске - на просто перед разрешением прерывания сбросить флаг
EXTI->PR = EXTI_PR_PR8; Как через библиотеку не знаю.



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

помогла очистка флага перед разрешением прерывания: EXTI_ClearITPendingBit(EXTI_Line8);
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.