網(wǎng)站:bbs.21ic.com
首先說一下定時器的分類,一共有四種定時器分別是:
-
高級控制定時器(Timer6)有3個; -
通用控制定時器(Timer4)有3個; -
通用定時器(TimerA)有6個; -
通用定時器(Timer0)有2個;
再次說一下這幾個定時器有什么區(qū)別:
看名字就知道高級控制定時器肯定是功能最全的
-
高級控制定時器 6(Timer6)是一個 16 位計數(shù)寬度的高性能定時器,可用于計數(shù)產(chǎn)生
不同形式的時鐘波形,輸出以供外部使用。
-
該定時器支持三角波和鋸齒波兩種波形模式,可生成各種 PWM 波形; -
單元間可實現(xiàn)軟件同步計數(shù)和硬件同步計數(shù); -
各基準值寄存器支持緩存功能; -
支持 2 相正交編碼和 3 相正交編碼; -
支持 EMB 控制。
a) PCLK0 及 PCLK0 的 4、16、64、256、1024 分頻(GCONR.CKDIV[2:0]設(shè)定)
b) 內(nèi)部觸發(fā)事件觸發(fā)輸入(HCUPR[17:16]或 HCDOR[17:16]設(shè)定)
c) TIM6_TRIGA-B 的端口輸入(HCUPR[11:8]或 HCDOR[11:8]設(shè)定)
d) TIM6_
計數(shù)時鐘源選擇 a 時為軟件計數(shù)模式,計數(shù)時鐘源選擇 b、c、d 時為硬件計數(shù)模式。
上述描述可以看到,b、c、d 時鐘互相獨立,可分別設(shè)定有效或無效,并且當選擇 b、c、d 時鐘時,a 時鐘自動無效。
定時器6的時鐘不能按照任意的分頻系數(shù)進行分頻,只能按照特定的頻率進行分頻,實話實說這一點就不如STM32方便了
-
通用比較基準值寄存器(GCMAR-GCMFR)共計 6 個,可分別與計數(shù)值比較產(chǎn)生比較匹配。 -
計數(shù)比較匹配時,狀態(tài)標志寄存器(STFLR)中的 STFLR.CMAF~STFLR.CMFF位分別會被置為 1。 -
此時若設(shè)定中斷控制寄存器(ICONR)的 INTENA~INTENF 中相應(yīng)位為 1 使能中斷,則對應(yīng)的中斷請(TMR6_U _GCMA~F)也會被觸發(fā)。 -
在硬件捕獲事件選擇寄存器(HCPAR、HCPBR)選擇的捕獲輸入有效條件產(chǎn)生時,捕獲輸入動作發(fā)生。 -
此時若設(shè)置中斷控制寄存器(ICONR)的 INTENA 或 INTENB 位為1 使能中斷,則對應(yīng)的中斷請求(TMR6_U _GCMA~B)被觸發(fā)。 -
2 個專用比較基準值寄存器(SCMAR-SCMBR)也可分別與計數(shù)值比較產(chǎn)生比較匹配。 -
計數(shù)比較匹配時,狀態(tài)標志寄存器(STFLR)中的 STFLR.CMSPAF~CMSPBF 位分別會被置為 1。此時若設(shè)定中斷控制寄存器(ICONR)的 INTENSAU 或 INTENSBU 中相應(yīng)位為 1 使能中斷,則對應(yīng)的中斷請求(TMR6_U _SCMA~B)也會被觸發(fā)。 -
這里面比較值的設(shè)置就是根據(jù)兩個比較基準寄存器的值來進行判斷的,這兩個寄存器分別是通用比較基準值寄存器,專用比較基準寄存器,其實還有一個是死區(qū)時間基準值寄存器
看看比較輸出的功能是怎么配置的
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ddl.h"
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/* KEY0 (SW2)*/
#define SW2_PORT (PortD)
#define SW2_PIN (Pin03)
/* KEY1 (SW4)*/
#define SW4_PORT (PortD)
#define SW4_PIN (Pin04)
/* KEY2 (SW3)*/
#define SW3_PORT (PortD)
#define SW3_PIN (Pin05)
/* KEY3 (SW5)*/
#define SW5_PORT (PortD)
#define SW5_PIN (Pin06)
/* LED0 Port/Pin definition */
#define LED0_PORT (PortE)
#define LED0_PIN (Pin06)
/* LED1 Port/Pin definition */
#define LED1_PORT (PortD)
#define LED1_PIN (Pin07)
/* LED2 Port/Pin definition */
#define LED2_PORT (PortB)
#define LED2_PIN (Pin05)
/* LED3 Port/Pin definition */
#define LED3_PORT (PortB)
#define LED3_PIN (Pin09)
/* LED0~1 toggle definition */
#define LED0_TOGGLE() (PORT_Toggle(LED0_PORT, LED0_PIN))
#define LED1_TOGGLE() (PORT_Toggle(LED1_PORT, LED1_PIN))
#define LED2_TOGGLE() (PORT_Toggle(LED2_PORT, LED2_PIN))
#define LED3_TOGGLE() (PORT_Toggle(LED3_PORT, LED3_PIN))
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
*******************************************************************************
** \brief Callback function of external interrupt ch.0
**
******************************************************************************/
void Timer6_OverFlow_CallBack(void)
{
}
/**
******************************************************************************
** \brief Initialize the system clock for the sample
**
** \param None
**
** \return None
******************************************************************************/
static void SysClkIni(void)
{
en_clk_sys_source_t enSysClkSrc;
stc_clk_sysclk_cfg_t stcSysClkCfg;
stc_clk_mpll_cfg_t stcMpllCfg;
stc_clk_output_cfg_t stcOutputClkCfg;
MEM_ZERO_STRUCT(enSysClkSrc);
MEM_ZERO_STRUCT(stcSysClkCfg);
MEM_ZERO_STRUCT(stcMpllCfg);
MEM_ZERO_STRUCT(stcOutputClkCfg);
/* Set bus clk div. */
stcSysClkCfg.enHclkDiv = ClkSysclkDiv1; // 168MHz
stcSysClkCfg.enExclkDiv = ClkSysclkDiv2; // 84MHz
stcSysClkCfg.enPclk0Div = ClkSysclkDiv1; // 168MHz (timer6 cnt)
stcSysClkCfg.enPclk1Div = ClkSysclkDiv2; // 84MHz (timer6 logic)
stcSysClkCfg.enPclk2Div = ClkSysclkDiv4; // 42MHz
stcSysClkCfg.enPclk3Div = ClkSysclkDiv4; // 42MHz
stcSysClkCfg.enPclk4Div = ClkSysclkDiv2; // 84MHz
CLK_SysClkConfig(&stcSysClkCfg);
CLK_HrcCmd(Enable); //Enable HRC
/* MPLL config. */
stcMpllCfg.pllmDiv = 2ul; //HRC 16M / 2
stcMpllCfg.plln = 42ul; //8M*42 = 336M
stcMpllCfg.PllpDiv = 2ul; //MLLP = 168M
stcMpllCfg.PllqDiv = 2ul; //MLLQ = 168M
stcMpllCfg.PllrDiv = 2ul; //MLLR = 168M
CLK_SetPllSource(ClkPllSrcHRC);
CLK_MpllConfig(&stcMpllCfg);
/* flash read wait cycle setting */
EFM_Unlock();
EFM_SetLatency(EFM_LATENCY_4);
EFM_Lock();
/* Enable MPLL. */
CLK_MpllCmd(Enable);
/* Wait MPLL ready. */
while(Set != CLK_GetFlagStatus(ClkFlagMPLLRdy))
{
;
}
/* Switch system clock source to MPLL. */
CLK_SetSysClkSource(CLKSysSrcMPLL);
}
/**
*******************************************************************************
** \brief Main function of project
**
** \param None
**
** \retval int32_t return value, if needed
**
******************************************************************************/
int32_t main(void)
{
uint16_t u16Period;
uint16_t u16Compare;
stc_timer6_basecnt_cfg_t stcTIM6BaseCntCfg;
stc_timer6_port_output_cfg_t stcTIM6PWMxCfg;
stc_timer6_gcmp_buf_cfg_t stcGCMPBufCfg;
stc_port_init_t stcPortInit;
stc_irq_regi_conf_t stcIrqRegiConf;
MEM_ZERO_STRUCT(stcTIM6BaseCntCfg);
MEM_ZERO_STRUCT(stcTIM6PWMxCfg);
MEM_ZERO_STRUCT(stcGCMPBufCfg);
MEM_ZERO_STRUCT(stcPortInit);
MEM_ZERO_STRUCT(stcIrqRegiConf);
SysClkIni();
PWC_Fcg2PeriphClockCmd(PWC_FCG2_PERIPH_TIM61, Enable);
PORT_SetFunc(PortE, Pin09, Func_Tim6, Disable); //Timer61 PWMA
PORT_SetFunc(PortE, Pin08, Func_Tim6, Disable); //Timer61 PWMB
stcTIM6BaseCntCfg.enCntMode = Timer6CntSawtoothMode; //Sawtooth wave mode
stcTIM6BaseCntCfg.enCntDir = Timer6CntDirUp; //Counter counting up
stcTIM6BaseCntCfg.enCntClkDiv = Timer6PclkDiv1; //Count clock: pclk0
Timer6_Init(M4_TMR61, &stcTIM6BaseCntCfg); //timer6 PWM frequency, count mode and clk config
u16Period = 33600u;
Timer6_SetPeriod(M4_TMR61, Timer6PeriodA, u16Period); //period set
u16Compare = 10000u;
Timer6_SetGeneralCmpValue(M4_TMR61, Timer6GenCompareA, u16Compare); //Set General Compare RegisterA Value
u16Compare = 20000u;
Timer6_SetGeneralCmpValue(M4_TMR61, Timer6GenCompareB, u16Compare); //Set General Compare RegisterB Value
stcTIM6PWMxCfg.enPortMode = Timer6ModeCompareOutput; //Compare output function
stcTIM6PWMxCfg.bOutEn = true; //Output enable
stcTIM6PWMxCfg.enPerc = Timer6PWMxCompareLow; //PWMA port output Low level when CNTER value match PERAR
stcTIM6PWMxCfg.enCmpc = Timer6PWMxCompareHigh; //PWMA port output High level when CNTER value match with GCMAR
stcTIM6PWMxCfg.enStaStp = Timer6PWMxStateSelSS; //PWMA output status is decide by STACA STPCA when CNTER start and stop
stcTIM6PWMxCfg.enStaOut = Timer6PWMxPortOutLow; //PWMA port output set low level when CNTER start
stcTIM6PWMxCfg.enStpOut = Timer6PWMxPortOutLow; //PWMA port output set low level when CNTER stop
stcTIM6PWMxCfg.enDisVal = Timer6PWMxDisValLow;
Timer6_PortOutputConfig(M4_TMR61, Timer6PWMA, &stcTIM6PWMxCfg);
stcTIM6PWMxCfg.enPortMode = Timer6ModeCompareOutput; //Compare output function
stcTIM6PWMxCfg.bOutEn = true; //Output enable
stcTIM6PWMxCfg.enPerc = Timer6PWMxCompareLow; //PWMB port output Low level when CNTER value match PERAR
stcTIM6PWMxCfg.enCmpc = Timer6PWMxCompareHigh; //PWMB port output High level when CNTER value match with GCMBR
stcTIM6PWMxCfg.enStaStp = Timer6PWMxStateSelSS; //PWMB output status is decide by STACB STPCB when CNTER start and stop
stcTIM6PWMxCfg.enStaOut = Timer6PWMxPortOutLow; //PWMB port output set low level when CNTER start
stcTIM6PWMxCfg.enStpOut = Timer6PWMxPortOutLow; //PWMB port output set low level when CNTER stop
stcTIM6PWMxCfg.enDisVal = Timer6PWMxDisValLow;
Timer6_PortOutputConfig(M4_TMR61, Timer6PWMB, &stcTIM6PWMxCfg);
/*config interrupt*/
/* Enable timer61 GOVF interrupt */
Timer6_ConfigIrq(M4_TMR61, Timer6INTENOVF, true);
stcIrqRegiConf.enIRQn = Int002_IRQn; //Register INT_TMR61_GOVF Int to Vect.No.002
stcIrqRegiConf.enIntSrc = INT_TMR61_GOVF; //Select Event interrupt of timer61
stcIrqRegiConf.pfnCallback = &Timer6_OverFlow_CallBack; //Callback function
enIrqRegistration(&stcIrqRegiConf); //Registration IRQ
NVIC_ClearPendingIRQ(stcIrqRegiConf.enIRQn); //Clear Pending
NVIC_SetPriority(stcIrqRegiConf.enIRQn, DDL_IRQ_PRIORITY_15);//Set priority
NVIC_EnableIRQ(stcIrqRegiConf.enIRQn); //Enable NVIC
/*start timer6*/
Timer6_StartCount(M4_TMR61);
while(1)
{
;
}
}
直接看源程序,就能找到三個時鐘分別是61 62 63
這次我們用的是61也就是第一個時鐘
那我們再看一下這個功能是配置的哪個寄存器呢?
這個時候如果還是沒看懂,那么我們回過頭來看用戶手冊關(guān)于這個定時器是怎么說的
以后我們?nèi)绻恢来a中配置的是什么意思了,也可以這樣來尋找答案。
u16Period = 33600u;
Timer6_SetPeriod(M4_TMR61, Timer6PeriodA, u16Period); //period set
這里我們用的是A通道,timer6有三個通道,分別如下圖所示
第五步:設(shè)置比較值
u16Compare = 10000u;
Timer6_SetGeneralCmpValue(M4_TMR61, Timer6GenCompareA, u16Compare); //Set General Compare RegisterA Value
u16Compare = 20000u;
Timer6_SetGeneralCmpValue(M4_TMR61, Timer6GenCompareB, u16Compare); //Set General Compare RegisterB Value
看到這里我們來畫個圖說明一下
我們制定好波形,波形的頻率就是根據(jù)預(yù)分頻值算出來的,然后設(shè)置好重裝載值和比較值,再設(shè)置中斷類型,就可以產(chǎn)生響應(yīng)的中斷
第六步:設(shè)置輸出功能
stcTIM6PWMxCfg.enPortMode = Timer6ModeCompareOutput; //Compare output function
stcTIM6PWMxCfg.bOutEn = true; //Output enable
stcTIM6PWMxCfg.enPerc = Timer6PWMxCompareLow; //PWMA port output Low level when CNTER value match PERAR
stcTIM6PWMxCfg.enCmpc = Timer6PWMxCompareHigh; //PWMA port output High level when CNTER value match with GCMAR
stcTIM6PWMxCfg.enStaStp = Timer6PWMxStateSelSS; //PWMA output status is decide by STACA STPCA when CNTER start and stop
stcTIM6PWMxCfg.enStaOut = Timer6PWMxPortOutLow; //PWMA port output set low level when CNTER start
stcTIM6PWMxCfg.enStpOut = Timer6PWMxPortOutLow; //PWMA port output set low level when CNTER stop
stcTIM6PWMxCfg.enDisVal = Timer6PWMxDisValLow;
Timer6_PortOutputConfig(M4_TMR61, Timer6PWMA, &stcTIM6PWMxCfg);
根據(jù)以上的代碼我們就設(shè)置好了比較輸出的功能,怎么算比較輸出呢,就是當計數(shù)值經(jīng)過比較值的時候輸出引腳進行翻轉(zhuǎn),由高電平變?yōu)榈碗娖剑蛘哂械碗娖阶優(yōu)楦唠娖?/span>
第七步:配置中斷功能
/*config interrupt*/
/* Enable timer61 GOVF interrupt */
Timer6_ConfigIrq(M4_TMR61, Timer6INTENOVF, true);
stcIrqRegiConf.enIRQn = Int002_IRQn; //Register INT_TMR61_GOVF Int to Vect.No.002
stcIrqRegiConf.enIntSrc = INT_TMR61_GOVF; //Select Event interrupt of timer61
stcIrqRegiConf.pfnCallback = &Timer6_OverFlow_CallBack; //Callback function
enIrqRegistration(&stcIrqRegiConf); //Registration IRQ
NVIC_ClearPendingIRQ(stcIrqRegiConf.enIRQn); //Clear Pending
NVIC_SetPriority(stcIrqRegiConf.enIRQn, DDL_IRQ_PRIORITY_15);//Set priority
NVIC_EnableIRQ(stcIrqRegiConf.enIRQn); //Enable NVIC
復(fù)制代碼
第八步:使能定時器
/*start timer6*/
Timer6_StartCount(M4_TMR61);
這里我們講解的是高級定時器的功能,剩下的定時器,就是在這個基礎(chǔ)上進行簡配得到的,所以就不再一一列舉了,大家有時間可以看看手冊和代碼,關(guān)鍵的注意事項在上面都介紹了,大家應(yīng)該配置沒有問題,如果遇到問題了,可以在本帖留言,我看到后會及時回復(fù) 謝謝大家了
免責聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!