为什么我的STM32F7每43秒才中断一次?
Why does my STM32F7 only interrupt every 43 seconds?
我的目标是中断 38khz 并切换 LED,但无论我设置什么预分频器和周期
static TIM_HandleTypeDef s_TimerInstance = {
.Instance = TIM2,
};
void Hal::initTim()
{
__TIM2_CLK_ENABLE();
s_TimerInstance.Init.Prescaler = 96; // This does nothing
s_TimerInstance.Init.CounterMode = TIM_COUNTERMODE_UP;
s_TimerInstance.Init.Period = 26; // This does nothing
s_TimerInstance.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(&s_TimerInstance);
HAL_TIM_Base_Start_IT(&s_TimerInstance);
HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM2_IRQn);
}
extern "C" void TIM2_IRQHandler()
{
HAL_TIM_IRQHandler(&s_TimerInstance);
}
extern "C" void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
HAL_GPIO_TogglePin(GPIOI, GPIO_PIN_1); // Happens every 43 seconds for some reason
}
extern "C" void HAL_TIMEx_BreakCallback(TIM_HandleTypeDef *htim){}
extern "C" void HAL_TIMEx_CommutationCallback(TIM_HandleTypeDef *htim){}
当我将它对准目标时,无论预分频器和周期设置为什么,LED 每 43 秒切换一次。
我一定是遗漏了什么,但我想不通。任何有中断经验的人都可以提供帮助?
嗯。定时器非常简单。你刚刚通过使用立方体让它变难了。
__TIM2_CLK_ENABLE();
TIM2->PSC = 96; // prescaler (note that 0 is /1)
TIM2->ARR = 0xFFFF-26; // reload on overflow
TIM2->DIER = TIM_DIER_UIE; // overflow isr
TIM2->CR1 |= TIM_CR1_CEN; // enable timer
HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM2_IRQn);
在 isr 中:
if(TIM2->SR & TIM_SR_UIF){
TIM2->SR &= ~TIM_SR_UIF;
}
顺便说一句。我喜欢在初始化时确认重置条件。
__HAL_RCC_TIM2_FORCE_RESET();
__NOP();
__HAL_RCC_TIM2_RELEASE_RESET();
STM32F469I-DISCOVERY 的不同项目,但我遵循了 Jeroen3 的回答。我不确定您在哪里可以获得 __HAL_RCC
... 和 __NOP();
代码,但没有它也能正常工作。我计算了预分频器和周期是一些因素。例如,要获得 1Hz 的闪烁 LED,我将使用预分频器' * period' = timer_clock 我了解到的是 core_clock/2.
所以 180MHz 的 core_clock 和 1Hz 的所需中断将提供
(prescaler+1)*(period+1) = 180MHz/2/1Hz = 90M
它可以分为 9000 和 10000。我不确定预分频器,但 16 位定时器的周期不能超过 2^6-1。这意味着因子不能是 90000 和 1000,因为 90000 大于 2¹⁶-1。也不可能是 900 和 100000。
extern "C"
{
#include "stm32f4xx_hal.h"
#include "stm32f4xx_hal_tim.h"
#include "stm32469i_discovery.h" //Needed for LED
/* User can use this section to tailor TIMx instance used and associated
resources */
/* Definition for TIMx clock resources */
#define TIMx TIM3
#define TIMx_CLK_ENABLE() __HAL_RCC_TIM3_CLK_ENABLE()
/* Definition for TIMx's NVIC */
#define TIMx_IRQn TIM3_IRQn
#define TIMx_IRQHandler TIM3_IRQHandler
void TIM3_IRQHandler()
{
if(TIMx->SR & TIM_SR_UIF){
TIMx->SR &= ~TIM_SR_UIF;
BSP_LED_Toggle(LED2);
}
}
void initTimer()
{
TIMx_CLK_ENABLE();
//SystemCoreClock = 180MHz
//PSC = 180/2/10000-1 = 9000-1
TIMx->PSC = (uint32_t)((SystemCoreClock / 2) / 10000) - 1;// prescaler (note that 0 is /1)
TIMx->ARR = 10000-1; // reload on overflow
TIMx->DIER = TIM_DIER_UIE; // overflow isr
TIMx->CR1 |= TIM_CR1_CEN; // enable timer
HAL_NVIC_SetPriority(TIMx_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIMx_IRQn);
}
}
#include "gui/model/Timer.hpp"
void Timer::init()
{
initTimer();
}
我的目标是中断 38khz 并切换 LED,但无论我设置什么预分频器和周期
static TIM_HandleTypeDef s_TimerInstance = {
.Instance = TIM2,
};
void Hal::initTim()
{
__TIM2_CLK_ENABLE();
s_TimerInstance.Init.Prescaler = 96; // This does nothing
s_TimerInstance.Init.CounterMode = TIM_COUNTERMODE_UP;
s_TimerInstance.Init.Period = 26; // This does nothing
s_TimerInstance.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(&s_TimerInstance);
HAL_TIM_Base_Start_IT(&s_TimerInstance);
HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM2_IRQn);
}
extern "C" void TIM2_IRQHandler()
{
HAL_TIM_IRQHandler(&s_TimerInstance);
}
extern "C" void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
HAL_GPIO_TogglePin(GPIOI, GPIO_PIN_1); // Happens every 43 seconds for some reason
}
extern "C" void HAL_TIMEx_BreakCallback(TIM_HandleTypeDef *htim){}
extern "C" void HAL_TIMEx_CommutationCallback(TIM_HandleTypeDef *htim){}
当我将它对准目标时,无论预分频器和周期设置为什么,LED 每 43 秒切换一次。
我一定是遗漏了什么,但我想不通。任何有中断经验的人都可以提供帮助?
嗯。定时器非常简单。你刚刚通过使用立方体让它变难了。
__TIM2_CLK_ENABLE();
TIM2->PSC = 96; // prescaler (note that 0 is /1)
TIM2->ARR = 0xFFFF-26; // reload on overflow
TIM2->DIER = TIM_DIER_UIE; // overflow isr
TIM2->CR1 |= TIM_CR1_CEN; // enable timer
HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM2_IRQn);
在 isr 中:
if(TIM2->SR & TIM_SR_UIF){
TIM2->SR &= ~TIM_SR_UIF;
}
顺便说一句。我喜欢在初始化时确认重置条件。
__HAL_RCC_TIM2_FORCE_RESET();
__NOP();
__HAL_RCC_TIM2_RELEASE_RESET();
STM32F469I-DISCOVERY 的不同项目,但我遵循了 Jeroen3 的回答。我不确定您在哪里可以获得 __HAL_RCC
... 和 __NOP();
代码,但没有它也能正常工作。我计算了预分频器和周期是一些因素。例如,要获得 1Hz 的闪烁 LED,我将使用预分频器' * period' = timer_clock 我了解到的是 core_clock/2.
所以 180MHz 的 core_clock 和 1Hz 的所需中断将提供
(prescaler+1)*(period+1) = 180MHz/2/1Hz = 90M
它可以分为 9000 和 10000。我不确定预分频器,但 16 位定时器的周期不能超过 2^6-1。这意味着因子不能是 90000 和 1000,因为 90000 大于 2¹⁶-1。也不可能是 900 和 100000。
extern "C"
{
#include "stm32f4xx_hal.h"
#include "stm32f4xx_hal_tim.h"
#include "stm32469i_discovery.h" //Needed for LED
/* User can use this section to tailor TIMx instance used and associated
resources */
/* Definition for TIMx clock resources */
#define TIMx TIM3
#define TIMx_CLK_ENABLE() __HAL_RCC_TIM3_CLK_ENABLE()
/* Definition for TIMx's NVIC */
#define TIMx_IRQn TIM3_IRQn
#define TIMx_IRQHandler TIM3_IRQHandler
void TIM3_IRQHandler()
{
if(TIMx->SR & TIM_SR_UIF){
TIMx->SR &= ~TIM_SR_UIF;
BSP_LED_Toggle(LED2);
}
}
void initTimer()
{
TIMx_CLK_ENABLE();
//SystemCoreClock = 180MHz
//PSC = 180/2/10000-1 = 9000-1
TIMx->PSC = (uint32_t)((SystemCoreClock / 2) / 10000) - 1;// prescaler (note that 0 is /1)
TIMx->ARR = 10000-1; // reload on overflow
TIMx->DIER = TIM_DIER_UIE; // overflow isr
TIMx->CR1 |= TIM_CR1_CEN; // enable timer
HAL_NVIC_SetPriority(TIMx_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIMx_IRQn);
}
}
#include "gui/model/Timer.hpp"
void Timer::init()
{
initTimer();
}