簡體   English   中英

TIM2溢出不觸發TIM2_IRQHandler@STM32G031J6

[英]TIM2 overflow does not trigger TIM2_IRQHandler @ STM32G031J6

使用以下代碼,我想讓 STM32G031J6M6 的引腳 5 (PA11) 以 50 kHz 的頻率閃爍。 為此,我將 TIM2 配置為每 10 us 溢出一次。 這是為了調用一個 ISR(“TIM2_IRGHandler”)來切換 PA11 的電平。 現在一切正常:切換正常,TIM2 計數到 10,重置並再次開始計數。 現在的問題是,當 TIM2 溢出時,我的 ISR 沒有被調用。 相反,程序只是“崩潰”了 我猜它會在 TIM2 溢出時進入一些“默認處理程序”。

(代碼被編譯為 C 代碼而不是C++。)

#include <stdlib.h>

#include <stm32g031xx.h>

/*!
 * \brief Configures pin 5 ("PA11") as digital output.
 */
void config_output(void) {
  RCC->IOPENR |= RCC_IOPENR_GPIOAEN;
  GPIOA->MODER &= ~(0x3u << (11 * 2));
  GPIOA->MODER |= (0x1u << (11 * 2));
  GPIOA->OTYPER &= ~(0x1u << (11 * 1));
}

/*!
 * \brief Configures TIM2 overflow with 10 us period (-> 100 kHz).
 */
void config_blink_timer(void) {
  //Enable the TIM2 clock.
  RCC->APBENR1 |= RCC_APBENR1_TIM2EN;

  //Make sure the timer's "counter" is off.
  TIM2->CR1 &= ~TIM_CR1_CEN;

  //Reset the peripheral.
  RCC->APBRSTR1 |= (RCC_APBRSTR1_TIM2RST);
  RCC->APBRSTR1 &= ~(RCC_APBRSTR1_TIM2RST);

  //Set the timer prescaler/autoreload timing registers.
  TIM2->PSC = 16 - 1; //-> 16 MHz / 16 = 1 MHz
  TIM2->ARR = 10 - 1; //-> 1/1 MHz * 10 = 10 us (100 kHz)

  //Send an update event to reset the timer and apply settings.
  TIM2->EGR |= TIM_EGR_UG;

  //Enable TIM2 interrupts.
  NVIC_EnableIRQ(TIM2_IRQn);
}

/*!
 * \brief Enables the "Cycle Timer", which will now fire interrupts that trigger
 * execution of the "App Loop" (--> \c TIM2_IRQHandler()).
 */
void run_app(void) {
  //Clear TIM2_IRQn update interrupt,
  TIM2->SR &= ~TIM_SR_UIF;

  //Enable the hardware interrupt.
  TIM2->DIER |= TIM_DIER_UIE;

  //Enable the timer.
  TIM2->CR1 |= TIM_CR1_CEN;
}

/*!
 * \brief Initializes any peripheral being used.
 */
void init(void) {
  //Disable interrupts.
  __disable_irq();

  config_output();
  config_blink_timer();

  //Enable interrupts.
  __enable_irq();
}

/*!
 * \brief Initializes the system and runs the application.
 */
int main(void) {
  init();

  run_app();

  while(1)
    __WFI();

  return EXIT_SUCCESS;
}

/*!
 * \brief This IRQ handler will be triggered every 10 us by the "Blink Timer".
 * This "time base" is used to blink a LED with a defined pattern (50 kHz,
 * 50% DS).
 */
void TIM2_IRQHandler(void) {
  //Toggle PA11 (pin 5).
  GPIOA->ODR ^= (0x1u << 11);

  //Clear TIM2 update interrupt flag.
  TIM2->SR &= ~TIM_SR_UIF;

  //Power-down until next "tick"/interrupt.
  __WFE();
}

好的,這個(德語)論壇(-> 線程鏈接)中的人讓我走上了正確的軌道,並最終回答了這個問題:我們可以通過將 TIM2_IRQn 的優先級明確設置為“0”來解決問題。 然而,與其治療症狀,不如解決原因,在這種情況下,它實際上只能是 SysTick。 但是,我不能再用原代碼重現這個問題了……如果有人知道這個奇怪現象的答案,當然歡迎他。

但現在基本上問題已經為我解決了。 以下代碼工作正常:

#include <stdlib.h>

#include <stm32g031xx.h>

/*!
 * \brief Configures pin 5 ("PA11") as digital output.
 */
void config_output(void) {
  RCC->IOPENR |= RCC_IOPENR_GPIOAEN;
  GPIOA->MODER &= ~(0x3u << (11 * 2));
  GPIOA->MODER |= (0x1u << (11 * 2));
  GPIOA->OTYPER &= ~(0x1u << (11 * 1));
}

/*!
 * \brief Configures TIM2 overflow with 10 us period (-> 100 kHz).
 */
void config_blink_timer(void) {
  //Enable the TIM2 clock.
  RCC->APBENR1 |= RCC_APBENR1_TIM2EN;

  //Make sure the timer's "counter" is off.
  TIM2->CR1 &= ~TIM_CR1_CEN;

  //Reset the peripheral.
  RCC->APBRSTR1 |= (RCC_APBRSTR1_TIM2RST);
  RCC->APBRSTR1 &= ~(RCC_APBRSTR1_TIM2RST);

  //Set the timer prescaler/autoreload timing registers.
  TIM2->PSC = 16 - 1; //-> 16 MHz / 16 = 1 MHz
  TIM2->ARR = 10 - 1; //-> 1/1 MHz * 10 = 10 us (100 kHz)

  //Send an update event to reset the timer and apply settings.
  TIM2->EGR |= TIM_EGR_UG;

  //Enable TIM2 interrupts and set priority.
  NVIC_EnableIRQ(TIM2_IRQn);
  NVIC_SetPriority(TIM2_IRQn, 0);
}

/*!
 * \brief Enables the "Cycle Timer", which will now fire interrupts that trigger
 * execution of the "App Loop" (--> \c TIM2_IRQHandler()).
 */
void start_app(void) {
  //Clear TIM2_IRQn update interrupt,
  TIM2->SR &= ~TIM_SR_UIF;

  //Enable the hardware interrupt.
  TIM2->DIER |= TIM_DIER_UIE;

  //Enable the timer.
  TIM2->CR1 |= TIM_CR1_CEN;
}

/*!
 * \brief Initializes any peripheral being used.
 */
void init(void) {
  //Disable interrupts.
  __disable_irq();

  config_output();
  config_blink_timer();

  //Enable interrupts.
  __enable_irq();
}

/*!
 * \brief Initializes the system and runs the application.
 */
int main(void) {
  init();

  start_app();

  while(1)
    __WFI();

  return EXIT_SUCCESS;
}

/*!
 * \brief This IRQ handler will be triggered every 10 us by the "Blink Timer".
 * This "time base" is used to blink a LED with a defined pattern (50 kHz,
 * 50% DS).
 */
void TIM2_IRQHandler(void) {
  //Clear TIM2 update interrupt flag.
  TIM2->SR &= ~TIM_SR_UIF;

  //Toggle PA11 (pin 5).
  GPIOA->ODR ^= (0x1u << 11);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM