筆記整理自B站UP主江科大自化協(xié)教程《STM32入門教程-2023持續(xù)更新中》,所用單片機(jī)也為教程推薦單片機(jī)。
大致內(nèi)容
第一部分:定時(shí)器基本定時(shí)的功能,定時(shí)器每隔這個(gè)時(shí)間產(chǎn)生一個(gè)中斷,來實(shí)現(xiàn)每隔一個(gè)固定時(shí)間執(zhí)行一段程序的目的,比如要做一個(gè)時(shí)鐘、秒表或者使用一些程序算法的時(shí)候都需要用到定時(shí)中斷這個(gè)功能
第二部分:定時(shí)器輸出比較的功能,最常見的用途就是產(chǎn)生PWM波形,用于驅(qū)動(dòng)電機(jī)等設(shè)備
第三部分:定時(shí)器輸入捕獲的功能,使用輸入buhuo這個(gè)模塊來實(shí)現(xiàn)測(cè)量方波頻率的例子
第四部分:定時(shí)器的編碼器接口,使用編碼器接口能夠更加方便地讀取正交編碼器的輸出波形,在編碼電機(jī)測(cè)速中,應(yīng)用廣泛
使用定時(shí)器的外部時(shí)鐘,可以提供一個(gè)更加精準(zhǔn)的時(shí)鐘來計(jì)時(shí)或者也可以把外部時(shí)鐘當(dāng)做一個(gè)計(jì)數(shù)器,用來統(tǒng)計(jì)引腳上電平翻轉(zhuǎn)的次數(shù)。
TIM簡(jiǎn)介
TIM(Timer)定時(shí)器,定時(shí)器可以對(duì)輸入的時(shí)鐘進(jìn)行計(jì)數(shù),并在計(jì)數(shù)值達(dá)到設(shè)定值時(shí)觸發(fā)中斷
當(dāng)計(jì)數(shù)器的輸入時(shí)一個(gè)準(zhǔn)確可靠的基準(zhǔn)時(shí)鐘(STM32中一般都是主頻72MHz)的時(shí)候,在對(duì)這個(gè)基準(zhǔn)時(shí)鐘進(jìn)行計(jì)數(shù)的過程,實(shí)際上就是計(jì)時(shí)的過程。
如果對(duì)72MHz計(jì)72個(gè)數(shù),那就是1MHz即1us的時(shí)間;如果計(jì)72000個(gè)數(shù),那就是1KHz即1ms的時(shí)間
16位的計(jì)數(shù)器、預(yù)分頻器、自動(dòng)重裝寄存器的時(shí)基單元(最核心的部分),在72MHz計(jì)數(shù)時(shí)鐘下可以實(shí)現(xiàn)最大59.65s的定時(shí)
計(jì)數(shù)器:用來執(zhí)行計(jì)數(shù)定時(shí)的一個(gè)寄存器,每來一個(gè)時(shí)鐘,計(jì)數(shù)器加1
預(yù)分頻器:可以對(duì)計(jì)數(shù)器的時(shí)鐘進(jìn)行分頻,讓這個(gè)計(jì)數(shù)更加靈活
自動(dòng)重裝寄存器:計(jì)數(shù)的目標(biāo)值,即想要計(jì)多少個(gè)時(shí)鐘申請(qǐng)中斷
72M/65536/65536得到中斷頻率,取到數(shù)即為59.65s
STM32定時(shí)器支持級(jí)聯(lián)的模式,也就是一個(gè)定時(shí)器的輸出當(dāng)做另一個(gè)定時(shí)器的輸入,這樣最大定時(shí)時(shí)間:59.65*65536*65536
不僅具備基本的定時(shí)中斷功能,而且還包含內(nèi)外時(shí)鐘源選擇、輸入捕獲、輸出比較、編碼器接口、主從觸發(fā)模式等多種功能。根據(jù)復(fù)雜度和應(yīng)用場(chǎng)景分為了高級(jí)定時(shí)器(最復(fù)雜)、通用定時(shí)器、基本定時(shí)器三種類型。
定時(shí)器類型

STM32F103C8T6定時(shí)器資源:TIM1、TIM2、TIM3、TIM4(沒有基本定時(shí)器)
基本定時(shí)器
基本定時(shí)器只能選擇內(nèi)部時(shí)鐘

基本定時(shí)器框圖
預(yù)分頻器
寫0:不分頻或者一分頻,輸出頻率=輸入頻率=72MHz;
寫1:二分頻,輸出頻率=輸入頻率/2=36MHz;
寫2:三分頻,輸出頻率=輸入頻率/3=24MHz;
概括歸納:實(shí)際分頻系數(shù) = 預(yù)分頻器的值 + 1
預(yù)分頻器是16位的,所以最大值可以寫65535,也就是65536分頻
計(jì)數(shù)器
可以對(duì)預(yù)分頻后的計(jì)數(shù)時(shí)鐘進(jìn)行計(jì)數(shù),計(jì)數(shù)時(shí)鐘每來一個(gè)上升沿計(jì)數(shù)器的值就+1,計(jì)數(shù)器也是16位的,里面的值可以從0~65535
UI(向上箭頭)
計(jì)數(shù)值等于自動(dòng)重裝值產(chǎn)生的中斷——更新中斷;
U(向下箭頭)
會(huì)產(chǎn)生一個(gè)事件——更新事件
更新事件不會(huì)觸發(fā)中斷,但可以觸發(fā)內(nèi)部其他電路的工作
主模式觸發(fā)DAC功能
它能讓內(nèi)部的硬件在不受程序的控制下實(shí)現(xiàn)自動(dòng)運(yùn)行
使用DAC的時(shí)候,可能會(huì)用DAC輸出一段波形,就需要每隔一段時(shí)間來觸發(fā)一次DAC,讓它輸出下一個(gè)電壓點(diǎn),通過把定時(shí)器的更新事件映射到這個(gè)觸發(fā)輸出TRGO(Trigger Out)的位置,這樣定時(shí)器的更新就不需要通過中斷來觸發(fā)DAC轉(zhuǎn)換了,整個(gè)過程不需要軟件的參與,實(shí)現(xiàn)了硬件的自動(dòng)化。

通用定時(shí)器

對(duì)于通用定時(shí)器而言,計(jì)數(shù)器的計(jì)數(shù)模式就不止向上計(jì)數(shù)一種,還有向下計(jì)數(shù)模式和中央對(duì)齊模式。
中央對(duì)齊模式:先向上自增,計(jì)到重裝值,申請(qǐng)中斷,然后再向下自減,減到0,申請(qǐng)中斷,一次循環(huán)...


ITR和定時(shí)器的連接關(guān)系
ITR0~3:可用于實(shí)現(xiàn)定時(shí)器的級(jí)聯(lián),比如可以先初始化TIM3,然后使用主模式把它的更新事件映射到TRGO上,再初始化TIM2,選擇TIR2,對(duì)應(yīng)就是TIM3的TRGO,再選擇時(shí)鐘為外部時(shí)鐘模式1(TRGI),這樣TIM3的更新事件就可以驅(qū)動(dòng)TIM2的時(shí)基單元
TI1F_ED:ED(edge邊沿)
外部時(shí)鐘模式1
輸入可以是ETR引腳(外部時(shí)鐘)、其他定時(shí)器、CH1引腳的邊沿、CH1引腳和CH2引腳
外部時(shí)鐘模式2

定時(shí)器主模式輸出

輸出比較電路

可以用于輸出PWM波形,驅(qū)動(dòng)電機(jī)
輸入捕獲電路

可以用于測(cè)量輸入方波的頻率

輸入捕獲和輸出比較共用的寄存器
高級(jí)定時(shí)器

相對(duì)于通用定時(shí)器增加的部分

可以實(shí)現(xiàn)每隔幾個(gè)計(jì)數(shù)周期,才發(fā)生一次更新事件和更新中斷(相當(dāng)于對(duì)輸出的更新信號(hào)又做了一次分頻),59.65*65536s

DTG(Dead Time Generate)死區(qū)生成電路
可以輸出一對(duì)互補(bǔ)的PWM波(對(duì)比通用定時(shí)器),為了驅(qū)動(dòng)三相無刷電機(jī)(四軸飛行器、電動(dòng)車的后輪、電鉆等)因?yàn)槿酂o刷電機(jī)的驅(qū)動(dòng)電路一般需要3個(gè)橋臂,每個(gè)橋臂兩個(gè)大功率開關(guān)管來控制,總共需要6個(gè)大功率開關(guān)管,所以這里的輸出PWM引腳的前三路就變?yōu)榱嘶パa(bǔ)的輸出,為了防止互補(bǔ)輸出的PWM驅(qū)動(dòng)橋臂時(shí),在開關(guān)切換的瞬間,由于器件的不理想,造成短暫的直通現(xiàn)象,所以前面就加上了死區(qū)生成電路,在開關(guān)切換的瞬間,產(chǎn)生一定時(shí)長(zhǎng)的地區(qū),讓橋臂的上下管全都關(guān)斷,防止直通現(xiàn)象。


為了給電機(jī)驅(qū)動(dòng)提供安全保障的,如果外部引腳BKIN(Break IN)產(chǎn)生了剎車信號(hào),或者內(nèi)部時(shí)鐘失效,產(chǎn)生了故障,那么控制電路就會(huì)自動(dòng)切斷電機(jī)的輸出,防止意外的發(fā)生。
定時(shí)中斷基本結(jié)構(gòu)圖

PSC:Prescaler預(yù)分頻器
CNT:Counter計(jì)數(shù)器
ARR:AutoReloadRegister自動(dòng)重裝定時(shí)器
中斷輸出控制:中斷輸出的允許位,如果需要某個(gè)中斷就允許一下
預(yù)分頻器時(shí)序

CK_PSC:預(yù)分頻器的輸入時(shí)鐘
CNT_EN:計(jì)數(shù)器使能,高電平計(jì)數(shù)器正常運(yùn)行,低電平計(jì)數(shù)器停止
CN_CNT:計(jì)數(shù)器時(shí)鐘輸入,也是預(yù)分頻器的時(shí)鐘輸出
根據(jù)上圖可以推斷ARR自動(dòng)重裝值就是FC
預(yù)分頻緩沖器:影子寄存器(可以看通用定時(shí)器高級(jí)定時(shí)器那張圖,方框帶有陰影的都是影子寄存器),這是真正起作用的寄存器
比如在某個(gè)時(shí)刻,把預(yù)分頻控制寄存器由0改成1,如果在此時(shí)立刻改變時(shí)鐘的分頻系數(shù),會(huì)導(dǎo)致在一個(gè)計(jì)數(shù)周期內(nèi),前半部分和后半部分的頻率不一致,不太嚴(yán)謹(jǐn);這個(gè)預(yù)分頻緩沖器,就是當(dāng)在計(jì)數(shù)計(jì)到一半的時(shí)候改變了分頻值,這個(gè)變化并不會(huì)立刻生效,而是會(huì)等到本次計(jì)數(shù)周期結(jié)束時(shí),產(chǎn)生了更新事件,預(yù)分頻控制寄存器的值才會(huì)被傳送到預(yù)分頻緩沖器中,才會(huì)生效。
計(jì)數(shù)器計(jì)數(shù)頻率:CK_CNT = CK_PSC / (PSC + 1)

計(jì)數(shù)器時(shí)序

CK_INT:內(nèi)部時(shí)鐘72MHz
計(jì)數(shù)器溢出頻率:CK_CNT_OV = CK_CNT / (ARR + 1) = CK_PSC / (PSC + 1) / (ARR + 1)
CK_PSC=72MHz
取倒數(shù)即為溢出時(shí)間
計(jì)數(shù)器無預(yù)裝時(shí)序

沒有緩沖寄存器的情況
計(jì)數(shù)器有預(yù)裝時(shí)序

有緩沖寄存器的情況
引入影子寄存器的目的:為了同步,讓值的變化和更新事件同步,防止在運(yùn)行途中更改造成錯(cuò)誤
RCC時(shí)鐘樹
用來產(chǎn)生和配置時(shí)鐘,并且把配置好的時(shí)鐘發(fā)送到各個(gè)外設(shè)的系統(tǒng)
程序中主函數(shù)之前還會(huì)執(zhí)行一個(gè)SystemInit函數(shù),這個(gè)函數(shù)就是用來配置整個(gè)時(shí)鐘樹的

左半邊是時(shí)鐘產(chǎn)生電路;右半邊是時(shí)鐘分配電路
SYSCLK:系統(tǒng)時(shí)鐘72MHz
時(shí)鐘產(chǎn)生電路有四個(gè)震蕩源,分別是內(nèi)部8MHz高速RC振蕩器、外部的4~16MHz高速石英晶體振蕩器(晶振一般都是接8MHz)、外部的32.768KHz的低速晶振(一般是給RTC提供時(shí)鐘)、內(nèi)部的40KHz低速RC振蕩器(給看門狗提供時(shí)鐘)
兩個(gè)高速晶振是用來提供系統(tǒng)時(shí)鐘,AHB、APB1、APB2的時(shí)鐘都是來源于這兩個(gè)高速晶振
PLL:鎖相環(huán),8MHz倍頻9倍,得到72MHz,等到鎖相環(huán)輸出穩(wěn)定后選擇鎖相環(huán)輸出為系統(tǒng)時(shí)鐘
一開始是內(nèi)部8MHz提供系統(tǒng)時(shí)鐘,后鎖相環(huán)輸出為系統(tǒng)時(shí)鐘,由8MHz切換為72MHz,這是ST配置的流程。
CSS:Clock Security System 時(shí)鐘安全系統(tǒng),負(fù)責(zé)切換時(shí)鐘,可以監(jiān)測(cè)外部時(shí)鐘的運(yùn)行狀態(tài),一旦外部時(shí)鐘失效,就會(huì)自動(dòng)把外部時(shí)鐘切換回內(nèi)部時(shí)鐘,保證系統(tǒng)時(shí)鐘的運(yùn)行,防止程序卡死造成事故,高級(jí)定時(shí)器中也有CSS。
APB1總線的時(shí)鐘:72MHz/2=36MHz
無論基本定時(shí)器、通用定時(shí)器、高級(jí)定時(shí)器的內(nèi)部基準(zhǔn)時(shí)鐘都是72MHz
外設(shè)時(shí)鐘配置就是指我們程序中配置時(shí)鐘

定時(shí)中斷代碼講解(定時(shí)器定時(shí)中斷變量++為例)
第一步:RCC開啟時(shí)鐘
第二步:選擇時(shí)基單元的時(shí)鐘源
第三步:配置時(shí)基單元
第四步:配置輸出中斷控制,允許更新中斷輸出到NVIC
第五步:配置NVIC,在NVIC中打開定時(shí)器中斷的通道,并分配一個(gè)優(yōu)先級(jí)
第六步:運(yùn)行控制,使能計(jì)數(shù)器
上述步驟可參考定時(shí)器中斷基本結(jié)構(gòu)圖:

定時(shí)器中斷基本結(jié)構(gòu)圖
先來看一下定時(shí)器的庫(kù)函數(shù),stm32f10x_tim.h
TIM_DeInit——恢復(fù)缺省配置
TIM_TimeBaseInit——時(shí)基單元初始化
TIM_TimeBaseStructInit——給結(jié)構(gòu)體變量賦一個(gè)默認(rèn)值
TIM_Cmd——使能計(jì)數(shù)器,對(duì)應(yīng)圖中的運(yùn)行控制
TIM_ITConfig——用來使能中斷輸出信號(hào),對(duì)應(yīng)圖中的中斷輸出控制
TIM_InternalClockConfig——選擇內(nèi)部時(shí)鐘
TIM_ITRxExternalClockConfig——選擇ITRx其他定時(shí)器的時(shí)鐘
TIM_TIxExternalClockConfig——選擇TIx捕獲通道的時(shí)鐘
TIM_ETRClockMode1Config——選擇ETR通過外部時(shí)鐘模式1輸入的時(shí)鐘
Polarity——極性、Filter——濾波器
TIM_ETRClockMode2Config——選擇ETR通過外部時(shí)鐘模式2輸入的時(shí)鐘
TIM_ETRConfig——單獨(dú)用來配置ETR引腳的預(yù)分頻器、極性、濾波器這些參數(shù)的
TIM_PrescalerConfig——單獨(dú)用來寫預(yù)分頻值的
TIM_CounterModeConfig——用來改變計(jì)數(shù)器的計(jì)數(shù)模式
TIM_ARRPreloadConfig——自動(dòng)重裝器預(yù)裝功能配置,前面提到過有預(yù)裝和無預(yù)裝
TIM_SetCounter——給計(jì)數(shù)器寫入一個(gè)值
TIM_SetAutoreload——給自動(dòng)重裝器寫入一個(gè)值
TIM_GetCounter——獲取當(dāng)前計(jì)數(shù)器的值,如果想看這個(gè)計(jì)數(shù)器計(jì)到哪里了可以調(diào)用這個(gè)函數(shù)
TIM_GetPrescaler——獲取當(dāng)前預(yù)分頻器的值
TIM_GetFlagStatus、TIM_ClearFlag、TIM_GetITStatus、TIM_ClearITPendingBit——獲取標(biāo)志位和清除標(biāo)志位,講外部中斷的時(shí)候也提到過,不知道的可以參考那一節(jié)
第一步——開啟時(shí)鐘

主體代碼
注意這里是APB1
第二步——選擇時(shí)基單元的時(shí)鐘
選擇為內(nèi)部時(shí)鐘,當(dāng)然定時(shí)器上電后默認(rèn)使用內(nèi)部時(shí)鐘,不寫這一行也行

主體代碼
第三步——配置時(shí)基單元
TIM_ClockDivision
之前有提到過濾波器可以濾掉信號(hào)抖動(dòng)干擾,如果工作呢?
就是在一個(gè)固定的是時(shí)鐘頻率f下對(duì)信號(hào)進(jìn)行采樣,如果連續(xù)N個(gè)采樣點(diǎn)都為相同的電平,那就代表輸入信號(hào)穩(wěn)定,把采樣值輸出,如果這N個(gè)采樣值不全相同,那就說明信號(hào)有抖動(dòng),這時(shí)就保持上一次的輸出或者直接輸出低電平,這樣就能保證輸出信號(hào)在一定程度上的濾波,這里的采樣頻率f和采樣點(diǎn)數(shù)N都是濾波器的參數(shù),頻率越低采樣點(diǎn)數(shù)越多,那濾波效果就越好,不過相應(yīng)的信號(hào)延遲就越大。
采樣頻率f從哪來?
內(nèi)部時(shí)鐘直接而來,也可以是由內(nèi)部時(shí)鐘加一個(gè)時(shí)鐘分頻而來,那分頻多少由TIM_ClockDivision函數(shù)決定
TIM_CounterMode

向上計(jì)數(shù)、向下計(jì)數(shù)、三種中央對(duì)齊的計(jì)數(shù)模式
TIM_Period
周期,ARR自動(dòng)重裝器的值
TIM_Prescaler
PSC,預(yù)分頻器的值
TIM_RepetitionCounter
重復(fù)計(jì)數(shù)器的值,這個(gè)是高級(jí)定時(shí)器才有的,這里不需要用,直接給0
定1s的時(shí)間如何配置參數(shù)呢?
公式:計(jì)數(shù)器溢出頻率:CK_CNT_OV = CK_CNT / (ARR + 1) = CK_PSC / (PSC + 1) / (ARR + 1)
定時(shí)1s->定時(shí)頻率1Hz
套用公式,比如PSC = 7200 - 1,ARR = 10000 - 1
72MHz / 7200 / 10000 = 1Hz
注意PSC和ARR的取值在0~65535之間
PSC和ARR的取值不是唯一的,可以預(yù)分頻給少點(diǎn),自動(dòng)重裝給多點(diǎn),這樣就是以一個(gè)比較高的頻率(時(shí)間短)計(jì)比較多的數(shù);也可以預(yù)分頻給多點(diǎn),自動(dòng)重裝給少點(diǎn),這樣就是以一個(gè)比較低的頻率(時(shí)間長(zhǎng))計(jì)比較少的數(shù)

主體代碼
第四步——使能更新中斷

主體代碼
開啟了更新中斷到NVIC的通路
第五步——配置NVIC

主體代碼
具體解釋可以參考外部中斷那一節(jié)
第六步——啟動(dòng)定時(shí)器

主體代碼
代碼分析

可以通過這個(gè)函數(shù)看一下計(jì)數(shù)器的值,我們這里是0~9999變化的,對(duì)應(yīng)了之前代碼中的TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;
中斷函數(shù)代碼部分
中斷函數(shù)名都是規(guī)定好的,啟動(dòng)文件中找,startup_stm32f10x_md.s

主體代碼
定時(shí)中斷代碼講解(定時(shí)器外部時(shí)鐘端口PA0為例)
上一部分代碼理解了,這一部分就可以在上一部分的代碼上稍作更改
第一步——開啟時(shí)鐘

主體代碼
第二部——配置GPIO

表格中給的是浮空輸入,這里建議用上拉輸入
如果外部的輸入信號(hào)功率很小,內(nèi)部的上拉電阻可能會(huì)影響到這個(gè)輸入信號(hào),這時(shí)可用浮空輸入,防止影響外部輸入的電平。

主體代碼
第三步——選擇時(shí)基單元的時(shí)鐘
這和之前不一樣,這里就是來源于外部時(shí)鐘了

主體代碼
第二個(gè)參數(shù):外部觸發(fā)預(yù)分頻器,TIM_ExtTRGPSC_OFF不需要分頻
第三個(gè)參數(shù):外部觸發(fā)的極性,TIM_ExtTRGPolarity_Inverted反向(低電平或者下降沿有效);TIM_ExtTRGPolarity_NonInverted不反向(高電平或者上升沿有效)
第四個(gè)參數(shù):外部觸發(fā)濾波器,之前第三步講時(shí)基單元的時(shí)候有介紹過濾波器,就是以采用頻率f采樣N個(gè)點(diǎn),具體怎樣的對(duì)應(yīng)關(guān)系看手冊(cè):

寫0x00不用濾波器
第四步——配置時(shí)基單元

主體代碼
公式:計(jì)數(shù)器溢出頻率:CK_CNT_OV = CK_CNT / (ARR + 1) = CK_PSC / (PSC + 1) / (ARR + 1)
計(jì)數(shù)器溢出頻率 = 72MHz / 1 / 10 = 7200000Hz
第五步——使能更新中斷

主體代碼
第六步——配置NVIC

主體代碼
第七步——啟動(dòng)定時(shí)器

主體代碼
編程小技巧
跨文件使用變量,extern聲明變量就是告訴編譯器,這個(gè)變量在別的文件中也定義了,這個(gè)變量就是另外文件中同一個(gè)變量的引用,這個(gè)過程并沒有定義新的變量,其實(shí)頭文件中的函數(shù)聲明也是用extern實(shí)現(xiàn)的,這個(gè)extern可以省略,一般不寫。
中斷函數(shù)可以放在main.c文件中,也可以放在其他模塊化的文件中
其他問題
在TIM_TimeBaseInit函數(shù)中最后有這么一句

生成一個(gè)更新事件,立刻來重新裝載預(yù)分頻器的值和重復(fù)計(jì)數(shù)器的值
預(yù)分頻器是有一個(gè)緩沖寄存器的,我們寫的值只有在更新事件時(shí)才會(huì)起作用,所以這里為了讓值立刻起作用,在這最后手動(dòng)生成了一個(gè)更新事件,這樣預(yù)分頻器的值就有效了,但同時(shí)它導(dǎo)致了更新事件和更新中斷是同時(shí)發(fā)生的,更新中斷會(huì)置更新中斷標(biāo)志位,當(dāng)我們之后一旦初始化完了,更新中斷就會(huì)立刻進(jìn)入,這就是我們剛一上電就立刻進(jìn)中斷的原因。文章來源:http://www.zghlxwxcb.cn/news/detail-771549.html
解決方法

感謝抽出寶貴時(shí)間閱讀的各位小讀者們,創(chuàng)作不易,如果感覺有幫助的話,幫忙點(diǎn)個(gè)贊再走吧!你們的支持是我創(chuàng)作的動(dòng)力,希望能帶給大家更多優(yōu)質(zhì)的文章。文章來源地址http://www.zghlxwxcb.cn/news/detail-771549.html
到了這里,關(guān)于STM32單片機(jī)入門學(xué)習(xí)筆記——定時(shí)器TIM第一部分的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!