Почему мой STM32F7 прерывается только каждые 43 секунды?

Моя цель состоит в том, чтобы прерывать 38 кГц и переключать светодиод, но независимо от того, что я установил в качестве прескалера и периода.

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){}

Когда я прошиваю его до цели, светодиод переключается каждые 43 секунды, независимо от того, какой прескалер и период установлены.

Должно быть, я что-то упускаю, но не могу понять. Кто-нибудь с опытом прерывания, который мог бы помочь?


person orsolli    schedule 30.11.2016    source источник
comment
Поскольку это не весь ваш код, нужно спросить, действительно ли вызывается HAL::initTim, и есть ли где-то другой код, перепрограммирующий ваш таймер.   -  person nos    schedule 30.11.2016
comment
Что такое системные часы и исходные часы таймера? (частота)   -  person Bence Kaulics    schedule 30.11.2016
comment
Было бы полезно увидеть немного больше вашего кода, особенно запуск часов, прерывание и таймер.   -  person staringlizard    schedule 01.12.2016


Ответы (2)


Что ж. Таймеры очень просты. Вы только что усложнили задачу, используя куб.

__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);

В ИСР:

if(TIM2->SR & TIM_SR_UIF){
    TIM2->SR &= ~TIM_SR_UIF;
}

Как в сторону. Мне нравится успокаивать условия сброса при инициализации.

__HAL_RCC_TIM2_FORCE_RESET();
__NOP();
__HAL_RCC_TIM2_RELEASE_RESET();
person Jeroen3    schedule 05.12.2016

Другой проект с STM32F469I-DISCOVERY, но я последовал ответу Jeroen3. Я не уверен, где у вас может быть код __HAL_RCC... и __NOP();, но он работал без него. Я рассчитал предварительный делитель и период как некоторые факторы. Например, чтобы получить мигающий светодиод с частотой 1 Гц, я бы использовал prescaler' * period' = timer_clock, который, как я узнал, был core_clock/2.

Таким образом, частота ядра 180 МГц и желаемое прерывание на частоте 1 Гц дадут

(предделитель+1)*(период+1) = 180MHz/2/1Hz = 90M

который можно разделить на 9000 и 10000. Я не уверен насчет прескалера, но период на 16-битном таймере может быть не более 2¹⁶-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();
}

Другое вдохновение: https://github.com/PaxInstruments/STM32CubeF4/blob/master/Projects/STM32469I-Discovery/Examples/TIM/TIM_TimeBase/Src/main.c

person orsolli    schedule 08.01.2017