廣大的互聯網的你們早上中午晚上、、又好、、沒錯了、、我又來了、、寫博客不是定時的、、爲何我要提寫博客不是定時的呢??聰明的人又猜到我要說什麼了吧、有前途、其實我仍是第一次聽到定時器有通用和高級之分的、、原來定時器也有分等級的呀、、STM32果然不簡單呀、、編程
好了、、爲啥名爲通用呢?、恕小弟不才、目前只理解爲:由於能夠通用,因此名爲通用定時器、那能夠通用在哪些方面呢?那通用的原理又是什麼呢?咦,不急不急、、待我慢慢翻開「葵花寶典」第STM32篇之通用定時器:葵花兄,近來可好?我們又見面了、能告訴我定時器能夠通用在哪些方面嗎?只見葵花兄不慌不忙的說:通用定時器能夠用來:函數
一、測量輸入信號的脈衝長度,也就是輸入捕獲(請對此四字短語養成良好的形象哈)編碼
二、產生輸出波形,也就是輸出比較或者PWM(同上)
spa
那葵花兄,通用的原理呢?又見葵花兄坦然自若的說:通用定時器是一個經過可編程預分頻器(PSC)(注:這三個字母要有印象哈)驅動的16位自動裝載計數器(CNT)(注:同上)構成。code
好了,你們撇開葵花兄,把焦點從新聚焦在我身上、那通用定時器有什麼功能呢?我想確定有人立刻反應:有定時的功能、、額、、我也不能說你錯是吧、、那我來具體點吧,其實也不是我具體,多虧了「葵花寶典」第STM32篇中文參考手冊 :blog
1) 16 位向上 、向下 、向上/向下自動裝載計數器 (TIMx_CNT)。
2) 16 位可編程( 能夠實時修改 )預分頻器(TIMx_PSC)(TIMx_PSC)(TIMx_PSC),計數器時鐘頻率的分系爲 1~ 65535 之間的任意數值。
3)4個獨立通道( TIMx_CH1~4 TIMx_CH1~4 TIMx_CH1~4 TIMx_CH1~4)
A.輸入捕獲
B.輸出比較
C.PWM 生成 (邊緣或中間對齊模式 )
D.單脈衝模式輸出
4)可以使用外部信號( TIMx_ETR )控制定時器和互連(能夠用1個定時器控制另一個定時器)的同步電路。
5)以下事件發生時產生中斷/DMA:
A.更新:計數器向上溢出/向下溢出,計數器初始化 ( 經過軟件或者內部 /外部觸發 )
B.觸發事件 (計數器啓動、中止初始化或者由內部/外部觸發計數 )
C.輸入捕獲
D.輸出比較
E.支持針對定位的增量 (正交 )編碼器和霍爾傳感電路
F.觸發輸入做爲外部時鐘或者按週期的電流管理事件
固然啦,在此博客中不考慮那麼多功能先哈、、先淡定、、如果被嚇到了、、先去喝杯茶壓壓驚哈、、那咱們怎麼來實現定時的功能呢?ip
只要定時、當達到必定容量時,就會發生溢出、、聰明的人又知道我要說什麼了吧?世上太多聰明的人了、、沒錯了、、把中斷這位兄弟叫上、讓溢出兄和中斷兄合身、、(省略合身等待的時間)、對了、誕生了溢出中斷、咱們給取個好聽的名字:更新中斷、在這裏,咱們是利用中斷來定時的、、同步
接下來,容小弟介紹下與此博客有關係的寄存器(具體的位是什麼功能我就不講了哈,由於咱們是採用庫而不是操做寄存器,想知道的能夠參考中文參考手冊哈),你們掌聲響起:歡迎控制兄(TIMx_CR1)博客
歡迎中斷/DMA使能兄(TIMx_DIER):
歡迎預分頻器兄(TIMx_PSC):
歡迎自動重裝載寄存器兄(TIMx_ARR):
好了、、這四位能夠在旁邊休息了(咱們就不介紹了)、、由於咱們的重點:庫兄要出現了,接下來,用最熱烈的掌聲歡迎:
首先:有請掛載時鐘大神ABP1(爲何要請這位大神呢?由於咱們的通用定時器是掛載在這位ABP1的,證據以下)
再者,咱們有請第二大神:初始化大神:TIM_TimeBaseInit(爲何是他呢?爲何?到底是爲何?啊哈、、請看)
看到了吧、、因此請不要懷疑大神的地位哈、、至於參數具體是哪些,你們能夠打開#include "stm32f10x_tim.h"哈,在這裏就很少說了、、相信你們都是聰明人、
前兩位大神出來了,咱們還有大神、、哎、、大神無處不在、、來、有請類型中斷使能大神
void TIM_ITConfig(TIM_TypeDef* TIMx, u16 TIM_IT, FunctionalState NewState)
看到中斷、、你們又有想到什麼貓膩沒??條件發射就是這樣煉成的、、沒錯了、、就是中斷優先級設置大神啦、、這個你們應該有印象、我就不細說了哈,沒印象的話這位大神可就要躲到某個角落傷心了,
看到以上大神、、其實還有一位大神沒出現、、此大神沒出現、、其餘大神啥都不是、、對了、就是定時器啓動大神
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)
好了、、最後,編寫中斷服務函數,在中斷函數裏檢查中斷標誌位和清中斷標誌位,還有你想要作的事,相信你們也是比較熟悉的了、、
在這裏,咱們來談談時鐘的問題、、你們能夠看到系統時鐘樹圖裏:
看到我美麗銷魂的塗鴉沒、、因爲個人系統時鐘初始化是36MHZ的、並且設置APB1的預分頻係數爲2,因此定時器的時鐘就爲72MHZ,你們能夠根據本身的系統時鐘設置選擇哈、、
到此,咱們來總結下使用中斷的定時器:
1.開啓掛載在ABP1上的TIM3的時鐘
2.對定時器進行初始化
3.設置中斷類型
4.設置中斷優先級
5.開啓定時器3
6.編寫中斷服務函數 看一下參考代碼:
1 void Timer_3_Init(u16 arr,u16 psc) 2 { 3 4 //Tout = (arr + 1) * (psc + 1) / 72; 5 6 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 7 NVIC_InitTypeDef NVIC_InitStructure; 8 9 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //1 此數字對應上面的步驟 10 11 TIM_TimeBaseStructure.TIM_Period = arr; //這個值在0~65535之間 爲16位計數值 //2 12 TIM_TimeBaseStructure.TIM_Prescaler = psc; 13 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; 14 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 15 TIM_TimeBaseInit(TIM3, & TIM_TimeBaseStructure); 16 17 TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE ); //3 18 19 NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //4 20 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; 21 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; 22 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 23 NVIC_Init(&NVIC_InitStructure); 24 25 TIM_Cmd(TIM3, ENABLE); //5 26 } 27 28 void TIM3_IRQHandler(void) //6 29 { 30 if(TIM_GetITStatus(TIM3, TIM_IT_Update) == SET) 31 { 32 TIM_ClearITPendingBit(TIM3, TIM_IT_Update); 33 LED1 = !LED1; 34 } 35 }
好了、、說到這裏、、通用果真是通用的、、對於全部的通用定時器都是一樣的原理、、在這裏咱們只是實現了簡單的定時(值加到某個程度就更新產生中斷,經過LED燈顯示)、、但願你們多多指教、、本博客比較滑稽、、望你們莫怪哈、、有什麼說錯的地方請像抓腐敗那樣提出來哈、、我虛心向您請教、、謝謝你們、、