STM32: การขัดจังหวะตัวจับเวลาทำงานทันที


10

นี่คือรหัสสำหรับตัวจับเวลาในโครงการของฉันบน 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()ฟังก์ชั่นตรงกลางโปรแกรมของฉันการขัดจังหวะจะเริ่มขึ้นหลังจากนั้นไม่กี่วินาที แต่เกือบจะในทันที ฉันลองใช้ตัวจับเวลาอื่น ๆ เพื่อตรวจสอบว่าไม่มีปัญหาฮาร์ดแวร์หรือไม่ แต่ไม่ใช่


ฉันขอแนะนำให้คุณล้างค่าตัวขัดจังหวะตัวจับเวลาในฟังก์ชั่น timerReset () ของคุณอย่างชัดเจน
brhans

1
หลังจากเพิ่มระหว่าง DeInit และ Init __HAL_TIM_CLEAR_FLAG (& RS485Timer, TIM_FLAG_UPDATE); และ __HAL_TIM_CLEAR_FLAG (& RS485Timer, TIM_IT_UPDATE); ไม่มีอะไรใหม่เกิดขึ้น
m0drzew

คำตอบ:


9

ฉันพบสิ่งนี้กับ STM32F105 ฟังก์ชั่น STM32F1xx Standard Peripheral Library แตกต่างจากที่คุณใช้อยู่เล็กน้อย แต่ความคิดควรจะเหมือนกัน

การออก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);

2
ปัญหาเดียวกันกับ STM32L151 โดยใช้ไลบรารี HAL วิธีแก้ปัญหา (เช่นสำหรับ TIM6):__HAL_TIM_CLEAR_FLAG(&htim6, TIM_SR_UIF);

3
ความคิดเห็นในไดรเวอร์ HAL ใหม่อธิบายถึงสาเหตุ: พวกเขาทำเช่นนี้เพื่อบังคับให้ค่า PSC ถูกอัปเดตเมื่อเริ่มต้นเนื่องจากมีการโหลดจริงลงใน SR-> PSC หลังจากเหตุการณ์อัปเดตเท่านั้น
Galaxy

ดี @Galaxy ขอบคุณสำหรับข้อมูล
bitsmack

1

เนื่องจากฉันมีปัญหาที่คล้ายกันและฉันไม่พบคำตอบฉันแบ่งปันประสบการณ์ของฉันโดยหวังว่าจะช่วยเหลือผู้อื่น

ฉันเชื่อว่าในกรณีของคุณการตั้งค่า URS (Update Request Source) ก่อนที่จะเริ่มต้นตัวจับเวลายังช่วยแก้ปัญหาได้

ในกรณีของฉันฉันใช้ไดรเวอร์เลเยอร์ต่ำดังนั้นรหัสตัวอย่างจะเป็น:

//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)ก่อนที่จะสร้างเหตุการณ์


1

ฉันมีปัญหาที่คล้ายกันใน One Pulse mod และฉันพบวิธีแก้ปัญหาสำหรับห้องสมุด HAL เมื่อฉันควบคุมการตั้งค่าสถานะตัวจับเวลาในฟังก์ชั่น "TIM2_IRQHandler" ฉันเห็น "จับภาพการเปรียบเทียบค่าสถานะ 1" ดังนั้นฉันจึงล้าง "การจับภาพเปรียบเทียบค่าสถานะ 1" แต่ครั้งนี้ฉันเห็นว่า "การจับภาพเปรียบเทียบธง 2" ถูกตั้งค่า ดังนั้นฉันจึงล้างการเปรียบเทียบค่าสถานะทั้งหมด (จาก 1 ถึง 4) ในฟังก์ชัน "TIM2_IRQHandler" ของฉันโดยใช้รหัส 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

ปัญหาเดียวกันกับ 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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.