1. 程式人生 > >stm32定時器之Output Compare

stm32定時器之Output Compare

stm32f103vb發出邏輯訊號給MOC3020,控制BTA16可控矽的通斷。

在檢測到過零訊號時,延時x毫秒,輸出1;延時y毫秒,關閉輸出。 實現相位控制調速感應電機(小功率)。


在stm32 discovery開發板上,使用藍燈和綠燈模擬。

採用定時器的OC,比較輸出來做。

選用VBT6的一個Timer來做,它有4個通道可以使用,可以拿來控制4路可控矽輸出。

使用CubeMX做外設配置。

針腳配置:


這樣不把輸出直接傳送到Pin上。 能直接傳送到Pin上,使用One Pulse Mode 比較方便。 受限於委託公司的設計限制,沒法使用脈衝模式。


注意Prescaler的值, 值  = 時鐘頻率/1000 - 1, 及為1ms.

Pulse 值,表示計數器到達多少時,做輸出,觸發中斷。


中斷需要啟用。

使用按鍵來觸發定時器,啟用兩個通道,這裡簡單使用延時來按鍵消抖,可以使用狀態機處理:

    if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET) {
      
      HAL_Delay(20);
      if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET) {
        // strat timer
        __HAL_TIM_SET_COUNTER ( &htim2, 0); // 設定0
        HAL_TIM_OC_Start_IT  ( &htim2,  TIM_CHANNEL_1); 
        HAL_TIM_OC_Start_IT  ( &htim2,  TIM_CHANNEL_2); 

      }
    }

定義兩個flag:
__IO uint8_t on_led_blue = 0;
__IO uint8_t on_led_green = 0;

在回撥函式處理:
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
  
  if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
  {
    if (!on_led_blue) {
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
      on_led_blue = 1;
      HAL_TIM_OC_Stop_IT  ( &htim2, TIM_CHANNEL_1);
      //設定新的時間
      uint16_t delay_new = __HAL_TIM_GET_COMPARE(&htim2, TIM_CHANNEL_1);
      __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, delay_new + 1999);
      HAL_TIM_OC_Start_IT  ( &htim2, TIM_CHANNEL_1);
    }
    else if (on_led_blue) {
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
      on_led_blue = 0;
      HAL_TIM_OC_Stop_IT  ( &htim2, TIM_CHANNEL_1); 
    }
    
 
  } 

  
    if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
    {
      if (!on_led_green) {
        HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);#define __HAL_TIM_SET_COMPARE (   __HANDLE__,  
    __CHANNEL__,  
    __COMPARE__  
 ) 
        on_led_green = 1;
        HAL_TIM_OC_Stop_IT  ( &htim2, TIM_CHANNEL_2);
        //設定新的時間
        uint16_t delay_new = __HAL_TIM_GET_COUNTER(&htim2, TIM_CHANNEL_2);
        __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, delay_new + 1999);
        HAL_TIM_OC_Start_IT  ( &htim2, TIM_CHANNEL_2);
      }
      else if (on_led_green) {
        HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);
        on_led_green = 0;
        HAL_TIM_OC_Stop_IT  ( &htim2, TIM_CHANNEL_2); 
      }
    }
  
}

使用flag來區別HAL_TIM_ActiveChannel是 delay_on,還是delay_off。

#define __HAL_TIM_SET_COMPARE (   __HANDLE__,  
    __CHANNEL__,  
    __COMPARE__  
 ) 

這個巨集可以方便的 Sets the TIM Capture Compare Register value on runtime without calling another time ConfigChannel function.

效果表現為:

按鍵按下,藍燈3秒亮,2秒後滅;綠燈5秒後亮,2秒後滅。

總之,使用Timer的輸出Pin接Moc3020,脈衝方式是最省事省心的做法。 

而其他Pin的話,只能這裡使用一個替代的方法來實現。