STM32: Zamanlayıcı kesmesi hemen çalışıyor


10

Bu STM32F429 benim projesinde zamanlayıcı için kod:

//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");
   }
  }
 }

Ve timerReset()programımın ortasında işlevi çalıştırdıktan sonra , kesinti birkaç saniye sonra değil, neredeyse hemen başlar. Donanım sorunu olup olmadığını kontrol etmek için birkaç zamanlayıcı denedim, ama hayır, değil.


TimerReset () işlevinizdeki timer interrupt bayrağını açıkça temizlemenizi öneririm.
brhans

1
DeInit ve Init __HAL_TIM_CLEAR_FLAG (& RS485Timer, TIM_FLAG_UPDATE) arasında ekledikten sonra; ve __HAL_TIM_CLEAR_FLAG (& RS485Timer, TIM_IT_UPDATE); yeni bir şey olmuyor.
m0drzew

Yanıtlar:


9

Bir STM32F105 ile karşılaştım. STM32F1xx Standart Çevre Birimi Kitaplığı işlevleri kullandığınızdan biraz farklıdır, ancak fikir aynı olmalıdır.

Düzenleyen TIM_TimeBaseInit()işlevini TIM_SR_UIF bayrak seti olmasına neden oldu. Nedenini bulmak için henüz geri dönmedim. Bu bit bir kez ayarlandığında, kesme etkinleştirilir etkinleştirilmez.

Düzeltmek için, aradıktan sonra TIM_TimeBaseInit()hemen aradım TIM_ClearITPendingBit(). Sonra kesmeyi etkinleştiririm TIM_ITConfig(). Bu sorunu çözdü.

Tam başlatma rutinim şöyle:

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

2
HAL kütüphanelerini kullanarak STM32L151'de aynı sorun. Geçici çözüm (örneğin, TIM6 için):__HAL_TIM_CLEAR_FLAG(&htim6, TIM_SR_UIF);

3
Yeni HAL sürücüsünde yapılan bir açıklama nedenini açıklar: bunu, bir güncelleme olayından sonra yalnızca SR-> PSC'ye yüklendiği için PSC değerini başlangıçta güncellenmeye zorlamak için yaparlar.
Galaxy

Güzel, @Galaxy, bilgi için teşekkürler.
bitsmack

1

Benzer bir sorunum olduğu ve cevap bulamadığım için diğer insanlara yardım etme umuduyla deneyimimi paylaşıyorum.

Sizin durumunuzda, zamanlayıcıyı başlatmadan önce URS'yi (Güncelleme İsteği Kaynağı) ayarlamanın da sorunu çözdüğüne inanıyorum.

Benim durumumda, düşük katmanlı sürücüleri kullanıyorum, bu yüzden örnek bir kod olurdu:

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

Sorun, zaman tabanını yapılandırmak için LL_TIM_SetPrescaler(TIM16, 7999)ve LL_TIM_SetAutoReload(TIM16, 2999)işlevlerini kullanıyordum ve bu işlevleri kullanırken değerlerin güncellenmediğini keşfettim, bu nedenle değerleri güncellemek için bir olay oluşturmak zorunda kaldım LL_TIM_GenerateEvent_UPDATE(TIM16).

Daha sonra LL_TIM_ClearFlag_UPDATE(TIM16)kesmeyi etkinleştirmeden önce kullanarak olay bayrağını temizleyebilir veya LL_TIM_SetUpdateSource(TIM16, LL_TIM_UPDATESOURCE_COUNTER)olayı oluşturmadan önce kullanabilirsiniz .


1

One Pulse modunda benzer bir sorun yaşadım ve HAL kütüphanesi için çözüm buldum. "TIM2_IRQHandler" fonksiyonunda zamanlayıcı bayraklarını kontrol ettiğimde, "yakalama karşılaştırması bayrak 1'i yakala" ayarlandığını gördüm. Ben "karşılaştırma bayrak 1 yakalama" temizledi. Ama bu sefer gördüm "yakalama karşılaştırma bayrağı 2" ayarlandı. Bu yüzden "TIM2_IRQHandler" fonksiyonumdaki tüm karşılaştırma bayraklarını (1'den 4'e) temizleyen kodları kullanarak temizledim.

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

0

TIM_TimeBaseInit () ve STM32F0xx ile aynı sorun. Bu işlevin son dizesi:

  TIMx->EGR = TIM_PSCReloadMode_Immediate;

Event Generation Register'da update olayını ayarlar. Bu yüzden IRQ Handler'a kontrol koydum:

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.