STM32L0 Таймер TIM22 вызывает непредвиденное прерывание? - PullRequest
0 голосов
/ 05 июля 2019

Каждый раз, когда я включаю таймер, он мгновенно активирует прерывание.Неважно, как я пытаюсь его масштабировать.кажется, что работает только ARR, но 16-битный с тактовой частотой 0,5 МГц дает мне маневр ~ 160 мс.

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

Мне бы хотелось, чтобы вызывающая функция делала таймер до заданного значения в milisec.Но независимо от того, как я настроил его, он завершается без масштабированного таймера и мгновенного прерывания после вызова.

Правильный способ сделать это?

    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;

Ответы [ 2 ]

3 голосов
/ 05 июля 2019
  1. Не задерживать прерывания

  2. вы активируете таймер, затем устанавливаете ARR, что неверно - сначала установите ARR и прескалер, затем сгенерируйте событие UG с помощью регистра EGR, затем включите таймер.

0 голосов
/ 09 июля 2019

Работает как шарм. Только потому, что я получил помощь здесь, опишу для будущих заинтересованных людей.

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

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

Прескейлер имел значение 1 мс, поэтому я разделил 524288 моей скорости ядра. Затем включите прерывание, сбросьте счетчик, чтобы убедиться, что он начинается с 0, а затем вручную создайте прерывание. И он делает прерывание «цикл» один раз, но с одним «если» и переменной, я могу контролировать, что он делает.

Итак, что я делаю, я вызываю функцию, которая устанавливает часы и включает счетчик внутри другой функции 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;
}

И прерывание. Большое спасибо! Веселитесь с регистрами!

...