STM32L0 定时器 TIM22 以不可预测的方式导致中断?
STM32L0 Timer TIM22 cause interrupt in unpredictive way?
每次启用定时器时,它都会立即激活中断。无论我如何尝试对其进行预缩放。只有 ARR 似乎可以工作,但是 16 位和 0.5MHz 时钟给了我 ~160ms 的机动时间。
#define SYSCLK_FREQ 524288
void timer_init(uint16_t detonation_delay_ms);
int main(void){
RCC->APB2ENR = RCC_APB2ENR_TIM22EN;
TIM22->PSC = (SYSCLK_FREQ/1000)-1;
NVIC_EnableIRQ(TIM22_IRQn);
NVIC_SetPriority(TIM22_IRQn,4);
}
/* calling function */
timer_init(65535);
/* calling function */
void timer_init(uint16_t detonation_delay_ms){
TIM22->CR1 &= ~TIM_CR1_CEN;
TIM22->SR=0;
TIM22->ARR = detonation_delay_ms;
TIM22->CR1 |= TIM_CR1_CEN;
TIM22->SR = 0;
}
void TIM22_IRQHandler(void){
TIM22->CR1 &= ~TIM_CR1_CEN;
TIM22->SR=0;
GPIOB->BSRR = GPIO_BSRR_BS_7;
}
我希望调用函数使计时器滴答到以毫秒为单位的调用值。但无论我如何设置它,它最终都没有缩放定时器和调用后的即时中断。
正确的做法?
TIM22->DIER = TIM_DIER_UIE;
TIM22->ARR = 65535-detonation_delay_ms;
TIM22->EGR = TIM_EGR_UG;
TIM22->CR1 |= TIM_CR1_OPM | TIM_CR1_CEN;
TIM22->SR=0;
不要延迟中断
你启用定时器然后设置ARR这是错误的——先设置ARR和预分频器,然后使用EGR寄存器生成UG事件,然后启用定时器。
很有魅力。只是因为我在这里得到了帮助,将描述给以后有兴趣的人。
使计时器中断工作的方法是生成一次中断'by hand'。这样做没问题,因为您可以通过单个 'if' 来控制中断期间发生的事情。
/* TIMER Enable */
RCC->APB2ENR = RCC_APB2ENR_TIM22EN;
我在上面的声明中遇到了问题,不知道为什么,但是在它之前声明了更多模块之后它没有工作。不得不把它放在列表的更高位置。手册没有说明为什么会这样。
/* Configure TIM22 interrupt */
TIM22->PSC = (SYSCLK_FREQ/1000)-1; /* Prescaler TIMERA 22 */
TIM22->DIER = TIM_DIER_UIE;
TIM22->CNT = 0;
TIM22->EGR = TIM_EGR_UG;
NVIC_EnableIRQ(TIM22_IRQn); /* Zalaczenie przerwania od TIMER'a */
NVIC_SetPriority(TIM22_IRQn,4); /* Ustawienie priorytetu przerwania od TIMER'a */
预分频器是1ms所以我把我的核心速度分了524288。然后启用中断,重置计数器以确保它从 0 开始,然后手动产生中断。它会中断 'loop' 一次,但只有一个 'if' 和变量,我可以控制它的作用。
所以我所做的是调用一个函数来设置时钟并在另一个函数 enable = 1 中启用计数; timer_init(毫秒);
然后是函数调用
void timer_init(uint16_t ms)
{
TIM22->CNT = 65535-ms;
TIM22->CR1 |= TIM_CR1_CEN;
}
void TIM22_IRQHandler(void)
/* Up-Counter milisec */
{
if(TIM22->CR1 & TIM_CR1_CEN) {TIM22->CR1 &= ~TIM_CR1_CEN;}
if(TIM22->SR & TIM_SR_UIF) {
if(enable == 1){
GPIOB->BSRR = GPIO_BSRR_BS_7;
}
}
TIM22->SR=0;
}
还有中断。
非常感谢!玩得开心寄存器!
每次启用定时器时,它都会立即激活中断。无论我如何尝试对其进行预缩放。只有 ARR 似乎可以工作,但是 16 位和 0.5MHz 时钟给了我 ~160ms 的机动时间。
#define SYSCLK_FREQ 524288
void timer_init(uint16_t detonation_delay_ms);
int main(void){
RCC->APB2ENR = RCC_APB2ENR_TIM22EN;
TIM22->PSC = (SYSCLK_FREQ/1000)-1;
NVIC_EnableIRQ(TIM22_IRQn);
NVIC_SetPriority(TIM22_IRQn,4);
}
/* calling function */
timer_init(65535);
/* calling function */
void timer_init(uint16_t detonation_delay_ms){
TIM22->CR1 &= ~TIM_CR1_CEN;
TIM22->SR=0;
TIM22->ARR = detonation_delay_ms;
TIM22->CR1 |= TIM_CR1_CEN;
TIM22->SR = 0;
}
void TIM22_IRQHandler(void){
TIM22->CR1 &= ~TIM_CR1_CEN;
TIM22->SR=0;
GPIOB->BSRR = GPIO_BSRR_BS_7;
}
我希望调用函数使计时器滴答到以毫秒为单位的调用值。但无论我如何设置它,它最终都没有缩放定时器和调用后的即时中断。
正确的做法?
TIM22->DIER = TIM_DIER_UIE;
TIM22->ARR = 65535-detonation_delay_ms;
TIM22->EGR = TIM_EGR_UG;
TIM22->CR1 |= TIM_CR1_OPM | TIM_CR1_CEN;
TIM22->SR=0;
不要延迟中断
你启用定时器然后设置ARR这是错误的——先设置ARR和预分频器,然后使用EGR寄存器生成UG事件,然后启用定时器。
很有魅力。只是因为我在这里得到了帮助,将描述给以后有兴趣的人。
使计时器中断工作的方法是生成一次中断'by hand'。这样做没问题,因为您可以通过单个 'if' 来控制中断期间发生的事情。
/* TIMER Enable */
RCC->APB2ENR = RCC_APB2ENR_TIM22EN;
我在上面的声明中遇到了问题,不知道为什么,但是在它之前声明了更多模块之后它没有工作。不得不把它放在列表的更高位置。手册没有说明为什么会这样。
/* Configure TIM22 interrupt */
TIM22->PSC = (SYSCLK_FREQ/1000)-1; /* Prescaler TIMERA 22 */
TIM22->DIER = TIM_DIER_UIE;
TIM22->CNT = 0;
TIM22->EGR = TIM_EGR_UG;
NVIC_EnableIRQ(TIM22_IRQn); /* Zalaczenie przerwania od TIMER'a */
NVIC_SetPriority(TIM22_IRQn,4); /* Ustawienie priorytetu przerwania od TIMER'a */
预分频器是1ms所以我把我的核心速度分了524288。然后启用中断,重置计数器以确保它从 0 开始,然后手动产生中断。它会中断 'loop' 一次,但只有一个 'if' 和变量,我可以控制它的作用。
所以我所做的是调用一个函数来设置时钟并在另一个函数 enable = 1 中启用计数; timer_init(毫秒);
然后是函数调用
void timer_init(uint16_t ms)
{
TIM22->CNT = 65535-ms;
TIM22->CR1 |= TIM_CR1_CEN;
}
void TIM22_IRQHandler(void)
/* Up-Counter milisec */
{
if(TIM22->CR1 & TIM_CR1_CEN) {TIM22->CR1 &= ~TIM_CR1_CEN;}
if(TIM22->SR & TIM_SR_UIF) {
if(enable == 1){
GPIOB->BSRR = GPIO_BSRR_BS_7;
}
}
TIM22->SR=0;
}
还有中断。 非常感谢!玩得开心寄存器!