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

5.2.硬件連接說明
TIMER 屬于片內外設,對于外部硬件設計,只需要單獨IO口外接信號線即可。
5.3.GD32 TIMER 外設原理簡介(以 GD32F30X 的高級定時器為例)
GD32 TIMER 主要特性
? 總通道數: 4;
? 計數器寬度: 16位;
? 定時器時鐘源可選:內部時鐘,內部觸發,外部輸入,外部觸發;
? 多種計數模式:向上計數,向下計數和中央計數;
? 可編程的預分頻器: 16位。運行時可以被改變;
? 每個通道可配置:輸入捕獲模式,輸出比較模式,可編程的PWM模式,單脈沖模式;
? 可編程的死區時間;
? 自動重裝載功能;
? 可編程的計數器重復功能;
? 中止輸入功能;
? 中斷輸出和DMA請求:更新事件,觸發事件,比較/捕獲事件和中止事件;
? 多個定時器的菊鏈使得一個定時器可以同時啟動多個定時器;
? 定時器的同步允許被選擇的定時器在同一個時鐘周期開始計數;
? 定時器主/從模式控制器。
TIMER 結構框圖介紹

5.4.軟件配置說明
定時中斷 TIMER4
通用定時器L0(TIMER1/2/3/4) 是4通道定時器,支持輸入捕獲,輸出比較,產生PWM信號控制電機和電源管理。通用定時器L0計數器是16位無符號計數器。通用定時器L0是可編程的,可以被用來計數,其外部事件可以驅動其他定時器。
這一章,將使用定時器產生中斷,然后在中斷服務函數里面翻轉 LED上的電平,來指示定時器中斷的產生。接下來我們以通用定時器 TIMER4 為實例,來說明要經過哪些步驟,才能達到這個要 求,并產生中斷。定時器配置步驟如下:
1)TIMER4 時鐘使能
rcu_periph_clock_enable(RCU_TIMER4);
2) 初始化定時器參數,設置自動重裝值,分頻系數,計數方式等
在庫函數中,定時器的初始化參數是通過初始化函數timer_parameter_struct 實現的:
void timer_init(uint32_t timer_periph, timer_parameter_struct* initpara);
第一個參數是確定是哪個定時器,這個比較容易理解。第二個參數是定時器初始化參數結構體指針,結構體類型為timer_parameter_struct ,下面我們看看這個結構體的定義:
/* 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);
對于定時器定時周期的計算,設 TIMER4 的經過總線分頻后得到的時鐘為 30MHz,通過預分頻 5999,得到 TIMER4 每個計 數的時鐘為 1/(30MHz / (5999+1)) =0.2ms,4000 得到的周期為 0.2ms *4000 =800ms
3)設置 TIMER 允許更新中斷
因為我們要使用 TIMER4 的更新中斷,寄存器的相應位便可使能更新中斷。在庫函數里面定時器中斷使能是通過timer_interrupt_enable函數來實現的:
void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt);
第一個參數是選擇定時器號,這個容易理解。
第二個參數非常關鍵,是用來指明我們使能的定時器中斷的類型。
4) TIMER4 中斷優先級設置
在定時器中斷使能之后,因為要產生中斷,必不可少的要設置 NVIC 相關寄存器,設置中斷優先級。通過nvic_irq_enable 函數實現中斷優先級的設置。
針對 TIMR4 初始化范例代碼格式
nvic_irq_enable(TIMER4_IRQn, 1, 1);
5)允許 TIMER工作,也就是使能 TIMER
光配置好定時器還不行,沒有開啟定時器,照樣不能用。我們在配置完后要開啟定時器,在固件庫里面使能定時器的函數是通過timer_enable函數來實現的
void timer_enable(uint32_t timer_periph)
這個函數非常簡單,比如我們要使能TIMER4,方法為:
timer_enable(TIMER4);
6)編寫中斷服務函數
在最后,還是要編寫定時器中斷服務函數,通過該函數來處理定時器產生的相關中斷。中斷產生后,通過狀態寄存器的值來判斷此次產生的中斷屬于什么類型。然后執行相關的操作,我們這里使用的是更新(溢出)中斷,在處理完中斷之后應來清除該中斷標志。
在固件庫函數里面,用來讀取中斷狀態寄存器的值判斷中斷類型的函數是:
FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t interrupt)
該函數的作用是,判斷定時器 TIMER 的中斷類型,并判斷是否發生中斷。
針對 TIMR4 中斷服務函數范例代碼:
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)是四通道定時器,支持輸入捕獲和輸出比較。可以產生PWM信號控制電機和電源管理。高級定時器含有一個16位無符號計數器。高級定時器是可編程的,可以用來計數,其外部事件可以驅動其他定時器。高級定時器包含了一個死區時間插入模塊,非常適合電機控制。
本章,我們使用的是 TIMER0的通道0 輸出 PWM(脈沖寬度調制)。
下面我們介紹通過庫函數來配置該功能的步驟:
(1)開啟 TIMER0 和 GPIO 時鐘,配置 PA8復用功能輸出。
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);
這里還需要說明一下, 對于定時器通道的引腳關系,引腳的IO口

這里補充說明下關于TIMER的相關GPIO口的命名
TIMERx_CHx : 定時器通道x
TIMERx_CHx_ON :定時器反向通道
TIMERx_BRKIN :剎車引腳
TIMERx_ETI:外部時鐘輸入
(2)初始化 TIMER0 ,設置 TIMER0 的預分頻和周期等參數, ,在上一節定時器中斷章節我們已經有講解,這里就不詳細講解,調用的格式為
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)設置 TIMER0_CH0 的 PWM 模式, 使能 TIMER0 的 CH0 輸出。 在庫函數中, PWM 通道設置是通過函數timer_channel_output_config來設置的
void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_oc_parameter_struct* ocpara)
我們直接來看看結構體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)設置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
在完成以上設置了之后,我們需要使能 TIMER0。使能 TIMER0 的方法前面已經講解過:
timer_enable(TIMER0);
通過以上 5 個步驟,我們就可以控制 TIMER0的 CH0 輸出 PWM 波了。這里特別提醒一下大家,高級定時器雖然和通用定時器類似,但是高級定時器要想輸出 PWM,必須多額外加一條函數
void timer_primary_output_config(uint32_t timer_periph, ControlStatus newvalue);
輸入捕獲 TIMER2
通用定時器L0(TIMER1/2/3/4) 是4通道定時器,支持輸入捕獲,輸出比較,產生PWM信號控制電機和電源管理。通用定時器L0計數器是16位無符號計數器。通用定時器L0是可編程的,可以被用來計數,其外部事件可以驅動其他定時器。
本章要實現通過輸入捕獲,來獲取TIMER2_CH0(PA6)上面的下降沿,下面我們介紹庫函數配置上述功能輸入捕獲的步驟:
1)開啟 TIMER2 時鐘,配置 PA6為復用功能,并開啟上拉電阻。
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,所以我們從對應的數據手冊可以查看到對應的 IO 口為 PA6:

2) 初始化定時器參數,設置自動重裝值, 分頻系數,計數方式等
/* 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)設置 TIMER2 的輸入捕獲參數,開啟輸入捕獲
庫函數是通過 timer_input_capture_config 函數來初始化輸入比較參數的: timer_input_capture_config(TIMER2,TIMER_CH_0,&timer_icinitpara);
同樣,我們來看看參數設置結構體 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) 編寫中斷服務函數
void TIMER2_IRQHandler(void){……}
6) 使能定時器
timer_enable(TIMER2);
通過以上 6 步設置,定時器 2 的通道 0 就可以開始輸入捕獲了
外部時鐘輸入 TIMER1
通用定時器L0(TIMER1/2/3/4) 是4通道定時器,支持輸入捕獲,輸出比較,產生PWM信號控制電機和電源管理。通用定時器L0計數器是16位無符號計數器。通用定時器L0是可編程的,可以被用來計數,其外部事件可以驅動其他定時器。
本章要實現使用TIMER1 PA0 作為時鐘輸入引腳,配置流程:
(1)使能GPIO,TIMER 時鐘和GPIO口復用配置
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)通過查看數據手冊,可以看到TIMER1_CH0_ETI,根據前面所講,是可以支持外部時鐘輸入的。
TIMER的結構體,初始化定時器參數,設置自動重裝值, 分頻系數,計數方式等
//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 使用注意事項
TIMER 高級定時器 做定時用的時候(使用到UPDAT中斷),在產生中斷之后,高級定時器的其他所有的狀態標志位會被置位,但是不會置位中斷標志位.
-
單片機
+關注
關注
6064文章
44932瀏覽量
647482 -
開發板
+關注
關注
25文章
5563瀏覽量
102662 -
Timer
+關注
關注
1文章
64瀏覽量
13127 -
GD32
+關注
關注
7文章
419瀏覽量
25203
發布評論請先 登錄
GD32 MCU 入門教程】GD32 MCU 常見外設介紹(12)FMC 模塊介紹

《GD32 MCU原理及固件庫開發指南》 + 初讀感悟
兆易創新GD32 MCU選型手冊,適用于GD32全系列MCU
【GD32 MCU 入門教程】一、GD32 MCU 開發環境搭建(1)使用Keil開發GD32

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

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

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

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

【GD32 MCU入門教程】GD32 MCU GPIO 結構與使用注意事項

評論