STM32: Ngắt hẹn giờ hoạt động ngay lập tức


10

Đây là mã cho bộ đếm thời gian trong dự án của tôi trên 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");
   }
  }
 }

Và sau khi chạy timerReset()chức năng ở giữa chương trình của tôi, ngắt bắt đầu không vài giây sau, mà gần như ngay lập tức. Tôi đã thử một vài bộ hẹn giờ khác để kiểm tra xem có vấn đề gì về phần cứng không, nhưng không, không phải vậy.


Tôi khuyên bạn nên xóa cờ ngắt hẹn giờ trong hàm timerReset ().
Brhans

1
Sau khi thêm giữa DeInit và init __HAL_TIM_CLEAR_FLAG (& RS485Timer, TIM_FLAG_UPDATE); và __HAL_TIM_CLEAR_FLAG (& RS485Timer, TIM_IT_UPDATE); không có gì mới đang xảy ra
m0drzew

Câu trả lời:


9

Tôi chạy vào đây với một STM32F105. Các chức năng Thư viện ngoại vi tiêu chuẩn STM32F1xx khác một chút so với những gì bạn đang sử dụng, nhưng ý tưởng nên giống nhau.

Việc phát hành TIM_TimeBaseInit()hàm khiến cờ TIM_SR_UIF được thiết lập. Tôi chưa quay lại để tìm hiểu tại sao. Khi bit này được đặt, ngắt sẽ kích hoạt ngay khi được bật.

Để sửa nó, sau khi gọi TIM_TimeBaseInit(), tôi gọi ngay TIM_ClearITPendingBit(). Sau đó, tôi sẽ kích hoạt ngắt với TIM_ITConfig(). Điều này đã khắc phục vấn đề.

Thói quen khởi tạo hoàn chỉnh của tôi trông như thế này:

// 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
Vấn đề tương tự trên STM32L151 khi sử dụng các thư viện HAL. Giải pháp thay thế (ví dụ cho TIM6):__HAL_TIM_CLEAR_FLAG(&htim6, TIM_SR_UIF);

3
Một nhận xét trong trình điều khiển HAL mới giải thích lý do: họ làm điều này để buộc giá trị PSC được cập nhật khi khởi tạo vì nó chỉ thực sự được tải vào SR-> PSC sau một sự kiện cập nhật.
Thiên hà

Rất vui, @Gal Wax, cảm ơn vì thông tin này.
bitsmack

1

Khi tôi gặp vấn đề tương tự và tôi đã không tìm thấy câu trả lời, tôi chia sẻ kinh nghiệm của mình với hy vọng giúp đỡ người khác.

Tôi tin rằng trong trường hợp của bạn, việc đặt URS (Nguồn yêu cầu cập nhật) trước khi khởi tạo bộ hẹn giờ cũng giải quyết được vấn đề.

Trong trường hợp của tôi, tôi đang sử dụng trình điều khiển lớp thấp, vì vậy mã ví dụ sẽ là:

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

Vấn đề là tôi đã sử dụng LL_TIM_SetPrescaler(TIM16, 7999)và các LL_TIM_SetAutoReload(TIM16, 2999)hàm để định cấu hình cơ sở thời gian và tôi phát hiện ra rằng khi sử dụng các hàm này, các giá trị không được cập nhật, vì vậy tôi phải tạo một sự kiện để cập nhật các giá trị sử dụng LL_TIM_GenerateEvent_UPDATE(TIM16).

Sau đó, bạn có thể xóa cờ sự kiện bằng cách sử dụng LL_TIM_ClearFlag_UPDATE(TIM16)trước khi bật ngắt hoặc sử dụng LL_TIM_SetUpdateSource(TIM16, LL_TIM_UPDATESOURCE_COUNTER)trước khi tạo sự kiện.


1

Tôi gặp vấn đề tương tự trong mod One Pulse và tôi đã tìm thấy giải pháp cho thư viện HAL. Khi tôi điều khiển cờ hẹn giờ trong chức năng "TIM2_IRQHandler", tôi thấy "cờ so sánh 1" đã được xử lý. Vì vậy, tôi đã xóa "chụp so sánh cờ 1". Nhưng lần này tôi thấy "chụp so sánh cờ 2" đã được giải quyết. Vì vậy, tôi đã xóa tất cả các cờ so sánh (từ 1 đến 4) trong chức năng "TIM2_IRQHandler" của mình bằng cách sử dụng mã folowing.

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

Vấn đề tương tự với TIM_TimeBaseInit () và STM32F0xx. Chuỗi cuối cùng của chức năng này:

  TIMx->EGR = TIM_PSCReloadMode_Immediate;

Nó đặt sự kiện cập nhật tại Đăng ký tạo sự kiện. Đó là lý do tại sao tôi đặt kiểm tra cho 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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.