STM32F4 EXTI прерывания мешают друг другу - PullRequest
0 голосов
/ 14 сентября 2018

Я работаю с микроконтроллером STM32F407VGT6 и у меня возникли проблемы с внешними прерываниями (EXTI).Я настроил два контакта как EXTI, и они PE7 и PE15.Они подключены к датчику Холла привода и обнаруживают края зубьев спускового колеса.Один является первичным источником с несколькими зубьями, а другое колесо - это однозубое колесо, которое подтверждает положение.Дело в том, что они могут работать индивидуально самостоятельно без проблем, но если я соединю их обоих, они начнут мешать друг другу, и я теряю синхронизацию положения, потому что MCU обнаруживает ложные фронты.Я могу воссоздать то же поведение, подключив любой контакт к слабому сигналу, а другой к драйверу HALL.Но если я отключу EXTI и оставлю пин-код в качестве входа, проблема исчезнет.Я понятия не имею, что здесь происходит.

Кроме того, у меня были проблемы с PE15 и EXTI раньше, и это может быть связано с этим.EXTI работал только в режимах EXTI_Trigger_Rising и EXTI_Trigger_Rising_Falling, но EXTI_Trigger_Falling давал обнаружение случайных фронтов, и единственным решением этой проблемы было прослушивание обоих краев и отмена того, который мне не нужен.Я не смог найти ничего об этом в таблице.

Этот STM32F4 вызывает головную боль, и у меня заканчиваются варианты.Ну, последний вариант - перенаправить драйверы зала на другие контакты и использовать входной захват / таймер.

Конфигурация основного колеса:

void Trigger_Configure_Primary(void) {
  // GPIO
  GPIOE->OSPEEDR |= (0x03 << (2 * 15)); // high speed

  // EXTI
  SYSCFG->EXTICR[3] = SYSCFG_EXTICR4_EXTI15_PE; // Tell system that you will use PE15 for EXTI15
  EXTI->RTSR |= (1 << 15); // rising edge
  EXTI->FTSR |= (1 << 15); // falling edge
  EXTI->IMR |= (1 << 15); // Unmask EXTI15 interrupt
  EXTI->PR |= (1 << 15); // Clear pending bit

  /* Add IRQ vector to NVIC */
  NVIC_SetPriority(EXTI15_10_IRQn, 0);
  NVIC_EnableIRQ(EXTI15_10_IRQn);
}

Конфигурация дополнительного колеса:

void Trigger_Configure_Secondary(void) {
  // GPIO
  GPIOE->OSPEEDR |= (0x03 << (2 * 7)); // high speed

  // EXTI
  SYSCFG->EXTICR[1] = SYSCFG_EXTICR2_EXTI7_PE; // Tell system that you will use PE7 for EXTI7
  EXTI->RTSR |= (1 << 7); // rising edge
  EXTI->FTSR |= (1 << 7); // falling edge
  EXTI->IMR |= (1 << 7); // Unmask EXTI7 interrupt
  EXTI->PR |= (1 << 7); // Clear pending bit

  /* Add IRQ vector to NVIC */
  NVIC_SetPriority(EXTI9_5_IRQn, 0);
  NVIC_EnableIRQ(EXTI9_5_IRQn);
}

обработчики IRQ:

void EXTI9_5_IRQHandler(void) {
  __disable_irq();
  /* Make sure that interrupt flag is set */
  if ((EXTI->PR & EXTI_Line7) != 0) {
    // Secondary trigger IRQ
    uint32_t now_nt = GET_TIMESTAMP();

    uint8_t edge = ((GPIOE->IDR & SECONDARY_PIN) == 0 ? 0 : 1);
    TD_Decode_Secondary_Trigger_Event(
      now_nt,
      edge
    );

#ifdef DEBUG
    // Stats
    secondary_ticks = (GET_TIMESTAMP() - now_nt);
#endif

    /* Clear interrupt flag */
    EXTI->PR |= EXTI_Line7;

    ++s_cnt;
  }
  __enable_irq();
}

void EXTI15_10_IRQHandler(void) {
  __disable_irq();
  /* Make sure that interrupt flag is set */
  if ((EXTI->PR & EXTI_Line15) != 0) {
    // Primary trigger IRQ
    uint32_t now_nt = GET_TIMESTAMP();

    uint8_t edge = ((GPIOE->IDR & PRIMARY_PIN) == 0 ? 0 : 1);
    if (primary_edge == edge) {
      TD_Decode_Primary_Trigger(now_nt);
    }

#ifdef DEBUG
    // Stats
    primary_ticks = (GET_TIMESTAMP() - now_nt);
#endif

    /* Clear interrupt flag */
    EXTI->PR |= EXTI_Line15;

    ++p_cnt;
  }
  __enable_irq();
}

1 Ответ

0 голосов
/ 15 сентября 2018

RM0090, 12.3.6 Ожидающий регистр (EXTI_PR):

Этот бит сбрасывается путем программирования его в «1».

Таким образом, этот код

/* Clear interrupt flag */
EXTI->PR |= EXTI_Line7;

Удаляет не только EXTI_Line7, но и все ожидающие прерывания, поскольку он читает EXTI-PR с 1 для все сработавшие прерывания, затем бит ИЛИ EXTI_Line7и пишет все обратно 1.

Использование

/* Clear interrupt flag */
EXTI->PR = EXTI_Line7;
...