5.1.TIMER 基礎(chǔ)知識
TIMER分高級定時(shí)器,通用定時(shí)器L0,L1,L2和基本定時(shí)器。
5.2.硬件連接說明
TIMER 屬于片內(nèi)外設(shè),對于外部硬件設(shè)計(jì),只需要單獨(dú)IO口外接信號線即可。
5.3.GD32 TIMER 外設(shè)原理簡介(以 GD32F30X 的高級定時(shí)器為例)
GD32 TIMER 主要特性
? 總通道數(shù): 4;
? 計(jì)數(shù)器寬度: 16位;
? 定時(shí)器時(shí)鐘源可選:內(nèi)部時(shí)鐘,內(nèi)部觸發(fā),外部輸入,外部觸發(fā);
? 多種計(jì)數(shù)模式:向上計(jì)數(shù),向下計(jì)數(shù)和中央計(jì)數(shù);
? 正交編碼器接口:用來追蹤運(yùn)動(dòng)和分辨旋轉(zhuǎn)方向和位置;
? 可編程的預(yù)分頻器: 16位。運(yùn)行時(shí)可以被改變;
? 每個(gè)通道可配置:輸入捕獲模式,輸出比較模式,可編程的PWM模式,單脈沖模式;
? 可編程的死區(qū)時(shí)間;
? 自動(dòng)重裝載功能;
? 可編程的計(jì)數(shù)器重復(fù)功能;
? 中止輸入功能;
? 中斷輸出和DMA請求:更新事件,觸發(fā)事件,比較/捕獲事件和中止事件;
? 多個(gè)定時(shí)器的菊鏈?zhǔn)沟靡粋€(gè)定時(shí)器可以同時(shí)啟動(dòng)多個(gè)定時(shí)器;
? 定時(shí)器的同步允許被選擇的定時(shí)器在同一個(gè)時(shí)鐘周期開始計(jì)數(shù);
? 定時(shí)器主/從模式控制器。
TIMER 結(jié)構(gòu)框圖介紹
5.4.軟件配置說明
定時(shí)中斷 TIMER4
通用定時(shí)器L0(TIMER1/2/3/4) 是4通道定時(shí)器,支持輸入捕獲,輸出比較,產(chǎn)生PWM信號控制電機(jī)和電源管理。通用定時(shí)器L0計(jì)數(shù)器是16位無符號計(jì)數(shù)器。通用定時(shí)器L0是可編程的,可以被用來計(jì)數(shù),其外部事件可以驅(qū)動(dòng)其他定時(shí)器。
這一章,將使用定時(shí)器產(chǎn)生中斷,然后在中斷服務(wù)函數(shù)里面翻轉(zhuǎn) LED上的電平,來指示定時(shí)器中斷的產(chǎn)生。接下來我們以通用定時(shí)器 TIMER4 為實(shí)例,來說明要經(jīng)過哪些步驟,才能達(dá)到這個(gè)要 求,并產(chǎn)生中斷。定時(shí)器配置步驟如下:
1)TIMER4 時(shí)鐘使能
rcu_periph_clock_enable(RCU_TIMER4);
2) 初始化定時(shí)器參數(shù),設(shè)置自動(dòng)重裝值,分頻系數(shù),計(jì)數(shù)方式等
在庫函數(shù)中,定時(shí)器的初始化參數(shù)是通過初始化函數(shù)timer_parameter_struct 實(shí)現(xiàn)的:
void timer_init(uint32_t timer_periph, timer_parameter_struct* initpara);
第一個(gè)參數(shù)是確定是哪個(gè)定時(shí)器,這個(gè)比較容易理解。第二個(gè)參數(shù)是定時(shí)器初始化參數(shù)結(jié)構(gòu)體指針,結(jié)構(gòu)體類型為timer_parameter_struct ,下面我們看看這個(gè)結(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);
對于定時(shí)器定時(shí)周期的計(jì)算,設(shè) TIMER4 的經(jīng)過總線分頻后得到的時(shí)鐘為 30MHz,通過預(yù)分頻 5999,得到 TIMER4 每個(gè)計(jì) 數(shù)的時(shí)鐘為 1/(30MHz / (5999+1)) =0.2ms,4000 得到的周期為 0.2ms *4000 =800ms
3)設(shè)置 TIMER 允許更新中斷
因?yàn)槲覀円褂?TIMER4 的更新中斷,寄存器的相應(yīng)位便可使能更新中斷。在庫函數(shù)里面定時(shí)器中斷使能是通過timer_interrupt_enable函數(shù)來實(shí)現(xiàn)的:
void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt);
第一個(gè)參數(shù)是選擇定時(shí)器號,這個(gè)容易理解。
第二個(gè)參數(shù)非常關(guān)鍵,是用來指明我們使能的定時(shí)器中斷的類型。
4) TIMER4 中斷優(yōu)先級設(shè)置
在定時(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í)器還不行,沒有開啟定時(shí)器,照樣不能用。我們在配置完后要開啟定時(shí)器,在固件庫里面使能定時(shí)器的函數(shù)是通過timer_enable函數(shù)來實(shí)現(xiàn)的
void timer_enable(uint32_t timer_periph)
這個(gè)函數(shù)非常簡單,比如我們要使能TIMER4,方法為:
timer_enable(TIMER4);
6)編寫中斷服務(wù)函數(shù)
在最后,還是要編寫定時(shí)器中斷服務(wù)函數(shù),通過該函數(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ù)的作用是,判斷定時(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
高級定時(shí)器(TIMER0和TIMER7)是四通道定時(shí)器,支持輸入捕獲和輸出比較??梢援a(chǎn)生PWM信號控制電機(jī)和電源管理。高級定時(shí)器含有一個(gè)16位無符號計(jì)數(shù)器。高級定時(shí)器是可編程的,可以用來計(jì)數(shù),其外部事件可以驅(qū)動(dòng)其他定時(shí)器。高級定時(shí)器包含了一個(gè)死區(qū)時(shí)間插入模塊,非常適合電機(jī)控制。
本章,我們使用的是 TIMER0的通道0 輸出 PWM(脈沖寬度調(diào)制)。
下面我們介紹通過庫函數(shù)來配置該功能的步驟:
(1)開啟 TIMER0 和 GPIO 時(shí)鐘,配置 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);
這里還需要說明一下, 對于定時(shí)器通道的引腳關(guān)系,引腳的IO口
這里補(bǔ)充說明下關(guān)于TIMER的相關(guān)GPIO口的命名
TIMERx_CHx : 定時(shí)器通道x
TIMERx_CHx_ON :定時(shí)器反向通道
TIMERx_BRKIN :剎車引腳
TIMERx_ETI:外部時(shí)鐘輸入
(2)初始化 TIMER0 ,設(shè)置 TIMER0 的預(yù)分頻和周期等參數(shù), ,在上一節(jié)定時(shí)器中斷章節(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 個(gè)步驟,我們就可以控制 TIMER0的 CH0 輸出 PWM 波了。這里特別提醒一下大家,高級定時(shí)器雖然和通用定時(shí)器類似,但是高級定時(shí)器要想輸出 PWM,必須多額外加一條函數(shù)
void timer_primary_output_config(uint32_t timer_periph, ControlStatus newvalue);
輸入捕獲 TIMER2
通用定時(shí)器L0(TIMER1/2/3/4) 是4通道定時(shí)器,支持輸入捕獲,輸出比較,產(chǎn)生PWM信號控制電機(jī)和電源管理。通用定時(shí)器L0計(jì)數(shù)器是16位無符號計(jì)數(shù)器。通用定時(shí)器L0是可編程的,可以被用來計(jì)數(shù),其外部事件可以驅(qū)動(dòng)其他定時(shí)器。
本章要實(shí)現(xiàn)通過輸入捕獲,來獲取TIMER2_CH0(PA6)上面的下降沿,下面我們介紹庫函數(shù)配置上述功能輸入捕獲的步驟:
1)開啟 TIMER2 時(shí)鐘,配置 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 輸出類似,這里我們使用的是定時(shí)器2的通道 0,所以我們從對應(yīng)的數(shù)據(jù)手冊可以查看到對應(yīng)的 IO 口為 PA6:
2) 初始化定時(shí)器參數(shù),設(shè)置自動(dòng)重裝值, 分頻系數(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) 使能定時(shí)器
timer_enable(TIMER2);
通過以上 6 步設(shè)置,定時(shí)器 2 的通道 0 就可以開始輸入捕獲了
外部時(shí)鐘輸入 TIMER1
通用定時(shí)器L0(TIMER1/2/3/4) 是4通道定時(shí)器,支持輸入捕獲,輸出比較,產(chǎn)生PWM信號控制電機(jī)和電源管理。通用定時(shí)器L0計(jì)數(shù)器是16位無符號計(jì)數(shù)器。通用定時(shí)器L0是可編程的,可以被用來計(jì)數(shù),其外部事件可以驅(qū)動(dòng)其他定時(shí)器。
本章要實(shí)現(xiàn)使用TIMER1 PA0 作為時(shí)鐘輸入引腳,配置流程:
(1)使能GPIO,TIMER 時(shí)鐘和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ù)前面所講,是可以支持外部時(shí)鐘輸入的。
TIMER的結(jié)構(gòu)體,初始化定時(shí)器參數(shù),設(shè)置自動(dòng)重裝值, 分頻系數(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的時(shí)鐘來源和時(shí)鐘源處理的配置
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 高級定時(shí)器 做定時(shí)用的時(shí)候(使用到UPDAT中斷),在產(chǎn)生中斷之后,高級定時(shí)器的其他所有的狀態(tài)標(biāo)志位會(huì)被置位,但是不會(huì)置位中斷標(biāo)志位.
本教程由GD32 MCU方案商聚沃科技原創(chuàng)發(fā)布,了解更多GD32 MCU教程,關(guān)注聚沃科技官網(wǎng)
-
單片機(jī)
+關(guān)注
關(guān)注
6026文章
44459瀏覽量
631247 -
開發(fā)板
+關(guān)注
關(guān)注
25文章
4846瀏覽量
96899 -
Timer
+關(guān)注
關(guān)注
1文章
63瀏覽量
12760 -
GD32
+關(guān)注
關(guān)注
7文章
403瀏覽量
24067
發(fā)布評論請先 登錄
相關(guān)推薦
評論