当前位置:首页 > 公众号精选 > 21ic电子网
[导读]这次和大家一起分享一下华大HC32F460的定时器。

出品  21ic论坛  binoo7

网站:bbs.21ic.com


这次和大家一起分享一下华大HC32F460的定时器。
首先说一下定时器的分类,一共有四种定时器分别是:
  • 高级控制定时器(Timer6)有3个;
  • 通用控制定时器(Timer4)有3个;
  • 通用定时器(TimerA)有6个;
  • 通用定时器(Timer0)有2个;

再次说一下这几个定时器有什么区别:
看名字就知道高级控制定时器肯定是功能最全的
  • 高级控制定时器 6(Timer6)是一个 16 位计数宽度的高性能定时器,可用于计数产生

不同形式的时钟波形,输出以供外部使用。
  • 该定时器支持三角波和锯齿波两种波形模式,可生成各种 PWM 波形;
  • 单元间可实现软件同步计数和硬件同步计数;
  • 各基准值寄存器支持缓存功能;
  • 支持 2 相正交编码和 3 相正交编码;
  • 支持 EMB 控制。
主要看一下基本框图

最全!华大HC32F460定时器介绍


看框图能看,Timer6 的计数时钟可以有以下几种选择:
a) PCLK0 及 PCLK0 的 4、16、64、256、1024 分频(GCONR.CKDIV[2:0]设定)
b) 内部触发事件触发输入(HCUPR[17:16]或 HCDOR[17:16]设定)
c) TIM6_TRIGA-B 的端口输入(HCUPR[11:8]或 HCDOR[11:8]设定)
d) TIM6__PWMA 和 TIM6__PWMB 的 正交编码 输入( HCUPR[7:0] 或HCDOR[7:0]设定)
计数时钟源选择 a 时为软件计数模式,计数时钟源选择 b、c、d 时为硬件计数模式。
上述描述可以看到,b、c、d 时钟互相独立,可分别设定有效或无效,并且当选择 b、c、d 时钟时,a 时钟自动无效。
定时器6的时钟不能按照任意的分频系数进行分频,只能按照特定的频率进行分频,实话实说这一点就不如STM32方便了

最全!华大HC32F460定时器介绍



计数方式有两种,一个是锯齿波,一个是三角波,两种波形的方式进行计数,当达到设定值后会清零或向下计数


自动重装载值这里叫做通用周期基准值寄存器,官方给的解释是设定每轮计数的计数周期值及对应缓存值 ,说实话这个官方的解释我看了一天也没搞懂是啥意思,很容易和STM32的周期计数混淆,大家要多注意了。


最全!华大HC32F460定时器介绍
看寄存器的配置就能知道这是一个16位的定时器。


定时器可以产生的中断中官方给的解释如下:


  • 通用比较基准值寄存器(GCMAR-GCMFR)共计 6 个,可分别与计数值比较产生比较匹配。
  • 计数比较匹配时,状态标志寄存器(STFLR)中的 STFLR.CMAF~STFLR.CMFF位分别会被置为 1。
  • 此时若设定中断控制寄存器(ICONR)的 INTENA~INTENF 中相应位为 1 使能中断,则对应的中断请(TMR6_U_GCMA~F)也会被触发。
  • 在硬件捕获事件选择寄存器(HCPAR、HCPBR)选择的捕获输入有效条件产生时,捕获输入动作发生。
  • 此时若设置中断控制寄存器(ICONR)的 INTENA 或 INTENB 位为1 使能中断,则对应的中断请求(TMR6_U_GCMA~B)被触发。
  • 2 个专用比较基准值寄存器(SCMAR-SCMBR)也可分别与计数值比较产生比较匹配。
  • 计数比较匹配时,状态标志寄存器(STFLR)中的 STFLR.CMSPAF~CMSPBF 位分别会被置为 1。此时若设定中断控制寄存器(ICONR)的 INTENSAU或 INTENSBU中相应位为 1 使能中断,则对应的中断请求(TMR6_U_SCMA~B)也会被触发。

看上面的解释可能会云里雾里看不懂啥意思,还不如直接看中断控制寄存器,有多少中断都在中断控制器里写的明明白白,这样的话我们就能很容易的来根据需要配置中断的功能了,具体配置如下图所示

最全!华大HC32F460定时器介绍



这里面比较值的设置就是根据两个比较基准寄存器的值来进行判断的,这两个寄存器分别是通用比较基准值寄存器,专用比较基准寄存器,其实还有一个是死区时间基准值寄存器


最全!华大HC32F460定时器介绍
下面直接看代码,看看高级控制定时器的用法


最全!华大HC32F460定时器介绍
官方给的例程挺多的,有耐心的小伙伴可以仔细分析一下MCU的TIMER6的PWM的锯齿波模式、无缓存输出功能,
看看比较输出的功能是怎么配置的

/******************************************************************************** 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) { ; }
}


我们直接分析主函数部分


第一步:先开启时钟 :PWC_Fcg2PeriphClockCmd(PWC_FCG2_PERIPH_TIM61, Enable);
最全!华大HC32F460定时器介绍
直接看源程序,就能找到三个时钟分别是61 62 63
这次我们用的是61也就是第一个时钟


第二步:是配置引脚为TIMER61的输出引脚 也就是端口复用
最全!华大HC32F460定时器介绍


第三步:配置定时器功能和预分频系数
最全!华大HC32F460定时器介绍
定时器都有什么功能呢,看源代码能看到有三个
最全!华大HC32F460定时器介绍
那我们再看一下这个功能是配置的哪个寄存器呢?
最全!华大HC32F460定时器介绍
这个时候如果还是没看懂,那么我们回过头来看用户手册关于这个定时器是怎么说的
最全!华大HC32F460定时器介绍
以后我们如果不知道代码中配置的是什么意思了,也可以这样来寻找答案。


第四步:设置通用周期基准值寄存器,也就是重装载值

u16Period = 33600u; Timer6_SetPeriod(M4_TMR61, Timer6PeriodA, u16Period); //period set


这里我们用的是A通道,timer6有三个通道,分别如下图所示
最全!华大HC32F460定时器介绍

第五步:设置比较值

 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

看到这里我们来画个图说明一下
最全!华大HC32F460定时器介绍
我们制定好波形,波形的频率就是根据预分频值算出来的,然后设置好重装载值和比较值,再设置中断类型,就可以产生响应的中断

第六步:设置输出功能

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);

根据以上的代码我们就设置好了比较输出的功能,怎么算比较输出呢,就是当计数值经过比较值的时候输出引脚进行翻转,由高电平变为低电平,或者有低电平变为高电平


这样就产生了占空比可调的PWM波形输出了,看下面的图,大家就清楚了


最全!华大HC32F460定时器介绍
每次遇到比较,就翻转输出,这样我们设置不同的比较值,就可以有不同占空比的PWM了,这样的控制方式对于步进电机控制上好处多多,我推荐大家可以看看硬石老师的电机开发例程和野火老师的例程,他们用的都是定时器的比较输出的功能来控制步进电机产生梯形加减速、S形加减速。


言归正传我们继续分析代码

第七步:配置中断功能

/*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
复制代码

最全!华大HC32F460定时器介绍

第八步:使能定时器

 /*start timer6*/ Timer6_StartCount(M4_TMR61);

这里我们讲解的是高级定时器的功能,剩下的定时器,就是在这个基础上进行简配得到的,所以就不再一一列举了,大家有时间可以看看手册和代码,关键的注意事项在上面都介绍了,大家应该配置没有问题,如果遇到问题了,可以在本帖留言,我看到后会及时回复 谢谢大家了



本文系21i c论坛网友binoo7的回忆 原创

免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

21ic电子网

扫描二维码,关注更多精彩内容

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭