5.1.TIMER 基礎(chǔ)知識
TIMER分高級定時器,通用定時器L0,L1,L2和基本定時器。

5.2.硬件連接說明
TIMER 屬于片內(nèi)外設(shè),對于外部硬件設(shè)計(jì),只需要單獨(dú)IO口外接信號線即可。
5.3.GD32 TIMER 外設(shè)原理簡介(以 GD32F30X 的高級定時器為例)
GD32 TIMER 主要特性
? 總通道數(shù): 4;
? 計(jì)數(shù)器寬度: 16位;
? 定時器時鐘源可選:內(nèi)部時鐘,內(nèi)部觸發(fā),外部輸入,外部觸發(fā);
? 多種計(jì)數(shù)模式:向上計(jì)數(shù),向下計(jì)數(shù)和中央計(jì)數(shù);
? 正交編碼器接口:用來追蹤運(yùn)動和分辨旋轉(zhuǎn)方向和位置;
? 可編程的預(yù)分頻器: 16位。運(yùn)行時可以被改變;
? 每個通道可配置:輸入捕獲模式,輸出比較模式,可編程的PWM模式,單脈沖模式;
? 可編程的死區(qū)時間;
? 自動重裝載功能;
? 可編程的計(jì)數(shù)器重復(fù)功能;
? 中止輸入功能;
? 中斷輸出和DMA請求:更新事件,觸發(fā)事件,比較/捕獲事件和中止事件;
? 多個定時器的菊鏈?zhǔn)沟靡粋€定時器可以同時啟動多個定時器;
? 定時器的同步允許被選擇的定時器在同一個時鐘周期開始計(jì)數(shù);
? 定時器主/從模式控制器。
TIMER 結(jié)構(gòu)框圖介紹

5.4.軟件配置說明
定時中斷 TIMER4
通用定時器L0(TIMER1/2/3/4) 是4通道定時器,支持輸入捕獲,輸出比較,產(chǎn)生PWM信號控制電機(jī)和電源管理。通用定時器L0計(jì)數(shù)器是16位無符號計(jì)數(shù)器。通用定時器L0是可編程的,可以被用來計(jì)數(shù),其外部事件可以驅(qū)動其他定時器。
這一章,將使用定時器產(chǎn)生中斷,然后在中斷服務(wù)函數(shù)里面翻轉(zhuǎn) LED上的電平,來指示定時器中斷的產(chǎn)生。接下來我們以通用定時器 TIMER4 為實(shí)例,來說明要經(jīng)過哪些步驟,才能達(dá)到這個要 求,并產(chǎn)生中斷。定時器配置步驟如下:
1)TIMER4 時鐘使能
rcu_periph_clock_enable(RCU_TIMER4);
2) 初始化定時器參數(shù),設(shè)置自動重裝值,分頻系數(shù),計(jì)數(shù)方式等
在庫函數(shù)中,定時器的初始化參數(shù)是通過初始化函數(shù)timer_parameter_struct 實(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 struct definitions */ typedef struct { uint16_t prescaler; /*!
針對 TIMR4 初始化范例代碼格式
timer_initpara.prescaler = 5999; //30M/6000 =500Hz timer_initpara.alignedmode = TIMER_COUNTER_EDGE; timer_initpara.counterdirection = TIMER_COUNTER_UP; timer_initpara.period = 4000-1; //800ms timer_initpara.clockdivision = TIMER_CKDIV_DIV1; timer_init(TIMER4, &timer_initpara);
對于定時器定時周期的計(jì)算,設(shè) TIMER4 的經(jīng)過總線分頻后得到的時鐘為 30MHz,通過預(yù)分頻 5999,得到 TIMER4 每個計(jì) 數(shù)的時鐘為 1/(30MHz / (5999+1)) =0.2ms,4000 得到的周期為 0.2ms *4000 =800ms
3)設(shè)置 TIMER 允許更新中斷
因?yàn)槲覀円褂?TIMER4 的更新中斷,寄存器的相應(yīng)位便可使能更新中斷。在庫函數(shù)里面定時器中斷使能是通過timer_interrupt_enable函數(shù)來實(shí)現(xiàn)的:
void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt);
第一個參數(shù)是選擇定時器號,這個容易理解。
第二個參數(shù)非常關(guān)鍵,是用來指明我們使能的定時器中斷的類型。
4) TIMER4 中斷優(yōu)先級設(shè)置
在定時器中斷使能之后,因?yàn)橐a(chǎn)生中斷,必不可少的要設(shè)置 NVIC 相關(guān)寄存器,設(shè)置中斷優(yōu)先級。通過nvic_irq_enable 函數(shù)實(shí)現(xiàn)中斷優(yōu)先級的設(shè)置。
針對 TIMR4 初始化范例代碼格式
nvic_irq_enable(TIMER4_IRQn, 1, 1);
5)允許 TIMER工作,也就是使能 TIMER
光配置好定時器還不行,沒有開啟定時器,照樣不能用。我們在配置完后要開啟定時器,在固件庫里面使能定時器的函數(shù)是通過timer_enable函數(shù)來實(shí)現(xiàn)的
void timer_enable(uint32_t timer_periph)
這個函數(shù)非常簡單,比如我們要使能TIMER4,方法為:
timer_enable(TIMER4);
6)編寫中斷服務(wù)函數(shù)
在最后,還是要編寫定時器中斷服務(wù)函數(shù),通過該函數(shù)來處理定時器產(chǎn)生的相關(guān)中斷。中斷產(chǎn)生后,通過狀態(tài)寄存器的值來判斷此次產(chǎn)生的中斷屬于什么類型。然后執(zhí)行相關(guān)的操作,我們這里使用的是更新(溢出)中斷,在處理完中斷之后應(yīng)來清除該中斷標(biāo)志。
在固件庫函數(shù)里面,用來讀取中斷狀態(tài)寄存器的值判斷中斷類型的函數(shù)是:
FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t interrupt)
該函數(shù)的作用是,判斷定時器 TIMER 的中斷類型,并判斷是否發(fā)生中斷。
針對 TIMR4 中斷服務(wù)函數(shù)范例代碼:
void TIMER4_IRQHandler(void) { if(SET == timer_interrupt_flag_get(TIMER4, TIMER_INT_UP)){ /* clear channel 0 interrupt bit */ timer_interrupt_flag_clear(TIMER4, TIMER_INT_UP); gd_eval_led_toggle(LED2); } }
PWM 輸出 TIMER0
高級定時器(TIMER0和TIMER7)是四通道定時器,支持輸入捕獲和輸出比較。可以產(chǎn)生PWM信號控制電機(jī)和電源管理。高級定時器含有一個16位無符號計(jì)數(shù)器。高級定時器是可編程的,可以用來計(jì)數(shù),其外部事件可以驅(qū)動其他定時器。高級定時器包含了一個死區(qū)時間插入模塊,非常適合電機(jī)控制。
本章,我們使用的是 TIMER0的通道0 輸出 PWM(脈沖寬度調(diào)制)。
下面我們介紹通過庫函數(shù)來配置該功能的步驟:
(1)開啟 TIMER0 和 GPIO 時鐘,配置 PA8復(fù)用功能輸出。
rcu_periph_clock_enable(RCU_TIMER0); rcu_periph_clock_enable(RCU_GPIOA); gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8);
這里還需要說明一下, 對于定時器通道的引腳關(guān)系,引腳的IO口

這里補(bǔ)充說明下關(guān)于TIMER的相關(guān)GPIO口的命名
TIMERx_CHx : 定時器通道x
TIMERx_CHx_ON :定時器反向通道
TIMERx_BRKIN :剎車引腳
TIMERx_ETI:外部時鐘輸入
(2)初始化 TIMER0 ,設(shè)置 TIMER0 的預(yù)分頻和周期等參數(shù), ,在上一節(jié)定時器中斷章節(jié)我們已經(jīng)有講解,這里就不詳細(xì)講解,調(diào)用的格式為
timer_initpara.prescaler = 5999; timer_initpara.alignedmode = TIMER_COUNTER_EDGE; timer_initpara.counterdirection = TIMER_COUNTER_UP; timer_initpara.period = 4000; timer_initpara.clockdivision = TIMER_CKDIV_DIV1; timer_initpara.repetitioncounter = 0; timer_init(TIMER0, &timer_initpara);
3)設(shè)置 TIMER0_CH0 的 PWM 模式, 使能 TIMER0 的 CH0 輸出。 在庫函數(shù)中, PWM 通道設(shè)置是通過函數(shù)timer_channel_output_config來設(shè)置的
void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_oc_parameter_struct* ocpara)
我們直接來看看結(jié)構(gòu)體timer_oc_parameter_struct的定義:
typedef struct { uint16_t outputstate; /*!< channel output state */ uint16_t outputnstate; /*!< channel complementary output state */ uint16_t ocpolarity; /*!< channel output polarity */ uint16_t ocnpolarity; /*!< channel complementary output polarity */ uint16_t ocidlestate; /*!< idle state of channel output */ uint16_t ocnidlestate; /*!< idle state of channel complementary output */ }timer_oc_parameter_struct;
針對 TIMR0 CH0 初始化范例代碼格式
/* CH0, CH1 and CH2 configuration in PWM mode */ timer_ocinitpara.outputstate = TIMER_CCX_ENABLE; timer_ocinitpara.outputnstate = TIMER_CCXN_DISABLE; timer_ocinitpara.ocpolarity = TIMER_OC_POLARITY_HIGH; timer_ocinitpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH; timer_ocinitpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW; timer_ocinitpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; timer_channel_output_config(TIMER0, TIMER_CH_0, &timer_ocinitpara);
4)設(shè)置PWM輸出以及脈沖寬度占空比
timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_0, 2000); timer_channel_output_mode_config(TIMER0, TIMER_CH_0, TIMER_OC_MODE_PWM0); timer_channel_output_shadow_config(TIMER0, TIMER_CH_0, TIMER_OC_SHADOW_DISABLE); timer_primary_output_config(TIMER0,ENABLE);
5)使能 TIMER0
在完成以上設(shè)置了之后,我們需要使能 TIMER0。使能 TIMER0 的方法前面已經(jīng)講解過:
timer_enable(TIMER0);
通過以上 5 個步驟,我們就可以控制 TIMER0的 CH0 輸出 PWM 波了。這里特別提醒一下大家,高級定時器雖然和通用定時器類似,但是高級定時器要想輸出 PWM,必須多額外加一條函數(shù)
void timer_primary_output_config(uint32_t timer_periph, ControlStatus newvalue);
輸入捕獲 TIMER2
通用定時器L0(TIMER1/2/3/4) 是4通道定時器,支持輸入捕獲,輸出比較,產(chǎn)生PWM信號控制電機(jī)和電源管理。通用定時器L0計(jì)數(shù)器是16位無符號計(jì)數(shù)器。通用定時器L0是可編程的,可以被用來計(jì)數(shù),其外部事件可以驅(qū)動其他定時器。
本章要實(shí)現(xiàn)通過輸入捕獲,來獲取TIMER2_CH0(PA6)上面的下降沿,下面我們介紹庫函數(shù)配置上述功能輸入捕獲的步驟:
1)開啟 TIMER2 時鐘,配置 PA6為復(fù)用功能,并開啟上拉電阻。
rcu_periph_clock_enable(RCU_TIMER2); rcu_periph_clock_enable(RCU_GPIOA); gpio_init(GPIOA, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_6); //INCUPTURE -TIMER2
跟上一講 PWM 輸出類似,這里我們使用的是定時器2的通道 0,所以我們從對應(yīng)的數(shù)據(jù)手冊可以查看到對應(yīng)的 IO 口為 PA6:

2) 初始化定時器參數(shù),設(shè)置自動重裝值, 分頻系數(shù),計(jì)數(shù)方式等
/* TIMER2 configuration */ timer_initpara.prescaler = 5999; timer_initpara.alignedmode = TIMER_COUNTER_EDGE; timer_initpara.counterdirection = TIMER_COUNTER_UP; timer_initpara.period = 4000; timer_initpara.clockdivision = TIMER_CKDIV_DIV1; timer_init(TIMER2, &timer_initpara);
3)設(shè)置 TIMER2 的輸入捕獲參數(shù),開啟輸入捕獲
庫函數(shù)是通過 timer_input_capture_config 函數(shù)來初始化輸入比較參數(shù)的: timer_input_capture_config(TIMER2,TIMER_CH_0,&timer_icinitpara);
同樣,我們來看看參數(shù)設(shè)置結(jié)構(gòu)體 TIM_ICInitTypeDef 的定義:
typedef struct { uint16_t icpolarity; /*!< channel input polarity */ uint16_t icselection; /*!< channel input mode selection */ uint16_t icprescaler; /*!< channel input capture prescaler */ uint16_t icfilter; /*!< channel input capture filter control */ }timer_ic_parameter_struct;
我們的配置代碼是:
/* initialize TIMER channel input parameter struct */ timer_channel_input_struct_para_init(&timer_icinitpara); /* TIMER2 CH0 input capture configuration */ timer_icinitpara.icpolarity = TIMER_IC_POLARITY_RISING; timer_icinitpara.icselection = TIMER_IC_SELECTION_DIRECTTI; timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1; timer_icinitpara.icfilter = 0x0; timer_input_capture_config(TIMER2,TIMER_CH_0,&timer_icinitpara);
4) 使能捕獲中斷和NVIC
timer_interrupt_enable(TIMER2,TIMER_INT_CH0); nvic_irq_enable(TIMER2_IRQn, 1, 1);
5) 編寫中斷服務(wù)函數(shù)
void TIMER2_IRQHandler(void){……}
6) 使能定時器
timer_enable(TIMER2);
通過以上 6 步設(shè)置,定時器 2 的通道 0 就可以開始輸入捕獲了
外部時鐘輸入 TIMER1
通用定時器L0(TIMER1/2/3/4) 是4通道定時器,支持輸入捕獲,輸出比較,產(chǎn)生PWM信號控制電機(jī)和電源管理。通用定時器L0計(jì)數(shù)器是16位無符號計(jì)數(shù)器。通用定時器L0是可編程的,可以被用來計(jì)數(shù),其外部事件可以驅(qū)動其他定時器。
本章要實(shí)現(xiàn)使用TIMER1 PA0 作為時鐘輸入引腳,配置流程:
(1)使能GPIO,TIMER 時鐘和GPIO口復(fù)用配置
rcu_periph_clock_enable(RCU_GPIOA); rcu_periph_clock_enable(RCU_AF); rcu_periph_clock_enable(RCU_TIMER1); gpio_init(GPIOA,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_50MHZ,GPIO_PIN_0);

(2)通過查看數(shù)據(jù)手冊,可以看到TIMER1_CH0_ETI,根據(jù)前面所講,是可以支持外部時鐘輸入的。
TIMER的結(jié)構(gòu)體,初始化定時器參數(shù),設(shè)置自動重裝值, 分頻系數(shù),計(jì)數(shù)方式等
//ETI timer_initpara.prescaler = 1; // 2 分頻 timer_initpara.alignedmode = TIMER_COUNTER_EDGE; timer_initpara.counterdirection = TIMER_COUNTER_UP; timer_initpara.period = 65535; timer_initpara.clockdivision = TIMER_CKDIV_DIV1; timer_initpara.repetitioncounter = 0; timer_init(TIMER1,&timer_initpara); timer_enable(TIMER1);
(3)配置TIMER的時鐘來源和時鐘源處理的配置
timer_input_trigger_source_select(TIMER1,TIMER_SMCFG_TRGSEL_ETIFP); timer_external_clock_mode1_config(TIMER1, TIMER_EXT_TRI_PSC_OFF, TIMER_ETP_RISING, 0);
(4)使能TIMER
timer_enable(TIMER1);
5.5.TIMER 使用注意事項(xiàng)
TIMER 高級定時器 做定時用的時候(使用到UPDAT中斷),在產(chǎn)生中斷之后,高級定時器的其他所有的狀態(tài)標(biāo)志位會被置位,但是不會置位中斷標(biāo)志位.
本教程由GD32 MCU方案商聚沃科技原創(chuàng)發(fā)布,了解更多GD32 MCU教程,關(guān)注聚沃科技官網(wǎng)
-
單片機(jī)
+關(guān)注
關(guān)注
6063文章
44921瀏覽量
646962 -
開發(fā)板
+關(guān)注
關(guān)注
25文章
5524瀏覽量
102309 -
Timer
+關(guān)注
關(guān)注
1文章
64瀏覽量
13112 -
GD32
+關(guān)注
關(guān)注
7文章
418瀏覽量
25156
發(fā)布評論請先 登錄
GD32 MCU 入門教程】GD32 MCU 常見外設(shè)介紹(12)FMC 模塊介紹

GD32的MCU介紹
《GD32 MCU原理及固件庫開發(fā)指南》 + 初讀感悟
《GD32 MCU原理及固件庫開發(fā)指南》+讀后感
兆易創(chuàng)新GD32 MCU選型手冊,適用于GD32全系列MCU
不同型號的GD32 MCU如何區(qū)分?

【GD32 MCU 入門教程】一、GD32 MCU 開發(fā)環(huán)境搭建(1)使用Keil開發(fā)GD32

【GD32 MCU 入門教程】一、GD32 MCU 開發(fā)環(huán)境搭建(2)使用 IAR 開發(fā) GD32

【GD32 MCU 入門教程】一、GD32 MCU 開發(fā)環(huán)境搭建(3)使用 Embedded Builder 開發(fā) GD32

【GD32 MCU 入門教程】二、GD32 MCU 燒錄說明(1)ISP 燒錄

【GD32 MCU 入門教程】GD32 MCU 常見外設(shè)介紹(14)RTC 模塊介紹

【GD32 MCU入門教程】GD32 MCU GPIO 結(jié)構(gòu)與使用注意事項(xiàng)

評論