มีความเป็นไปได้ไหม ที่จะ interrupt_timer แบบว่า ไม่ต้อง overflow/underflw [STM8]

  • 1 Replies
  • 450 Views
*

Offline TaoTao

  • ***
  • 233
    • View Profile
หากว่า ต้องการ interrupt() เมื่อ cnter ถึงระดับที่ตั้งไว้
แต่ หากช่วงการนับ มันไม่เท่ากัน.. ปัญหาคือ ต้องมาคำนวณ
และโหลดค่าใส่ใน ARR ใหม่ทุกครั้ง

ไม่รู้จะเป็นไปได้ไหม ประมาณว่า ให้มันเข้า loop interrupt
เมื่อ cnter = 0x1DCA, 0x210F.. หรืออะไรก็ได้
แบบว่า นับต่อไปเรื่อยๆ โดยไม่ต้องมาคอย reload ARR
เพราะการ reload ARR และ reset val cnter แต่ละที ใช้หลาย clock เลย

ปัจจุบัน ใช้การแก้ Reload bit : ARR และรอ OVF อยู่ครับ
เพราะมันจะเคลียร์ค่า cnter ทุกครั้ง(อันนี้ อัตโนมัต) ไม่ได้นับต่อยอดไปเรื่อยๆ

อ่าน Ref Manual มาหลายรอบละ ยังมึนอยู่เลย
หาไม่เจอ หรือ เธอไม่มี @_@!

*

Offline dec

  • **
  • 67
    • View Profile
ผมก็ไม่เคยใช้ STM8 มาก่อน แต่เท่าที่รู้ Timer interrupt มันจะมี Capture Compare Channel
ให้ใช้เหมือนกับ STM32 ครับ ต้องดูใน Datasheet ว่า Timer ตัวไหนมี Capture Compare Channel ให้ใช้บ้าง
มันจะเขียนอยู่ในตาราง TIM timer feature ใน Column CAPCOM channel ครับ


ปกติ CAPCOM channel จะใช้ทำ PWM แต่มันสามารถ Interrupt ได้ด้วยครับ โดย Config CAPCOM channel
ให้ทำงานเป็น Output Comparator แล้วก็ Set ค่า CCR ให้แต่ละ Channel พอ Timer มัน Count มาถึงค่า CCR
ของ Channel ไหนมันก็จะเด้งเข้า Interrupt ครับ

ผมไม่รู้ว่าตอนนี้ STM8 เค้าใช้ Library อันไหนกันนะครับ อันนี้ผมก็อปมาจากตัวอย่าง TIM2_OC_InactiveMode
ใน STM8S/A Standard peripheral library
https://www.st.com/en/embedded-software/stsw-stm8069.html

Code ส่วน Init
Code: [Select]
#define CCR1_Val ((uint16_t)976)
#define CCR2_Val ((uint16_t)488)
#define CCR3_Val  ((uint16_t)244)

/**
  * @brief  Configure Output Compare Active Mode for TIM2 Channel1, Channel2 and
  *         channel3 
  * @param  None
  * @retval None
  */
static void TIM2_Config(void)
{
  /* Time base configuration */
  TIM2_TimeBaseInit(TIM2_PRESCALER_2048, 65535);

  /* Prescaler configuration */
  TIM2_PrescalerConfig(TIM2_PRESCALER_2048, TIM2_PSCRELOADMODE_IMMEDIATE);

  /* Output Compare Active Mode configuration: Channel1 */
  /*
  TIM2_OCMode = TIM2_OCMODE_INACTIVE
       TIM2_OCPolarity = TIM2_OCPOLARITY_HIGH
       TIM2_Pulse = CCR1_Val
*/
  TIM2_OC1Init(TIM2_OCMODE_INACTIVE, TIM2_OUTPUTSTATE_ENABLE,CCR1_Val, TIM2_OCPOLARITY_HIGH);
  TIM2_OC1PreloadConfig(DISABLE);

  /* Output Compare Active Mode configuration: Channel2 */
 
  /*TIM2_Pulse = CCR2_Val;  */
  TIM2_OC2Init(TIM2_OCMODE_INACTIVE, TIM2_OUTPUTSTATE_ENABLE,CCR2_Val, TIM2_OCPOLARITY_HIGH);
  TIM2_OC2PreloadConfig(DISABLE);

  /* Output Compare Active Mode configuration: Channel3 */
  /*TIM2_Pulse = CCR3_Val  */
  TIM2_OC3Init(TIM2_OCMODE_INACTIVE, TIM2_OUTPUTSTATE_ENABLE,CCR3_Val, TIM2_OCPOLARITY_HIGH);
  TIM2_OC3PreloadConfig(DISABLE);

  TIM2_ARRPreloadConfig(ENABLE);
 
  /* TIM IT enable */
  TIM2_ITConfig(TIM2_IT_CC1, ENABLE);
  TIM2_ITConfig(TIM2_IT_CC2, ENABLE);
  TIM2_ITConfig(TIM2_IT_CC3, ENABLE);
 
  /* TIM2 enable counter */
  TIM2_Cmd(ENABLE);
}

Code ใน Interrupt
Code: [Select]
/**
  * @brief  Timer2 Capture/Compare Interrupt routine
  * @param  None
  * @retval None
  */
 INTERRUPT_HANDLER(TIM2_CAP_COM_IRQHandler, 14)
{
  if (TIM2_GetITStatus(TIM2_IT_CC1) != RESET)
  {
    /* Clear TIM2 Capture Compare1 interrupt pending bit*/
    TIM2_ClearITPendingBit(TIM2_IT_CC1);

    /* PG.5 toggles after 1000 ms */
    GPIO_WriteLow(GPIOG, GPIO_PIN_5);

  }
 
if (TIM2_GetITStatus(TIM2_IT_CC2) != RESET)
  {
    /* Clear TIM2 Capture Compare2 interrupt pending bit*/
    TIM2_ClearITPendingBit(TIM2_IT_CC2);
 
    /* PG.6 toggles after 500 ms */
    GPIO_WriteLow(GPIOG, GPIO_PIN_6);
  }
 
if (TIM2_GetITStatus(TIM2_IT_CC3) != RESET)
  {
    /* Clear TIM2 Capture Compare3 interrupt pending bit*/
    TIM2_ClearITPendingBit(TIM2_IT_CC3);
   
    /* PG.7 toggles after 250 ms */
    GPIO_WriteLow(GPIOG, GPIO_PIN_7);
  }
}