Обработчик прерывания STM32F4 для захвата его не вызывается

В приведенном ниже коде используется функция сравнения захвата канала 3 TIM1 для захвата нарастающего фронта на PE10, но она не работает, обработчик прерывания не вызывается. Я не очень хорошо разбираюсь в этом встроенном материале, так может ли кто-нибудь сказать мне, правильно ли я его настраиваю?

#include "STM32/stm32f4xx_tim.h"

void TIM1_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;

  /* TIM1 clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);

  /* GPIOA clock enable */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);

  /* TIM1 channel 3 pin (PE.10) configuration */
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOE, &GPIO_InitStructure);

  /* Connect TIM pins to AF2 */
  GPIO_PinAFConfig(GPIOE, GPIO_PinSource10, GPIO_AF_TIM1);

  /* Enable the TIM1 global Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

  TIM_ICInitTypeDef  TIM_ICInitStructure;
  TIM_ICInitStructure.TIM_Channel = TIM_Channel_3;
  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
  TIM_ICInitStructure.TIM_ICFilter = 0x0;

  TIM_ICInit(TIM1, &TIM_ICInitStructure);

  /* TIM enable counter */
  TIM_Cmd(TIM1, ENABLE);

  /* Enable the CC3 Interrupt Request */
  TIM_ITConfig(TIM1, TIM_IT_CC3, ENABLE);
}


void TIM1_CC_IRQHandler(void)
{
    // .................
}

int StartCapture()
{ 
  TIM1_Config();

  while(1); /* Infinite loop */
}

person Adrian    schedule 07.01.2015    source источник
comment
У меня нет абсолютно никакого опыта в том, что вы делаете, но в приведенном выше фрагменте ваш обработчик прерывания TIM1_CC_IRQHandler определен и никогда не используется, действительно ли это сделано специально? Вы пропускаете ту часть кода, в которой настраиваете обработчик для этого конкретного прерывания? Или это заранее заявленный символ, который вам просто нужно реализовать?   -  person tux3    schedule 07.01.2015
comment
Эта строка NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn сообщает, что обработчик TIM1_CC_IRQHandler должен вызывать его автоматически.   -  person Adrian    schedule 07.01.2015
comment
Есть ли ГЛОБАЛЬНАЯ маска включения \ отключения прерывания, которую вы не включаете?   -  person Anonymouse    schedule 07.01.2015
comment
NVIC_InitStructure.NVIC_IRQChannelCmd = ВКЛЮЧИТЬ; Это должно разрешить прерывание   -  person Adrian    schedule 07.01.2015
comment
Надеюсь, вы звоните StartCapture() куда-нибудь в свой main()   -  person WedaPashi    schedule 18.04.2015


Ответы (3)


Если ваш TIM1_CC_IRQHandler() получает вызов ОДИН РАЗ, то ответ Dracog71 правильный. Однако, если ваш IRQHandler() никогда не срабатывает, значит, при инициализации что-то не так.

Вот список вещей, которые вы должны сделать правильно, иначе IRQ не сработает.

1) Убедитесь, что часы GPIO[A:E] включены для используемого вывода.

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

3) Дважды проверьте, соответствует ли AF вашего штыря таблице альтернативного отображения функций в таблице данных (например, AF1 == TIM1_CH3).

4) В вашем TIM_ICInitStructure убедитесь, что TIM_Channel соответствует выбранному вами каналу (в вашем случае TIM_Channel_3).

5) Настройте и включите правильный канал IRQ в NVIC, например. NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn;

6) Разрешить прерывание: TIM_ITConfig(TIM1, TIM_IT_CC3, ENABLE);

7) Включите таймер: TIM_Cmd(TIM1, ENABLE);

person Andy J    schedule 08.08.2017

Что ж, думаю, через 6 лет мой ответ не потребуется. Но, возможно, кто-то другой, столкнувшийся с такой же проблемой, найдет его. Если вы пишете на C ++, может возникнуть конфликт имен. Если исходный прототип функции прерывания определен как C-функция, а ваша реализация является функцией C ++, поэтому это всего лишь две разные функции с одинаковым именем, а interupt попытается вызвать пустую C-функцию или даже может складываться в бесконечный цикл . Вот почему ваша функция C ++ может называться более новой. Чтобы решить эту проблему, просто определите свою функцию как extern C.

person Inineor    schedule 27.04.2021

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

  /**
    * @brief  Capture Compare Handler
    * @param  None
    * @retval None
    */
    void TIM1_CC_IRQHandler()
    {
        if (TIM_GetITStatus(TIM1, TIM_IT_CC3) != RESET)  <-- Add this
        {
            TIM_ClearITPendingBit(TIM1, TIM_IT_CC3); <-- This is important!

              //TODO

            }
    }
person Dracog71    schedule 24.01.2017