简体   繁体   English

STM32L0定时器TIM22是否以意外方式导致中断?

[英]STM32L0 Timer TIM22 cause interrupt in unpredictive way?

Every time I enable the timer it instantly activates the Interrupt. 每当我启用计时器时,它都会立即激活中断。 No matter how I try to prescale it. 无论我如何尝试对其进行预缩放。 only ARR seems to work but 16 bit with 0,5MHz clock gives me ~160ms maneuver. 只有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;
}

I wish that calling function makes the timer tick till the called value in milisec. 我希望调用函数可以使计时器计时直到毫秒内被调用的值。 But no matter how I set it up it ends up with no scaled timer and instant interrupt after calling it. 但是无论我如何设置,它最终都没有定标计时器,并且在调用它后不会立即中断。

Correct way to do it? 正确的方法吗?

    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;
  1. Do not delay in interrupts 不要延迟中断

  2. you enable the timer then set the ARR which is wrong - first set ARR and prescaller, then generate the UG event using the EGR register, then enable the timer. 您启用计时器,然后设置错误的ARR-首先设置ARR和预分频器,然后使用EGR寄存器生成UG事件,然后启用计时器。

Works like a charm. 奇迹般有效。 Just because I got help here will describe for future interested people. 仅仅因为我在这里得到了帮助,才会为将来的关注者提供帮助。

The way to get the interrupt working for the timers is to generate interrupt 'by hand' once. 使中断工作于定时器的方法是“手动”生成一次中断。 It's okay to do it because you can control what's happening during the interrupt by a single 'if'. 这样做是可行的,因为您可以通过单个“ if”控制中断期间发生的事情。

    /* TIMER Enable */
    RCC->APB2ENR = RCC_APB2ENR_TIM22EN;

I had a problem with the above declaration, dunno why but it wasn't working after declaring some more modules before it. 我对上面的声明有疑问,不知道为什么,但是在声明了更多模块之后它不起作用。 Had to put it on higher on the list. 不得不把它放在更高的位置。 Manual does not say why it happened. 手册没有说为什么会发生。

    /* 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 */

The prescaler meant to be 1ms so I divided 524288 of my core speed. 预分频比是1ms,所以我将524288的核心速度除了。 Then enabling the interrupt, resetting the counter to make sure it starts from 0 and then manually generating the interrupt. 然后启用中断,将计数器复位以确保其从0开始,然后手动生成中断。 And it does the interrupt 'loop' once but with a single 'if' and variable, I can control what it does. 而且它只执行一次中断“循环”,但是只有一个“ if”和变量,我可以控制它的作用。

So what I do, I am calling a function that set the clock and enables the count inside another function enable = 1; 所以我要做的就是调用一个设置时钟并在另一个函数中启用计数的函数enable = 1; timer_init(ms); timer_init(MS);

Then comes the function call 然后是函数调用

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;
}

And the interrupt. 和中断。 Thanks a lot!Have fun with registers! 非常感谢您与寄存器玩得开心!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM