---
# System prepended metadata

title: STM的高級timer和pwm輸出
tags: [STM32]

---

[TOC]

# 高級定時器

## 簡介
- 通用或高級定時器的結構較為複雜，具體可參閱rm0090或野火，可以理解成在基礎定時器上多了一大塊輸出/入功能的部分。輸入捕獲(Input Capture)和輸出比較(Output Comepare)使得一些常見功能應用得以實現，譬如PWM和QEP
- 有的有多個channel，每個channel可以有各自的輸入和輸出
- 通用定時器有的功能，高級定時器一定也有，所以以下針對高級定時器內容做介紹

## 時鐘源
- 相比基礎定時器，通用與高級定時器的時鐘源多了很多選擇
    - internal clock，與基礎定時器相同的内部時鐘源
    - TIx，外部從輸入端給入的觸發訊號
    - ITRx，從其他內部timer的輸出觸發做為觸發訊號
- 不同的輸入可以組成不同的功能函時鐘模式，具體見手冊

## 時基單元(Time Base Unit)
- 高級定時器的時基單元與基礎定時器大致相同，只是多了一點額外功能

### 計數器(Counter)
- 高級定時器的計數器主要有三種模式
    - Upcounting : 往上遞增計數
    - Downcounting : 往下遞減計數
    - Center-aligned : 從0往上數，數到ARR值後往下數，數到0後又往上數
- 計數器的溢位counting overflow判別
### 重複計數器(Repetion Counter)
- 高級定時器獨有的計數器，通用計時器沒有
- 以遞增計數模式來說，重複計數器讓你可以數更多次後才觸發更新事件，具體見手冊
    ![image](https://hackmd.io/_uploads/SJFUuWdn0.png)
    
## 其他功能

### 輸入捕獲(Input Capture)
- 輸入捕獲對輸入信號的 rising/falling edge做捕獲與判別
- 常見功能為測量輸入信號的pulse width(脈寬)、測量PWM的頻率或佔空比等

### 輸出比較(Output Comepare)
- 核心概念就是內部有一個比較暫存器，透過計數器與比較暫存器的值做比較(大、小、等於)，決定輸出信號的電平
- 最常用的就是PWM模式

# STM的PWM模式
- https://deepbluembedded.com/stm32-pwm-example-timer-pwm-mode-tutorial/

## PWM原理
- 網路資訊很多，可自行查詢
- 簡言之
    - 以調整一個方波週期中on/off的比例輸出一個可以比擬成類比訊號的技術
    - 佔空比(Duty Cycle)即表示on訊號在方波週期中佔的百分比
    - 控制馬達時，從馬達驅動電路的H橋給入on訊號，相當於使馬達通電旋轉，off關電。若在驅動電路給入PWM訊號，依據佔空比不斷切換馬達on/off相當於給馬達一個類比電壓，調控馬達輸出功率

## 運作原理
- PWM模式就是輸出比較的一種延伸應用模式
- 有一個比較暫存器(capture/compare register, CCR)負責存放一個值
    - PWM mode 1 : counter值大於CCR值時，OCxREF(想像成輸出即可)為低電位，CCR值越大，代表佔空比越大，近似類比電壓越高
    - PWM mode 2 : counter值大於CCR值時，OCxREF(想像成輸出即可)為高電位，CCR值越大，代表佔空比越小，近似類比電壓越低
- 藉由調整TIMx_ARR和TIMx_CCRx暫存器改變生成PWM的頻率與佔空比

### PWM edge-aligned mode
- 遞增或遞減計數模式下使用
- 當計數器上數到ARR值時，計數器歸0
- 依據PWM mode 1/2 生成PWM波型
    ![image](https://hackmd.io/_uploads/B1R-NXOh0.png =70%x)


### PWM center-aligned mode
- center-aligned計數模式下使用
- 因為是先往上數後右往下數，所以本來一個週期的方波會再生成一個對稱的方波，兩個再視為新的週期。
    ![image](https://hackmd.io/_uploads/BJ2wNQO2A.png =60%x)


## CubeMX 配置
- [就很簡單](https://ithelp.ithome.com.tw/articles/10284334)
- 使用timer 3做PWM輸出，timer3為通用暫存器
- Mode配置
    ![image](https://hackmd.io/_uploads/ryjGBm_hR.png)
    - Slave Mode、Trigger Source、Clock Source決定了計時器的觸發源
    - PWM預設在clock source使用internal clock，即使不設置軟體也會在生成檔案中設置
    - CH1~4可以獨立的處理不同功能，選擇PWM Generation
    - 注意PWM Generation no output不會在對應的GPIO腳位生成PWM，只會在timer 內部生成供軟體使用
- 參數配置
    ![image](https://hackmd.io/_uploads/Byjew7On0.png)
    - 計時器設定
    	- prescaler 和 period 用途皆與基礎定時器相同。這兩者主要影響PWM方波頻率，而PWM頻率越高，越能更近的比擬對應類比訊號
    	- Counter Mode 一般用上數
    	- CKD的分頻用於 dead-time generators and the digital filters，這邊不特別做設置
    	- auto-reload preload一樣Disable
    	- TRGO的部分跟之前一樣
    - PWM設定
        - Mode就是PWM mode 1或PWM mode 2
        - Pulse 就是在初始化時先寫入CCR的值
        - Output compare preload、fast mode、CH polarity保留原本的，具體用途見手冊
            - [Output compare preload](https://blog.csdn.net/qq_16069457/article/details/103684525) 

## 程式編寫
- 進入while前的設定中，需要先打開timer 3與PWM功能，在user code begin 2區段加入
    ``` c++=
    HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
    ```
    - 注意TIM_CHANNEL_1是庫定義常數，同樣在庫中函式註解有提及應該給入什麼參數
    ``` c++=
    /**
  	* @brief  Starts the PWM signal generation.
  	* @param  htim TIM handle
  	* @param  Channel TIM Channels to be enabled
  	*          This parameter can be one of the following values:
  	*            @arg TIM_CHANNEL_1: TIM Channel 1 selected
  	*            @arg TIM_CHANNEL_2: TIM Channel 2 selected
  	*            @arg TIM_CHANNEL_3: TIM Channel 3 selected
  	*            @arg TIM_CHANNEL_4: TIM Channel 4 selected
  	* @retval HAL status
  	*/
    HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel){ ...}
    ```
- 我們知道改寫ARR值就是調整PWM頻率，在你要改變PWM頻率的地方加入這行
    ``` c++=
    __HAL_TIM_SET_AUTORELOAD(&htim3, 1000);
    ```
- 我們知道改寫CCR值就是調整PWM佔空比，在你要改變PWM值的地方加入這行
    ``` c++=
    __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1,1000);
    ```
## 小結
- 高級定時器的功能多而雜，本次PWM功能也只選取當中最廣泛易用的模式做說明
- 

# 練習1 - 呼吸燈
- 配置好PWM設定
- 在對應的PWM腳位拉出線連接LED與電阻串聯後接地
- 在while中更改CCR值以改變LED亮度，CCR值遞增到ARR值後再遞減至0再遞增，不斷往復
