[综合信息] PWM输入捕获,使用TIM6

[复制链接]
 楼主| aoyi 发表于 2021-9-1 08:45 | 显示全部楼层 |阅读模式
一、启动时钟

PWC_Fcg2PeriphClockCmd(PWC_FCG2_TMR6_x, Enable);


TMR6对应FCG2,根据PWM输入引脚来确定是TMR6_x(本例为TMR6_2)。运行以后PWC的FCG2寄存器相应位被清0。

29399612ecd33051aa.png
同时TM62的这些寄存器被全部置1,GCONR的DIR位被置一。
50624612ecd4291620.png
以上步骤类似STM32的开启RCC时钟。


 楼主| aoyi 发表于 2021-9-1 08:47 | 显示全部楼层
二、功能初始化
设置TIM62的GCONR寄存器。

97594612ecd66d4f96.png

47829612ecd711ebb6.png

    /* Timer6 general count function configuration */
    stcTIM6BaseCntCfg.u32CntMode = TMR6_MODE_SAWTOOTH;
    stcTIM6BaseCntCfg.u32CntDir = TMR6_CNT_INCREASE;
    stcTIM6BaseCntCfg.u32CntClkDiv = TMR6_CLK_PCLK0_DIV1024;
    stcTIM6BaseCntCfg.u32CntStpAftOvf = TMR6_CNT_CONTINUOUS;
    (void)TMR6_Init(M4_TMR6_2, &stcTIM6BaseCntCfg);


设为锯齿波(TMR6_MODE_SAWTOOTH),计数增长(TMR6_CNT_INCREASE),1024分频(TMR6_CLK_PCLK0_DIV1024),计满溢出后继续计数(TMR6_CNT_CONTINUOUS)。

88703612ecd8046cc3.png

 楼主| aoyi 发表于 2021-9-1 08:48 | 显示全部楼层
三、配置GPIO为PWM输入

本例为PB07
PB07可以作为TIM62_PWM的A通道使用

63414612ecda216d29.png

#define         TMR6_2_PWMA_PORT       (GPIO_PORT_B)
#define         TMR6_2_PWMA_PIN        (GPIO_PIN_07)
GPIO_SetFunc(TMR6_2_PWMA_PORT, TMR6_2_PWMA_PIN, GPIO_FUNC_3_TIM62_PWMA, PIN_SUBFUNC_DISABLE);


83907612ecda9d1a1f.png

 楼主| aoyi 发表于 2021-9-1 08:49 | 显示全部楼层
四、确立TMR62定时周期

    /* Period register set */
    u32Period = 0xFFFFFFFFu;
    TMR6_SetPeriodReg(M4_TMR6_2, TMR6_PERIOD_REG_A, u32Period);


TMR62是32位计数器最大值可以设置到0xFFFFFFFF。对PERAR寄存器设置0xFFFFFFFF。PERBR和PERCR可以作为缓存,这里不用,不管它们。


 楼主| aoyi 发表于 2021-9-1 08:51 | 显示全部楼层
五、开启外部PWM信号捕获并配置滤波
设定端口控制寄存器PCNAR(PCNBR)的 CAPMDA(CAPMDB)位为1,捕获输入功能变为有效,同时设置FCNGR的对应A或B开启滤波,并配置其时钟分频。本例使用channel A。

    /* Capture input port configuration */
    stcTIM6PortInCfg.u32PortMode = TMR6_PORT_CAPTURE_INPUT;
    stcTIM6PortInCfg.u32FilterSta = TMR6_PORT_INPUT_FILTER_ON;
    stcTIM6PortInCfg.u32FltClk = TMR6_INPUT_FILTER_PCLK0_DIV16;
    (void)TMR6_PortInputConfig(M4_TMR6_2,TMR6_IO_PWMA, &stcTIM6PortInCfg);


watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2N5cHJlc3N4dDkyNg==,size_16,color_FFFFFF,t_70.jpg
在滤波采样基准时钟采样到端口上 3 次一致的电平时,该电平被当作有效电平传送到模块内部;小于 3 次一致的电平会被当作外部干扰滤掉,不传送到模块内部。其动作。


watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2N5cHJlc3N4dDkyNg==,size_16,color_FFFFFF,t_70.jpg
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2N5cHJlc3N4dDkyNg==,size_16,color_FFFFFF,t_70.jpg

 楼主| aoyi 发表于 2021-9-1 08:52 | 显示全部楼层
六、配置PWM捕获(HCPAR)

这个库函数是专门配置通道A的,操作寄存器HCPAR。

    TMR6_HwCaptureChACondCmd(M4_TMR6_2, TMR6_HW_CTRL_PWMA_RISING, Enable);


请注意,如果需要使用通道B,则需要换函数。

void TMR6_HwCaptureChBCondCmd(M4_TMR6_TypeDef *TMR6x,
                            uint32_t u32CondSrc,
                            en_functional_state_t enNewState)


2021012216051317.png
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2N5cHJlc3N4dDkyNg==,size_16,color_FFFFFF,t_70.jpg

 楼主| aoyi 发表于 2021-9-1 08:54 | 显示全部楼层
七、捕获到跳变沿后,计数器计数硬件清零(HCLRR)

配置硬件清零事件选择寄存器(HCLRR),使得每次发生捕获事件后,计数器从0开始重新计数。

如果想测量PWM周期,则应该与捕获条件一致,本例捕获为上升沿,所以清0条件也应为上升沿。

    TMR6_HwClrCondCmd(M4_TMR6_2, TMR6_HW_CTRL_PWMA_RISING, Enable);

2627612ece31d6c22.png


    TMR6_HwClrFuncCmd(M4_TMR6_2, Enable);

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2N5cHJlc3N4dDkyNg==,size_16,color_FFFFFF,t_70.jpg
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2N5cHJlc3N4dDkyNg==,size_16,color_FFFFFF,t_70.jpg

 楼主| aoyi 发表于 2021-9-1 08:55 | 显示全部楼层
八、配置中断(ICONR,发生捕获时触发)

启动捕获功能时,每当发生捕获事件,当前的计数值就被保存到相应的捕获寄存器(GCMAR、GCMBR)中,本例使用GCMAR。我们开启ICONR寄存器中的最低位。

    /* Enable M4_TMR6_2 GCMAR interrupt */
    TMR6_IntCmd(M4_TMR6_2, TMR6_IRQ_EN_CNT_MATCH_A, Enable);

6807612ecf515dc1a.png

这样就可以在发生捕获时触发中断。
到这里总结一下,当外部上升沿进来时,TMR62会直接产生:

产生捕获事件
计数器清零0
进而由于产生捕获事件间接产生:

触发中断



 楼主| aoyi 发表于 2021-9-1 08:56 | 显示全部楼层
九、配置中断向量及回调函数(NVIC)

STM32F4的中断向量通道和对应功能是固定死的,而HC32F4A0的非常灵活,可以自由配置。不过使用STM32的标准库函数来配NVIC非常方便,所以移植了STM32F4的misc.c文件,来对HC32F4A0进行NVIC配置。移植的时候需要修改以下几处:

1.misc.h

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2N5cHJlc3N4dDkyNg==,size_16,color_FFFFFF,t_70.jpg
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2N5cHJlc3N4dDkyNg==,size_16,color_FFFFFF,t_70.jpg
2. misc.c

20210123172550256.png
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2N5cHJlc3N4dDkyNg==,size_16,color_FFFFFF,t_70.jpg
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2N5cHJlc3N4dDkyNg==,size_16,color_FFFFFF,t_70.jpg
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2N5cHJlc3N4dDkyNg==,size_16,color_FFFFFF,t_70.jpg

然后即可使用misc文件里面的函数来配置NVIC了。


/**因为HC32F4A0的中断向量通道与中断源以及相应的中断服务函数可以灵活映射,所以需要手动配置**/

        stcIrqRegiConf.enIRQn = Int003_IRQn;                    /* Register INT_TMR6_2_GCMA Int to Vect.No.003 */

    stcIrqRegiConf.enIntSrc = INT_TMR6_2_GCMA;              /* Select Event interrupt of M4_TMR6_2 */

    stcIrqRegiConf.pfnCallback = &Tmr6_2_CapInputCallBack;  /* Callback function */

    (void)INTC_IrqSignIn(&stcIrqRegiConf);  

   

/**后面就使用移植过来的misc文件中的库函数来配置NVIC了,注意ENABLE要改为Enable,其它跟STM32一样了**/

        NVIC_InitTypeDef NVIC_InitStructure;

        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

       

        NVIC_InitStructure.NVIC_IRQChannel = Int003_IRQn;      

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;               

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;                       

    NVIC_InitStructure.NVIC_IRQChannelCmd = Enable;

    NVIC_Init(&NVIC_InitStructure);



98518612ecf8f7487b.png

Intxxx_IRQn可选择为Int000_IRQn ~ Int031_IRQn,以及Int056_IRQn ~ Int061_IRQn。



您需要登录后才可以回帖 登录 | 注册

本版积分规则

101

主题

3316

帖子

3

粉丝
快速回复 返回顶部 返回列表