STM32: Interupsi timer bekerja segera

10

Ini adalah kode untuk timer di proyek saya di 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");
   }
  }
 }

Dan setelah menjalankan timerReset()fungsi di tengah program saya, interupsi dimulai tidak beberapa detik kemudian, tetapi segera. Saya mencoba beberapa timer lain untuk memeriksa apakah tidak ada masalah perangkat keras, tetapi tidak, tidak.

m0drzew
sumber
Saya akan menyarankan Anda secara eksplisit menghapus flag interupsi timer di fungsi timerReset () Anda.
brhans
1
Setelah menambahkan antara DeInit dan Init __HAL_TIM_CLEAR_FLAG (& RS485Timer, TIM_FLAG_UPDATE); dan __HAL_TIM_CLEAR_FLAG (& RS485Timer, TIM_IT_UPDATE); tidak ada yang baru terjadi.
m0drzew

Jawaban:

9

Saya mengalami ini dengan STM32F105. Fungsi Pustaka Periferal Standar STM32F1xx sedikit berbeda dari apa yang Anda gunakan, tetapi idenya harus sama.

Mengeluarkan TIM_TimeBaseInit()fungsi menyebabkan bendera TIM_SR_UIF menjadi diatur. Saya belum kembali untuk mencari tahu mengapa. Setelah bit ini diatur, interupsi akan memicu segera setelah diaktifkan.

Untuk memperbaikinya, setelah menelepon TIM_TimeBaseInit(), saya langsung menelepon TIM_ClearITPendingBit(). Maka saya akan mengaktifkan interupsi dengan TIM_ITConfig(). Ini memperbaiki masalah.

Rutin inisialisasi lengkap saya terlihat seperti ini:

// 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);
bitmack
sumber
2
Masalah yang sama pada STM32L151 menggunakan pustaka HAL. Penanganan masalah (misalnya untuk TIM6):__HAL_TIM_CLEAR_FLAG(&htim6, TIM_SR_UIF);
3
Sebuah komentar pada driver HAL baru menjelaskan alasannya: mereka melakukan ini untuk memaksa nilai PSC diperbarui pada inisialisasi karena hanya benar-benar dimuat ke dalam SR-> PSC setelah acara pembaruan.
Galaxy
Bagus, @Galaxy, terima kasih atas informasinya.
bitsmack
1

Karena saya memiliki masalah yang sama dan saya belum menemukan jawaban, saya membagikan pengalaman saya dengan harapan dapat membantu orang lain.

Saya percaya bahwa dalam kasus Anda, pengaturan URS (Perbarui Permintaan Sumber) sebelum menginisialisasi timer juga memecahkan masalah.

Dalam kasus saya, saya menggunakan driver low-layer, jadi kode contohnya adalah:

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

Masalahnya adalah saya menggunakan LL_TIM_SetPrescaler(TIM16, 7999)dan LL_TIM_SetAutoReload(TIM16, 2999)fungsi - fungsi untuk mengkonfigurasi basis waktu, dan saya menemukan bahwa ketika menggunakan fungsi-fungsi ini, nilai-nilai tidak diperbarui, jadi saya harus membuat acara untuk memperbarui nilai menggunakan LL_TIM_GenerateEvent_UPDATE(TIM16).

Anda kemudian dapat menghapus bendera acara menggunakan LL_TIM_ClearFlag_UPDATE(TIM16)sebelum mengaktifkan interupsi, atau menggunakan LL_TIM_SetUpdateSource(TIM16, LL_TIM_UPDATESOURCE_COUNTER)sebelum membuat acara.

Fabiano
sumber
1

Saya punya masalah serupa di mod One Pulse dan saya menemukan solusi untuk perpustakaan HAL. Ketika saya mengontrol flag timer di fungsi "TIM2_IRQHandler", saya melihat "capture compare flag 1" sudah diset. Jadi saya membersihkan "capture bandingkan flag 1". Tapi kali ini saya melihat "capture bandingkan bendera 2" telah diselesaikan. Jadi saya membersihkan semua flag pembanding (dari 1 hingga 4) dalam fungsi "TIM2_IRQHandler" saya dengan menggunakan kode berikut.

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 */
}
Barış İşbiliroğlu
sumber
0

Masalah yang sama dengan TIM_TimeBaseInit () dan STM32F0xx. String terakhir dari fungsi ini:

  TIMx->EGR = TIM_PSCReloadMode_Immediate;

Ini mengatur acara pembaruan di Event Generation Register. Itu sebabnya saya memberi tanda centang pada IRQ Handler:

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
caponier
sumber