在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

GD32開發(fā)實(shí)戰(zhàn)指南(基礎(chǔ)篇) 第7章 定時器

嵌入式大雜燴 ? 來源:嵌入式大雜燴 ? 作者:嵌入式大雜燴 ? 2023-05-11 09:00 ? 次閱讀

開發(fā)環(huán)境:

MDK:Keil 5.30

開發(fā)板:GD32F207I-EVAL

MCU:GD32F207IK

1 定時器工作原理概述

系統(tǒng)滴答定時器一般用來提供“心跳”作用,而GD32定時器最基本功能也是定時,可以設(shè)置不同時間長度的定時。定時器除了最基本的定時功能外,定時器與GPIO有掛鉤使得它可以發(fā)揮強(qiáng)大的作用,比如可以輸出不同頻率、不同占空比的方波信號、PWM信號,同時做為輸入捕獲功能時,可以測量脈沖寬度、實(shí)現(xiàn)電容按鍵檢測等等。

GD32有三類定時器,基本定時器就是單純的定時計(jì)數(shù)器,通用定時器多了四個通道,相對應(yīng)的增加了功能,高級定時器具有基本,通用定時器的所有的功能,并且添加了其他功能。定時器的對比特性如下表所示。

定時器 定時器****0/7 定時器****1/2/3/4 定時器****8/11 定時器****9/10/12/13 定時器****5/6
類型 高級 通用(L0) 通用(L1) 通用(L2) 基本
預(yù)分頻器 16位 16位 16位 16位 16位
計(jì)數(shù)器 16位 16位 16位 16位 16位
計(jì)數(shù)模式 向上, 向下, 中央對齊 向上, 向下, 中央對齊 向上, 向下, 中央對齊 向上, 向下, 中央對齊 向上

1.1 基本定時器

TIMER5和TIMER6定時器的主要功能包括:

● 16位自動重裝載累加計(jì)數(shù)器

● 16位可編程(可實(shí)時修改)預(yù)分頻器,用于對輸入的時鐘按系數(shù)為1 ~ 65536之間的任意數(shù)值分頻

● 時鐘源只有內(nèi)部時鐘

● 在更新事件(計(jì)數(shù)器溢出)時產(chǎn)生中斷/DMA請求

總的說來,基本定時器 TIMER5和TIMER6只具備最基本的定時功能,就是累加的時鐘脈沖數(shù)超過預(yù)定值時,能觸發(fā)中斷或觸發(fā) DMA 請求。由于在芯片內(nèi)部與 DAC 外設(shè)相連,可通過觸發(fā)輸出驅(qū)動 DAC,也可以作為其他通用定時器的時鐘基準(zhǔn)。

這兩個基本定時器使用的時鐘源都是CK_TIMER驅(qū)動,時鐘源經(jīng)過 TIMERx_PSC預(yù)分頻器輸入至脈沖計(jì)數(shù)器TIMERx_CNT,基本定時器只能工作在向上計(jì)數(shù)模式,在重載寄存器TIMERx_CAR中保存的是定時器的溢出值。

工作時,脈沖計(jì)數(shù)器TIMERx_CNT由時鐘觸發(fā)進(jìn)行計(jì)數(shù),當(dāng) TIMx_CNT 的計(jì)數(shù)值 X 等于重載寄存器TIMERx_CAR中保存的數(shù)值 N 時,產(chǎn)生溢出事件,可觸發(fā)中斷或 DMA 請求。然后TIMERx_CNT的值重新被置為 0,重新向上計(jì)數(shù)。

1683729210717qoj86wq8k1

1.2 通用定時器

通用TIMERx(TIMER1/ TIMER2/ TIMER3/ TIMER4/ TIMER8/ TIMER11/ TIMER9/ TIMER10/ TIMER12/ TIMER13)定時器功能包括:

● 16位向上、向下、向上/向下自動裝載計(jì)數(shù)器;

● 16位可編程(可以實(shí)時修改)預(yù)分頻器,計(jì)數(shù)器時鐘頻率的分頻系數(shù)為1~65536之間的任意數(shù)值;

● 4個獨(dú)立通道:輸入捕獲,輸出比較,PWM生成(邊緣或中間對齊模式),單脈沖模式輸出;

● 使用外部信號控制定時器和定時器互連的同步電路;

● 如下事件發(fā)生時產(chǎn)生中斷/DMA:更新:計(jì)數(shù)器向上溢出/向下溢出,計(jì)數(shù)器初始化(通過軟件或者內(nèi)部/外部觸發(fā)), 觸發(fā)事件(計(jì)數(shù)器啟動、停止、初始化或者由內(nèi)部/外部觸發(fā)計(jì)數(shù)),輸入捕獲,輸出比較;

● 支持針對定位的增量(正交)編碼器和霍爾傳感器電路;

● 時鐘源可選:內(nèi)部時鐘,內(nèi)部觸發(fā),外部輸入,外部觸發(fā);

相比之下,通用定時器就比基本定時器復(fù)雜得多了。除了基本的定時,它主要用在測量輸入脈沖的頻率、脈沖寬與輸出 PWM 脈沖的場合,還具有編碼器的接口

16837292112783m1yhn9uky

從時鐘源方面來說,通用定時器比基本定時器多了一個選擇,它可以使用外部脈沖作為定時器的時鐘源。使用外部時鐘源時,要使用寄存器進(jìn)行觸發(fā)邊沿、濾波器帶寬的配置。如果選擇內(nèi)部時鐘源的話則與基本定時器一樣,也為CK_TIMER。但要注意的是,所有定時器(包括基本、通用和高級)使用內(nèi)部時鐘時,定時器的時鐘源都被稱為CK_TIMER,但CK_TIMER的時鐘來源并不是完全一樣的,見下圖。

1683729211828lvanongcnk

基本定時器和部分通用定時器的時鐘來源是 APB1 預(yù)分頻器的輸出。當(dāng) APB1 的分頻系數(shù)為 1 時,則CK_TIMER直接等于該APB1 預(yù)分頻器的輸出,而 APB1 的分頻系數(shù) 不 為 1 時,CK_TIMER則為APB1 預(yù)分頻器輸出的 2 倍。

如在常見的配置中,AHB=120MHz,而 APB1 預(yù)分頻器的分頻系數(shù)被配置為2,則PCLK1 剛好達(dá)到最大值60MHz,而此時APB1的分頻系數(shù)不為 1,則CK_TIMER = (AHB/2) x 2 = 120MHz。

而對于部分通用定時器和高級定時器的時鐘來源則是 APB2 預(yù)分頻器的輸出,同樣它也根據(jù)分頻系數(shù)分為兩種情況。

常見的配置中 AHB=120MHz,APB2 預(yù)分頻器的分頻系數(shù)被配置為1,此時PCLK2剛好達(dá)到最大值120MHz,而CK_TIMER則直接等于APB2分頻器的輸出,即CK_TIMER的時鐘 CK_TIMER =AHB=120MHz。

雖然這種配置下最終CK_TIMER的時鐘頻率相等,但必須清楚實(shí)質(zhì)上它們的時鐘來源是有區(qū)別的。還要強(qiáng)調(diào)的是:CK_TIMER是定時器內(nèi)部的時鐘源,但在時鐘輸出到脈沖計(jì)數(shù)器 TIMERx_CNT 前,還經(jīng)過一個預(yù)分頻器TIMERx_PSC,最終用于驅(qū)動脈沖計(jì)數(shù)器 TIMERx_CNT 的時鐘頻率根據(jù)預(yù)分頻器 TIMERx_PSC 的配置而定。

1.3 高級定時器

TIMER0和TIMER7定時器的功能包括:

● 16位向上、向下、向上/下自動裝載計(jì)數(shù)器;

● 16位可編程(可以實(shí)時修改)預(yù)分頻器,計(jì)數(shù)器時鐘頻率的分頻系數(shù)為1 ~ 65535之間的任意數(shù)值;

● 多達(dá)4個獨(dú)立通道:輸入捕獲,輸出比較,PWM生成(邊緣或中間對齊模式),單脈沖模式輸出;

● 死區(qū)時間可編程的互補(bǔ)輸出;

● 使用外部信號控制定時器和定時器互聯(lián)的同步電路;

● 允許在指定數(shù)目的計(jì)數(shù)器周期之后更新定時器寄存器的重復(fù)計(jì)數(shù)器;

● 剎車輸入信號可以將定時器輸出信號置于復(fù)位狀態(tài)或者一個已知狀態(tài);

● 如下事件發(fā)生時產(chǎn)生中斷/DMA:更新:計(jì)數(shù)器向上溢出/向下溢出,計(jì)數(shù)器初始化(通過軟件或者內(nèi)部/外部觸發(fā)),觸發(fā)事件(計(jì)數(shù)器啟動、停止、初始化或者由內(nèi)部/外部觸發(fā)計(jì)數(shù)),輸入捕獲,輸出比較,剎車信號輸入;

● 支持針對定位的增量(正交)編碼器和霍爾傳感器電路;

● 時鐘源可選:內(nèi)部時鐘,內(nèi)部觸發(fā),外部輸入,外部觸發(fā);

總的來說,TIMER0和TIMER7是兩個高級定時器,它們具有基本、通用定時器的所有功能,還具有三相 6 步電機(jī)的接口、剎車功能(break function)及用于 PWM 驅(qū)動電路的死區(qū)時間控制等,使得它非常適合于電機(jī)的控制。如圖4 所示為高級定時器結(jié)構(gòu)。

168372921242248hf2ofiaj

相比于通用定時器,主要多出了BRK、DTG 兩個結(jié)構(gòu),因而具有了死區(qū)時間的控制功能。首先,死區(qū)時間是什么呢?在 H 橋、三相橋的 PWM 驅(qū)動電路中,上下兩個橋臂的PWM 驅(qū)動信號是互補(bǔ)的,即上下橋臂輪流導(dǎo)通,但實(shí)際上為了防止出現(xiàn)上下兩個臂同時導(dǎo)通(會造成短路),在上下兩臂切換時留一小段時間,上下臂都施加關(guān)斷信號,這個上下臂都關(guān)斷的時間稱為死區(qū)時間。

高級定時器可以配置出輸出互補(bǔ)的 PWM 信號,并且在這個 PWM 信號中加入死區(qū)時間,為電機(jī)的控制提供了極大的便利。下圖中的 OCxREF 為參考信號(可理解為原信號),OCx_O和 OCx_ON 為定時器通過 GPIO 引腳輸出的 PWM 互補(bǔ)信號。

1683729212884y29ee17c9u

若不加入死區(qū)時間,當(dāng)OxCPRE出現(xiàn)下降沿,OCx_O同時輸出下降沿,OCx_ON 則同時輸出相反的上升沿,即這三個信號的跳變是同時的。

加入死區(qū)時間后,當(dāng) OxCPRE出現(xiàn)下降沿,OCx_O同時輸出下降沿,但 OCx_ON 則過了一小段延遲再輸出上升沿,OxCPRE出現(xiàn)上升沿后,OCx_O要經(jīng)過一段延時再輸出上升沿。假如 OCx_O、 OCx_ON 分別控制上、下橋臂,有了延遲后,就不容易出現(xiàn)上、下橋臂同時導(dǎo)通的情況。這個延遲時間與 PWM 信號驅(qū)動的電子器件特性相關(guān),從事工控領(lǐng)域的朋友對此應(yīng)該比較熟悉。

2 定時器計(jì)數(shù)模式

定時器可以向上計(jì)數(shù)、向下計(jì)數(shù)、向上向下雙向計(jì)數(shù)模式。

  • 向上計(jì)數(shù)模式:計(jì)數(shù)器從0計(jì)數(shù)到自動加載值(TIMERx_CAR),然后重新從0開始計(jì)數(shù)并且產(chǎn)生一個計(jì)數(shù)器溢出事件。
  • 向下計(jì)數(shù)模式:計(jì)數(shù)器從自動裝入的值(TIMERx_CAR)開始向下計(jì)數(shù)到0,然后從自動裝入的值重新開始,并產(chǎn)生一個計(jì)數(shù)器向下溢出事件。
  • 中央對齊模式(向上/向下計(jì)數(shù)):計(jì)數(shù)器從0開始計(jì)數(shù)到自動裝入的值-1,產(chǎn)生一個計(jì)數(shù)器溢出事件,然后向下計(jì)數(shù)到1并且產(chǎn)生一個計(jì)數(shù)器溢出事件;然后再從0開始重新計(jì)數(shù)。

簡單地理解三種計(jì)數(shù)模式,可以通過下面的圖形:

https://img-blog.csdn.net/20180417164424341

圖6定時器計(jì)數(shù)模式

計(jì)數(shù)器時鐘可由下列時鐘源提供:

  • 內(nèi)部時鐘(CK_TIMER);
  • 外部時鐘模式0:定時器選擇外部輸入引腳作為時鐘源;
  • 外部時鐘模式1:定時器選擇外部輸入引腳ETI作為時鐘源;

3 定時器的寄存器分析

為了深入了解 GD32 的通用寄存器,下面我們先介紹一下與我們這章的實(shí)驗(yàn)密切相關(guān)的幾個通用定時器的寄存器。首先是控制寄存器0(TIMERx_CTL0),該寄存器的各位描述如下圖。

1683729213662cigun06hll

首先我們來看看TIMERx_CTL0的最低位,也就是計(jì)數(shù)器使能位,該位必須置1,才能讓定時器開始計(jì)數(shù)。 從第 4 位 DIR 可以看出默認(rèn)的計(jì)數(shù)方式是向上計(jì)數(shù), 同時也可以向下計(jì)數(shù),第 5,6位是設(shè)置計(jì)數(shù)對齊方式的。從第 8 和第 9 位可以看出,我們還可以設(shè)置定時器的時鐘分頻因子為1,2,4。

接下來介紹第二個與我們這章密切相關(guān)的寄存器:DMA/中斷使能寄存器(TIMERx_DMAINTEN)。該寄存器是一個 16 位的寄存器,其各位描述如下圖所示。

168372921409311u5mr8m3v

這里我們同樣僅關(guān)心它的第 0 位,該位是更新中斷允許位,本章用到的是定時器的更新中斷,所以該位要設(shè)置為1。

接下來我們看第三個與我們這章有關(guān)的寄存器:預(yù)分頻寄存器(TIMERx_PSC)。該寄存器用設(shè)置對時鐘進(jìn)行分頻,然后提供給計(jì)數(shù)器,作為計(jì)數(shù)器的時鐘。該寄存器的各位描述如下圖。

1683729214532vbfc5i5igg

這里順帶介紹一下TIMERx_CNT 寄存器,該寄存器是定時器的計(jì)數(shù)器,該寄存器存儲了當(dāng)前定時器的計(jì)數(shù)值。

接著我們介紹計(jì)數(shù)器自動重載寄存器(TIMERx_CAR),該寄存器在物理上實(shí)際對應(yīng)著 2 個寄存器。一個是程序員可以直接操作的,另外一個是程序員看不到的,這個看不到的寄存器在《GD32F20x_User_Manual_EN_Rev2.4》里面被叫做影子寄存器。事實(shí)上真正起作用的是影子寄存器。根據(jù)TIMERx_CTL0寄存器中ARSE位的設(shè)置:ARSE=0 時,預(yù)裝載寄存器的內(nèi)容可以隨時傳送到影子寄存器,此時二者是連通的;而 ARSE=1 時,在每一次更新事件時,才把預(yù)裝在寄存器的內(nèi)容傳送到影子寄存器。自動重裝載寄存器的各位描述如下圖。

1683729214954twuu440c13

最后,我們要介紹的寄存器是:中斷標(biāo)志寄存器(TIMERx_INTF)。該寄存器用來標(biāo)記當(dāng)前與定時器相關(guān)的各種事件/中斷是否發(fā)生。該寄存器的各位描述如下圖。

16837292153226gzenqdxzh

1683729215675iqwup0kat8

關(guān)于這些位的詳細(xì)描述,請參考《GD32F20x_User_Manual_EN_Rev2.4》。只要對以上幾個寄存器進(jìn)行簡單的設(shè)置,我們就可以使用通用定時器了,并且可以產(chǎn)生中斷。這一章,我們將使用定時器產(chǎn)生中斷,然后在中斷服務(wù)函數(shù)里面翻轉(zhuǎn) DS1 上的電平,來指示定時器中斷的產(chǎn)生。

4 定時器代碼實(shí)現(xiàn)

接下來我們以通用定時器TIMER1為實(shí)例,來說明要經(jīng)過哪些步驟,才能達(dá)到這個要求,并產(chǎn)生中斷。

4.1 定時器配置步驟

這里我們就對每個步驟通過庫函數(shù)的實(shí)現(xiàn)方式來描述。首先要提到的是,定時器相關(guān)的庫函數(shù)主要集中在固件庫文件 gd32f20x_timer.h 和 gd32f20x_timer.c 文件中。

1) TIMER1時鐘使能。

TIMER1是掛載在 APB1 之下,所以我們通過 APB1 總線下的使能使能函數(shù)來使能 TIMER1。調(diào)用的函數(shù)是:

rcu_periph_clock_enable(RCU_TIMER1);

2) 初始化定時器參數(shù),設(shè)置自動重裝值,分頻系數(shù),計(jì)數(shù)方式等。

在庫函數(shù)中,定時器的初始化參數(shù)是通過初始化函數(shù) timer_init實(shí)現(xiàn)的:

void timer_init(uint32_t timer_periph, timer_parameter_struct *initpara)

第一個參數(shù)是確定是哪個定時器,這個比較容易理解。

第二個參數(shù)是定時器初始化參數(shù)結(jié)構(gòu)體指針,結(jié)構(gòu)體類型為 timer_parameter_struct,下面我們看看這個結(jié)構(gòu)體的定義:

/* TIMER init parameter structure definitions */
typedef struct {
    uint16_t prescaler;                         /*!< prescaler value */
    uint16_t alignedmode;                       /*!< aligned mode */
    uint16_t counterdirection;                  /*!< counter direction */
    uint32_t period;                            /*!< period value */
    uint16_t clockdivision;                     /*!< clock division value */
    uint8_t  repetitioncounter;                 /*!< the counter repetition value */
} timer_parameter_struct;

這個結(jié)構(gòu)體一共有6個成員變量。

第一個參數(shù) prescaler 是用來設(shè)置分頻系數(shù)的,剛才上面有講解。

第二個參數(shù)alignedmode是對齊模式,分為邊沿對齊模式,中央對齊向下計(jì)數(shù)置1模式,中央對齊向上計(jì)數(shù)置1模式,中央對齊上下計(jì)數(shù)置1模式。

第三個參數(shù)counterdirection是計(jì)數(shù)方向,向上計(jì)數(shù)和向下計(jì)數(shù)。

第四個參數(shù)period是設(shè)置自動重載計(jì)數(shù)周期值,這在前面也已經(jīng)講解過。

第五個參數(shù)clockdivision是用來設(shè)置時鐘分頻因子。

第六個參數(shù)repetitioncounter是重復(fù)計(jì)數(shù)器。

針對 TIMER1初始化范例代碼格式:

timer_parameter_struct timer_initpara;

/* TIMER1 configuration */
timer_initpara.prescaler         = 119;
timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection  = TIMER_COUNTER_UP;
timer_initpara.period            = 999;
timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TIMER1, &timer_initpara);

3) 設(shè)置TIMERx_DMAINTEN允許更新中斷。

因?yàn)槲覀円褂?TIMER1的更新中斷, 寄存器的相應(yīng)位便可使能更新中斷。 在庫函數(shù)里面定時器中斷使能是通過 timer_interrupt_enable()函數(shù)來實(shí)現(xiàn)的:

void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt)

第一個參數(shù)是選擇定時器號,這個容易理解,取值為TIMERx(x=0..13)。

第二個參數(shù)非常關(guān)鍵,是用來指明我們使能的定時器中斷的類型,定時器中斷的類型有很多種,包括TIMER_INT_UP, TIMER_INT_TRG等等。

例如我們要使能 TIMER1 的更新中斷,格式為:

timer_interrupt_enable(TIMER1,TIMER_INT_UP);

4) TIMER1中斷優(yōu)先級設(shè)置。

在定時器中斷使能之后,因?yàn)橐a(chǎn)生中斷,必不可少的要設(shè)置 NVIC 相關(guān)寄存器,設(shè)置中斷優(yōu)先級。中斷優(yōu)先級配置代碼如下:

//TIMER1 interrupt setting, preemptive priority 0, sub-priority 3
nvic_irq_enable(TIMER1_IRQn, 0, 3);

5) 允許 TIMER1工作,也就是使能 TIMER1。

光配置好定時器還不行,沒有開啟定時器,照樣不能用。我們在配置完后要開啟定時器,通過 TIMER_CTL0的TIMER_CTL0_CEN位來設(shè)置。在固件庫里面使能定時器的函數(shù)是通過 timer_enable()函數(shù)來實(shí)現(xiàn)的:

void timer_enable(uint32_t timer_periph)

這個函數(shù)非常簡單,比如我們要使能定時器1,方法為:

/* TIMER1 enable */
timer_enable(TIMER1);

6) 編寫中斷服務(wù)函數(shù)。

在最后,還是要編寫定時器中斷服務(wù)函數(shù),通過該函數(shù)來處理定時器產(chǎn)生的相關(guān)中斷。在中斷產(chǎn)生后,通過狀態(tài)寄存器的值來判斷此次產(chǎn)生的中斷屬于什么類型。然后執(zhí)行相關(guān)的操作,我們這里使用的是更新(溢出)中斷,所以在中斷標(biāo)志寄存器TIMERx_INTF的最低位。在處理完中斷之后應(yīng)該向TIMERx_INTF最低位寫 0,來清除該中斷標(biāo)志。

在固件庫函數(shù)里面,用來讀取中斷狀態(tài)寄存器的值判斷中斷類型的函數(shù)是:

FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t int_flag)

該函數(shù)的作用是,判斷定時器 TIMERx 的中斷類型是否發(fā)生中斷。比如,我們要判斷定時器1是否發(fā)生更新(溢出)中斷,方法為:

if ( timer_interrupt_flag_get(TIMER1 , TIMER_INT_UP) != RESET ) {}

固件庫中清除中斷標(biāo)志位的函數(shù)是:


該函數(shù)的作用是,清除定時器 TIMERx 的中斷標(biāo)志位。 使用起來非常簡單,比如我們在TIMER1 的溢出中斷發(fā)生后,我們要清除中斷標(biāo)志位,方法是:

timer_interrupt_flag_clear(TIMER1 , TIMER_INT_UP);

這里需要說明一下,固件庫還提供了兩個函數(shù)用來判斷定時器狀態(tài)以及清除定時器狀態(tài)標(biāo)志位的函數(shù) timer_flag_get()和timer_flag_clear(),他們的作用和前面兩個函數(shù)的作用類似。只是在 timer_interrupt_flag_get()函數(shù)中會先判斷這種中斷是否使能,使能了才去判斷中斷標(biāo)志位,而timer_flag_get()直接用來判斷狀態(tài)標(biāo)志位。

通過以上幾個步驟,我們就可以達(dá)到我們的目的了,使用通用定時器的更新中斷,來控制LED的亮滅。

最后定時器核心配置代碼如下:

/*
    brief      configure the TIMER peripheral
    param[in]  tim_typedef_enum TIM_id, uint16_t prescaler, uint32_t period, uint8_t prePriority, uint8_t subPriority
    param[out] none
    retval     none
  */
void timx_init(tim_typedef_enum TIM_id, uint16_t prescaler, uint32_t period, uint8_t prePriority, uint8_t subPriority)
{
    /* TIMER configuration: generate PWM signals with different duty cycles */
    timer_parameter_struct timer_initpara;

	  //Enable TIMER clock
    rcu_periph_clock_enable(TIM_CLK[TIM_id]);

    timer_deinit(TIM[TIM_id]);

    /* TIMER configuration */
    timer_initpara.prescaler         = prescaler;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = period;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_init(TIM[TIM_id], &timer_initpara);

    timer_interrupt_enable(TIM[TIM_id], TIMER_INT_UP);	/* Enable timer interrupt */ 
	
    //TIMER interrupt setting, preemptive priority 0, sub-priority 3
    nvic_irq_enable(TIM_IRQn[TIM_id], prePriority, subPriority);	

    /* TIMER enable */
    timer_enable(TIM[TIM_id]);

    rcu_periph_clock_disable(TIM_CLK[TIM_id]);/* disable timer clock*/ 
}

中斷代碼如下:

/**
  * @brief  This function handles TIMER1 interrupt request.
  * @param  None
  * @retval None
  */
void TIMER1_IRQHandler(void)
{
    if ( timer_interrupt_flag_get(TIMER1 , TIMER_INT_UP) != RESET ) 
    {
        time++;
        timer_interrupt_flag_clear(TIMER1 , TIMER_INT_UP);
    }
}

主函數(shù)如下:

/*
    brief      main function
    param[in]  none
    param[out] none
    retval     none
*/
int main(void)
{
    //systick init
    sysTick_init();

    /* configure the TIMER peripheral */
    timx_init(T1, 119, 999, 0, 1);

    /* configure LED1 GPIO port */
    led_init(LED1);

    /* configure LED2 GPIO port */
    led_init(LED2);

    /* configure LED3 GPIO port */
    led_init(LED3);

    /* configure LED4 GPIO port */
    led_init(LED4);

    //Enable TIMER1 clock
    rcu_periph_clock_enable(RCU_TIMER1);

    while(1) 
    {
        if ( time == 1000 ) /* 1000 * 1 ms = 1s 時間到 */
        {
            time = 0;
            /* LED 取反 */
            led_toggle(LED1); 
            led_toggle(LED2); 
            led_toggle(LED3); 
            led_toggle(LED4); 
        }
    }
}

接下來分析下定時器溢出時間。

4.2 定時器溢出時間計(jì)算

1.定時器的時鐘源

定時器時鐘CK_TIMER經(jīng) APB1 預(yù)分頻器后分頻提供,如果 APB1 預(yù)分頻系數(shù)等于 1,則頻率不變,否則頻率乘以 2,庫函數(shù)中 APB1 預(yù)分頻的系數(shù)是 2,即 PCLK1=60M,所以定時器時鐘 CK_TIMER=60*2=120M。

其時鐘初始化代碼在system_stm32f20x.c定義的,這里使用的默認(rèn)配置,具體時鐘設(shè)置函數(shù)是system_clock_120m_hxtal(),代碼如下:

/*!
    \\brief      configure the system clock to 120M by PLL which selects HXTAL(8M) as its clock source
    \\param[in]  none
    \\param[out] none
    \\retval     none
*/
static void system_clock_120m_hxtal(void)
{
    uint32_t timeout = 0U;
    uint32_t stab_flag = 0U;

    /* enable HXTAL */
    RCU_CTL |= RCU_CTL_HXTALEN;

    /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
    do {
        timeout++;
        stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
    } while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));

    /* if fail */
    if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)) {
        while(1) {
        }
    }

    /* HXTAL is stable */
    /* AHB = SYSCLK */
    RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
    /* APB2 = AHB/1 */
    RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
    /* APB1 = AHB/2 */
    RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;

    /* CK_PLL = (CK_PREDIV0) * 10 = 120 MHz */
    RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL);
    RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL10);

    /* CK_PREDIV0 = (CK_HXTAL) / 5 * 12 /5 = 12 MHz */
    RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
    RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL12 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV5);

    /* enable PLL1 */
    RCU_CTL |= RCU_CTL_PLL1EN;
    /* wait till PLL1 is ready */
    while((RCU_CTL & RCU_CTL_PLL1STB) == 0U) {
    }

    /* enable PLL */
    RCU_CTL |= RCU_CTL_PLLEN;

    /* wait until PLL is stable */
    while(0U == (RCU_CTL & RCU_CTL_PLLSTB)) {
    }

    /* select PLL as system clock */
    RCU_CFG0 &= ~RCU_CFG0_SCS;
    RCU_CFG0 |= RCU_CKSYSSRC_PLL;

    /* wait until PLL is selected as system clock */
    while(0U == (RCU_CFG0 & RCU_SCSS_PLL)) {
    }
}

重點(diǎn)關(guān)注以下代碼:

/* APB1 = AHB/2 */
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;

而RCU_APB1_CKAHB_DIV2的定義如下:

#define RCU_APB1_CKAHB_DIV2             CFG0_APB1PSC(4)                     /*!< APB1 prescaler select CK_AHB/2 */

因此最終到TIMER1上的時鐘為120Mhz。

2.定時器頻率

TIMER1上的時鐘為120Mhz,定時器分頻系數(shù)為119,因此TIMER1的頻率為

CK_CNT=TIMERxCLK/(PSC+1)=1MHz

3.自動重裝載值

自動重裝載寄存器 TIMERx_CAR是一個 16 位的寄存器,這里面裝著計(jì)數(shù)器能計(jì)數(shù)的最大數(shù)值。當(dāng)計(jì)數(shù)到這個值的時候,如果使能了中斷的話,定時器就產(chǎn)生溢出中斷,這里設(shè)置的是999。

完整配置參數(shù)如下:

Prtscaler (定時器分頻系數(shù)) : 119

Counter Mode(計(jì)數(shù)模式) :Up(向上計(jì)數(shù)模式)

Counter Period(自動重裝載值) : 999

CKD(時鐘分頻因子) : No Division 不分頻

定時器溢出時間:

Tout=1/(Tclk/psc) *(arr+1)

本文設(shè)置參數(shù)為: arr=999 psc=119 Tclk=120Mhz ,因此最終的溢出時間如下:

Tout=1/(120MHz /(119+1)) *(999+1)=1ms

值得注意的是,自動重裝載值計(jì)算溢出時間要加1,這是因?yàn)樽詣又匮b載寄存器 TIMERx_CAR是從0開始計(jì)數(shù)的。

5 實(shí)現(xiàn)現(xiàn)象

將編譯好的程序下載到看板子中,可以看到LED不停閃爍。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • mcu
    mcu
    +關(guān)注

    關(guān)注

    146

    文章

    17668

    瀏覽量

    357501
  • 定時器
    +關(guān)注

    關(guān)注

    23

    文章

    3271

    瀏覽量

    116520
  • 開發(fā)板
    +關(guān)注

    關(guān)注

    25

    文章

    5374

    瀏覽量

    100557
  • Cortex-M
    +關(guān)注

    關(guān)注

    2

    文章

    229

    瀏覽量

    30129
  • GD32
    +關(guān)注

    關(guān)注

    7

    文章

    418

    瀏覽量

    24966
收藏 人收藏

    評論

    相關(guān)推薦

    GD32對Timer定時器原理的詳細(xì)講解

    GD32 Timr定時器看起來比較復(fù)雜啊。一看GD32E10x 的SPEC:一個高級定時器,三個通用定時器,還有一個基本
    的頭像 發(fā)表于 04-22 17:02 ?1.7w次閱讀
    <b class='flag-5'>GD32</b>對Timer<b class='flag-5'>定時器</b>原理的詳細(xì)講解

    GD32開發(fā)實(shí)戰(zhàn)指南(基礎(chǔ)) 1 開發(fā)環(huán)境搭建

    設(shè)計(jì)的GD32F207I-EVAL開發(fā)板。 GD32F207I-EVAL開發(fā)板使用 GD32F207IK作為主控制
    的頭像 發(fā)表于 05-07 23:35 ?1.2w次閱讀
    <b class='flag-5'>GD32</b><b class='flag-5'>開發(fā)</b><b class='flag-5'>實(shí)戰(zhàn)</b><b class='flag-5'>指南</b>(基礎(chǔ)<b class='flag-5'>篇</b>) <b class='flag-5'>第</b>1<b class='flag-5'>章</b> <b class='flag-5'>開發(fā)</b>環(huán)境搭建

    GD32開發(fā)實(shí)戰(zhàn)指南(基礎(chǔ)) 5 跳動的心臟-Systick

    Cortex-M的內(nèi)核中包含Systick定時器了,只要是Cortex-M系列的MCU就會有Systick,因此這是通用的,下面詳細(xì)分析。
    的頭像 發(fā)表于 05-10 09:00 ?7487次閱讀
    <b class='flag-5'>GD32</b><b class='flag-5'>開發(fā)</b><b class='flag-5'>實(shí)戰(zhàn)</b><b class='flag-5'>指南</b>(基礎(chǔ)<b class='flag-5'>篇</b>) <b class='flag-5'>第</b>5<b class='flag-5'>章</b>  跳動的心臟-Systick

    GD32開發(fā)實(shí)戰(zhàn)指南(基礎(chǔ)) 8 定時器

    Modulation” 的縮寫,簡稱脈寬調(diào)制,是利用微處理的數(shù)字輸出來對模擬電路進(jìn)行控制的一種非常有效的技術(shù)。簡單一點(diǎn),就是對脈沖寬度的控制。 GD32定時器除了 TIMER5 和 6(基本
    的頭像 發(fā)表于 05-12 22:14 ?8501次閱讀
    <b class='flag-5'>GD32</b><b class='flag-5'>開發(fā)</b><b class='flag-5'>實(shí)戰(zhàn)</b><b class='flag-5'>指南</b>(基礎(chǔ)<b class='flag-5'>篇</b>) <b class='flag-5'>第</b>8<b class='flag-5'>章</b> <b class='flag-5'>定時器</b>

    GD32開發(fā)實(shí)戰(zhàn)指南(基礎(chǔ)) 14 內(nèi)部溫度傳感

    GD32 有一個內(nèi)部的溫度傳感,可以用來測量 CPU 及周圍的溫度(TA)。該溫度傳感在內(nèi)部和 ADCx_IN16 輸入通道相連接,此通道把傳感輸出的電壓轉(zhuǎn)換成數(shù)字值。溫度傳感
    的頭像 發(fā)表于 05-17 08:58 ?5871次閱讀
    <b class='flag-5'>GD32</b><b class='flag-5'>開發(fā)</b><b class='flag-5'>實(shí)戰(zhàn)</b><b class='flag-5'>指南</b>(基礎(chǔ)<b class='flag-5'>篇</b>) <b class='flag-5'>第</b>14<b class='flag-5'>章</b> 內(nèi)部溫度傳感<b class='flag-5'>器</b>

    GD32開發(fā)實(shí)戰(zhàn)指南(基礎(chǔ)) 15 低功耗

    GD32的工作電壓(VDD)為2.0~3.6V。通過內(nèi)置的電壓調(diào)節(jié)提供所需的1.8V電源。當(dāng)主電源VDD掉電后,通過VBAT腳為實(shí)時時鐘(RTC)和備份寄存提供電源。
    的頭像 發(fā)表于 05-17 08:59 ?8610次閱讀
    <b class='flag-5'>GD32</b><b class='flag-5'>開發(fā)</b><b class='flag-5'>實(shí)戰(zhàn)</b><b class='flag-5'>指南</b>(基礎(chǔ)<b class='flag-5'>篇</b>) <b class='flag-5'>第</b>15<b class='flag-5'>章</b> 低功耗

    GD32開發(fā)實(shí)戰(zhàn)指南(基礎(chǔ)) 16 RTC

    運(yùn)行的定時器。從定時器的角度來說,相對于通用定時器 TIMER 外設(shè),它十分簡單,只有很純粹的計(jì)時功能(當(dāng)然,可以觸發(fā)中斷);但從掉電還繼續(xù)運(yùn)行的角度來說,它卻是 GD32中唯一一個具
    的頭像 發(fā)表于 05-18 22:14 ?7736次閱讀
    <b class='flag-5'>GD32</b><b class='flag-5'>開發(fā)</b><b class='flag-5'>實(shí)戰(zhàn)</b><b class='flag-5'>指南</b>(基礎(chǔ)<b class='flag-5'>篇</b>) <b class='flag-5'>第</b>16<b class='flag-5'>章</b> RTC

    GD32開發(fā)實(shí)戰(zhàn)指南(基礎(chǔ)) 17 看門狗

    開發(fā)環(huán)境: MDK:Keil 5.30 開發(fā)板:GD32F207I-EVAL MCU:GD32F207IK GD32 有兩個看門狗, 一個是
    的頭像 發(fā)表于 06-03 16:00 ?1.2w次閱讀
    <b class='flag-5'>GD32</b><b class='flag-5'>開發(fā)</b><b class='flag-5'>實(shí)戰(zhàn)</b><b class='flag-5'>指南</b>(基礎(chǔ)<b class='flag-5'>篇</b>) <b class='flag-5'>第</b>17<b class='flag-5'>章</b> 看門狗

    【圖書分享】《STM32庫開發(fā)實(shí)戰(zhàn)指南

    庫函數(shù)開發(fā)小結(jié) 10 DMA——為CPU減負(fù) 11 ADC實(shí)驗(yàn)(DMA方式) 12
    發(fā)表于 03-13 17:01

    定時器的工作原理

    標(biāo)準(zhǔn)庫3.5實(shí)現(xiàn):《嵌入式-STM32開發(fā)指南》第二部分 基礎(chǔ) - 4 定時器4.1定時器
    發(fā)表于 08-19 07:49

    GD32 MCU原理及固件庫開發(fā)指南》+讀后感

    2介紹GD32 MCU快速入門與開發(fā)平臺搭建的方法,包括對軟硬件開發(fā)平臺、調(diào)試工具、GD32
    發(fā)表于 06-06 21:52

    GD32-Colibri-F207實(shí)驗(yàn)板定時器1停止

    GD32-Colibri-F207實(shí)驗(yàn)板定時器1停止,很好的GD32資料,快來學(xué)習(xí)吧。
    發(fā)表于 04-21 14:24 ?11次下載

    《嵌入式-STM32開發(fā)指南》第二部分 基礎(chǔ) - 4 定時器(HAL庫)

    《嵌入式-STM32開發(fā)指南》第二部分 基礎(chǔ) - 4 定時器(HAL庫)
    發(fā)表于 12-05 14:51 ?15次下載
    《嵌入式-STM32<b class='flag-5'>開發(fā)指南</b>》第二部分 基礎(chǔ)<b class='flag-5'>篇</b> - <b class='flag-5'>第</b>4<b class='flag-5'>章</b>  <b class='flag-5'>定時器</b>(HAL庫)

    GD32開發(fā)實(shí)戰(zhàn)指南(基礎(chǔ)) 19 程序加密

    GD32通過讀取芯片唯一ID號來實(shí)現(xiàn)程序的保護(hù),防止被抄襲。96位的產(chǎn)品唯一身份標(biāo)識所提供的參考號碼對任意一個GD32微控制
    的頭像 發(fā)表于 05-20 09:10 ?4473次閱讀
    <b class='flag-5'>GD32</b><b class='flag-5'>開發(fā)</b><b class='flag-5'>實(shí)戰(zhàn)</b><b class='flag-5'>指南</b>(基礎(chǔ)<b class='flag-5'>篇</b>) <b class='flag-5'>第</b>19<b class='flag-5'>章</b> 程序加密

    GD32 Timer定時器周期時間計(jì)算公式

    有小伙伴反饋GD32 Timer定時器的周期時間不知如何計(jì)算,今天就來安排。
    的頭像 發(fā)表于 01-22 09:53 ?3201次閱讀
    <b class='flag-5'>GD32</b> Timer<b class='flag-5'>定時器</b>周期時間計(jì)算公式
    主站蜘蛛池模板: h在线国产| 午夜寂寞影视 | 欧美三级不卡在线观线看高清 | 丁香激情六月天 | 天天搞夜夜操 | 久久免费久久 | 久久久久久青草大香综合精品 | 激情六月网 | 男啪女色黄无遮挡免费观看 | 色又色| 天堂资源8中文最新版在线 天堂资源地址在线 | 午夜免费体验 | 高清毛片一区二区三区 | 亚洲大香伊人蕉在人依线 | 免费看国产一级片 | 黄网站在线观看视频 | 久久国产乱子伦精品免费午夜 | 天天色天天摸 | 国产视频一区二区在线观看 | 亚洲国产成人在线 | 就是操就是干 | 四虎影视永久地址 | 日本xxxxx黄区免费看动漫 | 天天视频官网天天视频在线 | 天天干狠狠插 | 国产综合视频 | 午夜免费理论片在线看 | 四虎在线观看免费永久 | 视频在线免费 | 狠狠色成色综合网 | 国产你懂的在线 | 国产理论视频 | 色视频在线观看完整免费版 | 黄h网站| 美女视频永久黄网站免费观看国产 | 爆操极品美女 | 婷婷亚洲综合一区二区 | 天天射网站| 伊人网站在线 | 黄色三级三级三级免费看 | 欧美黄色大片免费观看 |