Это код таймера в моем проекте на STM32F429:
//timer initialization
void timerInit()
{
uwPrescalerValue2 = (uint32_t) ((SystemCoreClock / 2) / 100000) - 1;
RS485Timer.Instance = TIM5;
RS485Timer.Init.Period = 67400000; // high value to notice interrupt even without debugging
RS485Timer.Init.Prescaler = 400000;
RS485Timer.Init.ClockDivision = 0;
RS485Timer.Init.CounterMode = TIM_COUNTERMODE_UP;
HAL_TIM_Base_Init(&RS485Timer);
}
void timerReset()
{
HAL_TIM_Base_Stop_IT(&RS485Timer);
HAL_TIM_Base_DeInit(&RS485Timer);
HAL_TIM_Base_Init(&RS485Timer);
HAL_TIM_Base_Start_IT(&RS485Timer);
printf("%d timer reset\n", countereset);
countereset++;
}
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
/*##-1- Enable peripherals and GPIO Clocks #################################*/
/* TIMx Peripheral clock enable */
__TIM5_CLK_ENABLE();
/*##-2- Configure the NVIC for TIMx #########################################*/
/* Set the TIMx priority */
HAL_NVIC_SetPriority(TIM5_IRQn, 7, 1);
/* Enable the TIMx global Interrupt */
HAL_NVIC_EnableIRQ(TIM5_IRQn);
}
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *htim)
{
__TIM5_FORCE_RESET();
__TIM5_RELEASE_RESET();
HAL_NVIC_DisableIRQ(TIM5_IRQn);
}
void TIM5_IRQHandler(void)
{
if (__HAL_TIM_GET_FLAG(&RS485Timer, TIM_FLAG_UPDATE) != RESET) //In case other interrupts are also running
{
if (__HAL_TIM_GET_ITSTATUS(&RS485Timer, TIM_IT_UPDATE) != RESET)
{
__HAL_TIM_CLEAR_FLAG(&RS485Timer, TIM_FLAG_UPDATE);
HAL_TIM_IRQHandler(&RS485Timer);
printf("timer interrupt\n");
}
}
}
И после запуска timerReset()
функции в середине моей программы прерывание начинается не через несколько секунд, а почти сразу. Я попробовал несколько других таймеров, чтобы проверить, нет ли проблем с оборудованием, но нет, это не так.
Я столкнулся с этим с STM32F105. Функции стандартной периферийной библиотеки STM32F1xx немного отличаются от того, что вы используете, но идея должна быть той же.
Выдача TIM_TimeBaseInit()
функции привела к установке флага TIM_SR_UIF. Я еще не вернулся, чтобы понять, почему. Как только этот бит установлен, прерывание сработает, как только оно будет разрешено.
Чтобы это исправить, после звонка TIM_TimeBaseInit()
я сразу позвонил TIM_ClearITPendingBit()
. Затем я бы включил прерывание с помощью TIM_ITConfig()
. Это решило проблему.
Моя полная процедура инициализации выглядит так:
// Enable the peripheral clock
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
// Configure the timebase
TIM_TimeBaseInitStructure.TIM_Prescaler = 1;
TIM_TimeBaseInitStructure.TIM_Period = 35999;
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseInitStructure);
// That last function caused the UIF flag to get set. Clear it.
TIM_ClearITPendingBit(TIM5, TIM_IT_Update);
// Configure so that the interrupt flag is only set upon overflow
TIM_UpdateRequestConfig(TIM5, TIM_UpdateSource_Regular);
// Enable the TIM5 Update Interrupt type
TIM_ITConfig(TIM5, TIM_IT_Update, ENABLE);
__HAL_TIM_CLEAR_FLAG(&htim6, TIM_SR_UIF);
Поскольку у меня была аналогичная проблема, и я не нашел ответов, я делюсь своим опытом в надежде помочь другим людям.
Я считаю, что в вашем случае установка URS (Источник запроса на обновление) перед инициализацией таймера также решает проблему.
В моем случае я использую низкоуровневые драйверы, поэтому пример кода будет таким:
//Enables APB1 TIM16 peripheral clock
LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_TIM16);
//Sets update event source to counter overflows only
LL_TIM_SetUpdateSource(TIM16, LL_TIM_UPDATESOURCE_COUNTER);
//Configures the TIM16 time base
LL_TIM_InitTypeDef TIM_InitStruct;
TIM_InitStruct.Prescaler = 7999;
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
TIM_InitStruct.Autoreload = 2999;
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
TIM_InitStruct.RepetitionCounter = 0;
LL_TIM_Init(TIM16, &TIM_InitStruct);
//Enables update interrupt
LL_TIM_EnableIT_UPDATE(TIM16);
//Enables timer counter
LL_TIM_EnableCounter(TIM16);
//Enables Interrupt
NVIC_EnableIRQ(TIM16_IRQn);
Проблема в том, что я использовал функции LL_TIM_SetPrescaler(TIM16, 7999)
и LL_TIM_SetAutoReload(TIM16, 2999)
для настройки базы времени и обнаружил, что при использовании этих функций значения не обновлялись, поэтому мне пришлось сгенерировать событие для обновления значений с помощью LL_TIM_GenerateEvent_UPDATE(TIM16)
.
Затем вы можете либо очистить флаг события с помощью LL_TIM_ClearFlag_UPDATE(TIM16)
перед включением прерывания, либо использовать LL_TIM_SetUpdateSource(TIM16, LL_TIM_UPDATESOURCE_COUNTER)
перед генерацией события.
На основе решения отprogramrsought.com
Сбрасывать TIM_SR_UIF
флаг перед каждым HAL_TIM_Base_Start_IT()
вызовом
#define FIX_TIMER_TRIGGER(handle_ptr) (__HAL_TIM_CLEAR_FLAG(handle_ptr, TIM_SR_UIF))
...
void myfunc(){
FIX_TIMER_TRIGGER(&htim7);
HAL_TIM_Base_Start_IT(&htim7);
}
Протестировано на плате STM32F407 Discovery.
При отладке помните, что по умолчанию периферийные устройства не останавливаются при остановке ядра, поэтому таймеры будут продолжать запускать прерывание, пока вы остановлены. У меня также была приятная головная боль некоторое время назад, пока я не обнаружил биты для зависания периферийных устройств в режиме отладки.
Вы можете включить его при запуске main следующим образом:
void main(void){
__HAL_DBGMCU_FREEZE_TIM1(); // Enable Timer1 Freeze on Debug
HAL_Init();
// blah
// blah rest of the main code
// blah
}
У вас есть все определения в начале stm32f4xx_hal.h.
У меня была похожая проблема в моде One Pulse, и я нашел решение для библиотеки HAL. Когда я управлял флагами таймера в функции «TIM2_IRQHandler», я видел, что установлен «флаг сравнения захвата 1». Поэтому я очистил «флаг сравнения захвата 1». Но на этот раз я увидел, что установлен «флаг сравнения захвата 2». Поэтому я очистил все флаги сравнения (от 1 до 4) в моей функции «TIM2_IRQHandler», используя следующие коды.
void TIM2_IRQHandler(void)
{
/* USER CODE BEGIN TIM2_IRQn 0 */
/* USER CODE END TIM2_IRQn 0 */
HAL_TIM_IRQHandler(&htim2);
/* USER CODE BEGIN TIM2_IRQn 1 */
if(__HAL_TIM_GET_FLAG(&htim2, TIM_FLAG_CC1) != RESET)
{
timer2Proccess();
__HAL_TIM_CLEAR_FLAG(&htim2,TIM_FLAG_CC1 );
__HAL_TIM_CLEAR_FLAG(&htim2,TIM_FLAG_CC2 );
__HAL_TIM_CLEAR_FLAG(&htim2,TIM_FLAG_CC3 );
__HAL_TIM_CLEAR_FLAG(&htim2,TIM_FLAG_CC4 );
}
/* USER CODE END TIM2_IRQn 1 */
}
Та же проблема с TIM_TimeBaseInit() и STM32F0xx. Последняя строка этой функции:
TIMx->EGR = TIM_PSCReloadMode_Immediate;
Он устанавливает событие обновления в регистре генерации событий. Вот почему я поставил галочку на обработчик IRQ:
void TIM1_IRQHandler() {
if(TIM_GetFlagStatus(TIM1, TIM_FLAG_Update) == SET) {
TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
if((TIM1 -> CR1 & TIM_CR1_CEN) == 0) return; //Timer is not working
//Interrupt code
брахи
m0drzew