寄存器層
1、TIM_Base_Set初始化常用:
CR1:TIM control reg 1
該寄存器內容決定定時器計數模式CounterMode、分頻比ClockDivision和ARR重裝值何時寫入有效判斷AutoReloadPreload
PSC:TIM prescaler reg
該寄存器內容決定預分頻Prescaler,對輸入的步長進行預處理為單位時間
ARR:TIM auto_reload_reg
該寄存器內容決定周期Period
CNT:TIM counter reg
定時器計數寄存器,Period對單位時間的count
EGR:TIM event generation reg
2、TIM_OC_Set初始化常用:
CR2:TIM control reg 2
該寄存器內容決定輸出引腳電平狀態OCIdleState或OCNIdleState
CCMRx:TIM_capture/compare mode reg x
channel1/2-------------x = 1
channel3/4-------------x = 2
該寄存器內容決定輸出模式OCMode,其中就包含了PWM
CCER:TIM capture/compare enable reg
該寄存器內容決定輸出極性設置OCPolarity/OCNPolarity
CCRx:TIM capture/compare regx
該寄存器在OC模式下決定PWM的Pulse值
3、TIM_TIx_Set初始化常用:
CCMRx:TIM capture/compare reg x
channel1/2-------------x = 1
channel3/4-------------x = 2
該寄存器決定捕獲通道選擇ICSelection和捕獲濾波器ICFilter,以及輸入捕獲預分頻ICPrescaler,注意ICPrescaler與寄存器是直接建立聯系,而不是通過TIM_TIx_Set傳入寄存器的,這與TIx的定義有關
CCER:TIM capture/compare enable reg
該寄存器決定輸入觸發極性ICPolarity,可選擇上升沿、下降沿或者雙沿觸發
CCRx:TIM capture/compare regx
該寄存器存儲上一個輸入捕獲事件發生時的計數值
上述各個寄存器對應的數值,除ICPrescaler外都在各自的TIM_XXX_Set中被賦以TIM_Base_InitTypeDef、TIM_OC_InitTypeDef、TIM_IC_InitTypeDef結構體中對應成員的數值,用戶只需要設定這些成員的數值就可以改變寄存器值
/** * @brief TIM Time base Configuration Structure definition */ typedef struct { uint32_t Prescaler; /*!< Specifies the prescaler value used to divide the TIM clock. This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */ uint32_t CounterMode; /*!< Specifies the counter mode. This parameter can be a value of @ref TIM_Counter_Mode */ uint32_t Period; /*!< Specifies the period value to be loaded into the active Auto-Reload Register at the next update event. This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */ uint32_t ClockDivision; /*!< Specifies the clock division. This parameter can be a value of @ref TIM_ClockDivision */ uint32_t RepetitionCounter; /*!< Specifies the repetition counter value. Each time the RCR downcounter reaches zero, an update event is generated and counting restarts from the RCR value (N). This means in PWM mode that (N+1) corresponds to: - the number of PWM periods in edge-aligned mode - the number of half PWM period in center-aligned mode GP timers: this parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFF. Advanced timers: this parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */ uint32_t AutoReloadPreload; /*!< Specifies the auto-reload preload. This parameter can be a value of @ref TIM_AutoReloadPreload */ } TIM_Base_InitTypeDef;
/** * @brief TIM Output Compare Configuration Structure definition */ typedef struct { uint32_t OCMode; /*!< Specifies the TIM mode. This parameter can be a value of @ref TIM_Output_Compare_and_PWM_modes */ uint32_t Pulse; /*!< Specifies the pulse value to be loaded into the Capture Compare Register. This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */ uint32_t OCPolarity; /*!< Specifies the output polarity. This parameter can be a value of @ref TIM_Output_Compare_Polarity */ uint32_t OCNPolarity; /*!< Specifies the complementary output polarity. This parameter can be a value of @ref TIM_Output_Compare_N_Polarity @note This parameter is valid only for timer instances supporting break feature. */ uint32_t OCFastMode; /*!< Specifies the Fast mode state. This parameter can be a value of @ref TIM_Output_Fast_State @note This parameter is valid only in PWM1 and PWM2 mode. */ uint32_t OCIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state. This parameter can be a value of @ref TIM_Output_Compare_Idle_State @note This parameter is valid only for timer instances supporting break feature. */ uint32_t OCNIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state. This parameter can be a value of @ref TIM_Output_Compare_N_Idle_State @note This parameter is valid only for timer instances supporting break feature. */ } TIM_OC_InitTypeDef;
/** * @brief TIM Input Capture Configuration Structure definition */ typedef struct { uint32_t ICPolarity; /*!< Specifies the active edge of the input signal. This parameter can be a value of @ref TIM_Input_Capture_Polarity */ uint32_t ICSelection; /*!< Specifies the input. This parameter can be a value of @ref TIM_Input_Capture_Selection */ uint32_t ICPrescaler; /*!< Specifies the Input Capture Prescaler. This parameter can be a value of @ref TIM_Input_Capture_Prescaler */ uint32_t ICFilter; /*!< Specifies the input capture filter. This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */ } TIM_IC_InitTypeDef;
Init與Config層
這一層相當於一個過渡,目的是更方便地引出API
從官方差異化的命名可以看出,定時器的輸出與輸入捕獲有別於定時器的基本功能——定時溢出,而是在基本功能實現的情況下去做一些附加的東西,這里從回調函數也可以看出來,並不復雜就不再細說,這些函數會調用對應的TIM_XXX_Set與MspInit
用戶Init層
用戶需要編寫Init層,通過TypeDef上述句柄,修改結構體內容並傳入Init與Config層達到配置TIM特性的目的,Init與Config層、寄存器層都是封裝在HAL庫里的,於是我們可以得到如下關系
一層層把包含特性配置信息的句柄傳入,最后賦值給寄存器
以上就是定時器初始化的部分內容
要讓定時器開始工作,中斷使能必不可少
CRx:TIM control regx
控制寄存器,使能時需要置位寄存器使能計數器,具體操作可由函數__HAL_TIM_ENABLE(&htim)實現
DIER:TIM DMA/interrupt enable reg
中斷允許寄存器,一般情況下可調用__HAL_TIM_ENABLE_IT(&htim,TIM_IT_UPDATE)置位對應寄存器
定時器使能完成后,用戶最常訪問的就是定時器的狀態,要訪問定時器的狀態,只需要下面這個寄存器
SR:TIM state reg
__HAL_TIM_GET_FLAG(__HANDLE__, __FLAG__)
__HAL_TIM_CLEAR_FLAG(__HANDLE__, __FLAG__)
其中,__HANDLE__為自定義的句柄&htim,__FLAG__為各flag
/** @brief Check whether the specified TIM interrupt flag is set or not. * @param __HANDLE__ specifies the TIM Handle. * @param __FLAG__ specifies the TIM interrupt flag to check. * This parameter can be one of the following values: * @arg TIM_FLAG_UPDATE: Update interrupt flag * @arg TIM_FLAG_CC1: Capture/Compare 1 interrupt flag * @arg TIM_FLAG_CC2: Capture/Compare 2 interrupt flag * @arg TIM_FLAG_CC3: Capture/Compare 3 interrupt flag * @arg TIM_FLAG_CC4: Capture/Compare 4 interrupt flag * @arg TIM_FLAG_COM: Commutation interrupt flag * @arg TIM_FLAG_TRIGGER: Trigger interrupt flag * @arg TIM_FLAG_BREAK: Break interrupt flag * @arg TIM_FLAG_CC1OF: Capture/Compare 1 overcapture flag * @arg TIM_FLAG_CC2OF: Capture/Compare 2 overcapture flag * @arg TIM_FLAG_CC3OF: Capture/Compare 3 overcapture flag * @arg TIM_FLAG_CC4OF: Capture/Compare 4 overcapture flag * @retval The new state of __FLAG__ (TRUE or FALSE). */ #define __HAL_TIM_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->Instance->SR &(__FLAG__)) == (__FLAG__))
TIM Channels應用實例1:輸出比較(PWM)
STM32可以由定時器產生PWM波,相較於TIM的一般應用,增加了對於通道及輸出口的配置:
初始化:MX_TIM_Init()
1、配置結構體TIM_HandleTypeDef定義的htim成員
2、配置結構體TIM_OC_InitTypeDef定義的sConfigOC成員
3、配置結構體TIM_MasterConfigTypeDef與TIM_ClockConfigTypeDef定義的成員,這里按默認
4、配置輸出GPIO復用參數,MX將其封裝在一個MspPostInit里在MX_TIM_Init()調用
其中第二條是與一般應用的不同之處,用於初始化Output Compare的各項參數
輸出允許:HAL_TIM_PWM_Start(&htim,TIM_CHANNEL_x)
允許輸出PWM,將在配置的GPIO口上輸出PWM波,這一功能的配置相對簡單,也可以看出,ST官方給出定時器的比較與捕獲通道,具有很多用處,且避免了用戶需要自己寫邏輯來實現這些功能的麻煩
TIM Channels應用實例2:輸入捕獲
輸入捕獲,實際上就是在定時器的基礎上加了對於特定引腳的捕獲通道,使得循環計時的定時器能關聯上外部引腳電平:
初始化:MX_TIM_Init()
1、配置結構體TIM_HandleTypeDef定義的htim成員
2、配置結構體TIM_IC_InitTypeDef定義的sConfigIC成員
3、配置結構體TIM_MasterConfigTypeDef與TIM_ClockConfigTypeDef定義的成員,這里按默認
4、配置輸入GPIO復用參數,此處寫在MspInit里
中斷允許:HAL_TIM_IC_Start_IT(&htim5,TIM_CHANNEL_1);
__HAL_TIM_ENABLE_IT(&htim5,TIM_IT_UPDATE);
此處對CR進行了兩次操作,后者將DIER置位為TIM_TI_UPDATE,在前者將DIER置位為TIM_IT_CC1,同時允許了CR中的計數器使能
中斷服務:
基本的邏輯就是在檢測到高電平時定時器清零,接着開始循環計時,同時更改觸發電平為低電平觸發,每溢出一次手動計數,這是在下次觸發時,高電平事件就是ARR乘以溢出次數加上此次的CCRx
uint8_t TIM5CH1_CAPTURE_STA = 0; uint32_t TIM5CH1_CAPTURE_VAL = 0; void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim == (&htim5)) { if((TIM5CH1_CAPTURE_STA &0x80) == 0) { if(TIM5CH1_CAPTURE_STA &0x40) { if((TIM5CH1_CAPTURE_STA &0x30) == 0x3f) { TIM5CH1_CAPTURE_STA |= 0x80; TIM5CH1_CAPTURE_VAL = 0xffffffff; } else { TIM5CH1_CAPTURE_STA ++; } } } } } void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if(htim == (&htim5)) { if((TIM5CH1_CAPTURE_STA &0x80) == 0) { if(TIM5CH1_CAPTURE_STA &0x40) { TIM5CH1_CAPTURE_STA |= 0x80; TIM5CH1_CAPTURE_VAL = HAL_TIM_ReadCapturedValue(&htim5,TIM_CHANNEL_1); TIM_RESET_CAPTUREPOLARITY (&htim5, TIM_CHANNEL_1); TIM_SET_CAPTUREPOLARITY (&htim5, TIM_CHANNEL_1, TIM_ICPOLARITY_RISING); } else { TIM5CH1_CAPTURE_STA = 0; TIM5CH1_CAPTURE_VAL = 0; TIM5CH1_CAPTURE_STA |= 0x40; __HAL_TIM_DISABLE (&htim5); //關閉定時器5 __HAL_TIM_SET_COUNTER (&htim5,0); TIM_RESET_CAPTUREPOLARITY (&htim5,TIM_CHANNEL_1); //一定要先清除原來的設置!! TIM_SET_CAPTUREPOLARITY (&htim5,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);//定時器5通道1設置為下降沿捕獲 __HAL_TIM_ENABLE (&htim5);//使能定時器5 } } } }
if(TIM5CH1_CAPTURE_STA&0X80) //成功捕獲到了一次高電平 { temp=TIM5CH1_CAPTURE_STA&0X3F; temp*=0XFFFFFFFF; //溢出時間總和 temp+=TIM5CH1_CAPTURE_VAL; //得到總的高電平時間 printf("HIGH:%lld us\r\n",temp);//打印總的高點平時間 TIM5CH1_CAPTURE_STA=0; //開啟下一次捕獲 }
此處引用正點原子的服務函數,自行理解