[技术问答] HC32F460 Timer6 捕获脉宽(高电平)

[复制链接]
 楼主| 茂xiang 发表于 2021-9-1 12:32 | 显示全部楼层 |阅读模式
HC32F460 Timer6想要测量高电平脉宽时间(超声波模块),参考示例,使用PB2 TrigB引脚,MCU给一个仿真脉冲时没有任何反应,大家帮看下是什么原因
  1. #include "hc32_ddl.h"
  2. #include "hal_CLK.h"
  3. #include "hc32f46x_timer6.h"
  4. #include "sysGeneralFunc.h"

  5. /******************************************************************************/
  6. /** \file main.c
  7. **
  8. ** \brief This sample demonstrates how to use Timer6.
  9. **
  10. **   - 2018-11-30  1.0  husj  first version for Device Driver Library of Timer6.
  11. **
  12. ******************************************************************************/

  13. #include "hc32_ddl.h"

  14. /*******************************************************************************
  15. * Local type definitions ('typedef')
  16. ******************************************************************************/

  17. /*******************************************************************************
  18. * Local pre-processor symbols/macros ('#define')
  19. ******************************************************************************/
  20. /* KEY0 (SW2)*/
  21. #define  SW2_PORT           (PortD)
  22. #define  SW2_PIN            (Pin03)
  23. /* KEY1 (SW4)*/
  24. #define  SW4_PORT           (PortD)
  25. #define  SW4_PIN            (Pin04)
  26. /* KEY2 (SW3)*/
  27. #define  SW3_PORT           (PortD)
  28. #define  SW3_PIN            (Pin05)
  29. /* KEY3 (SW5)*/
  30. #define  SW5_PORT           (PortD)
  31. #define  SW5_PIN            (Pin06)

  32. /* LED0 Port/Pin definition */
  33. #define  LED0_PORT          (PortE)
  34. #define  LED0_PIN           (Pin06)

  35. /* LED1 Port/Pin definition */
  36. #define  LED1_PORT          (PortD)
  37. #define  LED1_PIN           (Pin07)

  38. /* LED2 Port/Pin definition */
  39. #define  LED2_PORT          (PortB)
  40. #define  LED2_PIN           (Pin05)

  41. /* LED3 Port/Pin definition */
  42. #define  LED3_PORT          (PortB)
  43. #define  LED3_PIN           (Pin09)

  44. /* LED0~1 toggle definition */
  45. #define  LED0_TOGGLE()      (PORT_Toggle(LED0_PORT, LED0_PIN))
  46. #define  LED1_TOGGLE()      (PORT_Toggle(LED1_PORT, LED1_PIN))
  47. #define  LED2_TOGGLE()      (PORT_Toggle(LED2_PORT, LED2_PIN))
  48. #define  LED3_TOGGLE()      (PORT_Toggle(LED3_PORT, LED3_PIN))

  49. /*******************************************************************************
  50. * Global variable definitions (declared in header file with 'extern')
  51. ******************************************************************************/
  52. uint16_t u16CaptureA;
  53. uint16_t u16CaptureC;
  54. float ftCapDuty;

  55. //问题,溢出怎么办?-->溢出直接进入中断了
  56. //捕获中断但是下降沿怎么获取?
  57. uint8_t capFlag=0;
  58. void Timer62_CapInputCallBack(void)
  59. {
  60.         if(!capFlag){
  61.                 capFlag=1;
  62.                 u16CaptureA = Timer6_GetGeneralCmpValue(M4_TMR62, Timer6GenCompareB);
  63.         }else{
  64.                 capFlag=0;
  65.                 u16CaptureC = Timer6_GetGeneralCmpValue(M4_TMR62, Timer6GenCompareB);
  66.                 //计算 u16CaptureC - u16CaptureA
  67.         }
  68.    
  69. //    if(0u == M4_PORT->PCRE11_f.PIN)
  70. //    {
  71. //        ftCapDuty = (float)u16CaptureC / (float)u16CaptureA;
  72. //    }
  73. }

  74. /**
  75. ******************************************************************************
  76. ** \brief  Initialize the system clock for the sample
  77. **
  78. ** \param  None
  79. **
  80. ** \return None
  81. ******************************************************************************/
  82. static void SysClkIni(void)
  83. {
  84.     en_clk_sys_source_t       enSysClkSrc;
  85.     stc_clk_sysclk_cfg_t      stcSysClkCfg;
  86.     stc_clk_mpll_cfg_t        stcMpllCfg;

  87.     MEM_ZERO_STRUCT(enSysClkSrc);
  88.     MEM_ZERO_STRUCT(stcSysClkCfg);
  89.     MEM_ZERO_STRUCT(stcMpllCfg);

  90.     /* Set bus clk div. */
  91.     stcSysClkCfg.enHclkDiv = ClkSysclkDiv1;   // 168MHz
  92.     stcSysClkCfg.enExclkDiv = ClkSysclkDiv2;  // 84MHz

  93.     stcSysClkCfg.enPclk0Div = ClkSysclkDiv1;  // 168MHz
  94.     stcSysClkCfg.enPclk1Div = ClkSysclkDiv2;  // 84MHz
  95.     stcSysClkCfg.enPclk2Div = ClkSysclkDiv4;  // 42MHz
  96.     stcSysClkCfg.enPclk3Div = ClkSysclkDiv4;  // 42MHz
  97.     stcSysClkCfg.enPclk4Div = ClkSysclkDiv2;  // 84MHz
  98.     CLK_SysClkConfig(&stcSysClkCfg);

  99.     CLK_HrcCmd(Enable);       //Enable HRC

  100.     /* MPLL config. */
  101.     stcMpllCfg.pllmDiv = 2ul;   //HRC 16M / 2
  102.     stcMpllCfg.plln    = 42ul;  //8M*42 = 336M
  103.     stcMpllCfg.PllpDiv = 2ul;   //MLLP = 168M
  104.     stcMpllCfg.PllqDiv = 2ul;   //MLLQ = 168M
  105.     stcMpllCfg.PllrDiv = 2ul;   //MLLR = 168M
  106.     CLK_SetPllSource(ClkPllSrcHRC);
  107.     CLK_MpllConfig(&stcMpllCfg);

  108.     /* flash read wait cycle setting */
  109.     EFM_Unlock();
  110.     EFM_SetLatency(EFM_LATENCY_4);
  111.     EFM_Lock();

  112.     /* Enable MPLL. */
  113.     CLK_MpllCmd(Enable);

  114.     /* Wait MPLL ready. */
  115.     while(Set != CLK_GetFlagStatus(ClkFlagMPLLRdy))
  116.     {
  117.         ;
  118.     }

  119.     /* Switch system clock source to MPLL. */
  120.     CLK_SetSysClkSource(CLKSysSrcMPLL);
  121. }


  122. #define IO_TEST_PORT        (PortB)
  123. #define IO_TEST_PIN                (Pin10)
  124. #define IO_TEST_OUT_H        PORT_SetBits(IO_TEST_PORT, IO_TEST_PIN)
  125. #define IO_TEST_OUT_L        PORT_ResetBits(IO_TEST_PORT, IO_TEST_PIN)


  126. /*******************************************************************************
  127. *名    称:IIC_IO_Init(void)
  128. *功    能:软件IIC,IO口输出初始化
  129. *说    明:
  130. *修    改:
  131. *******************************************************************************/
  132. void IO_OUT_Init(){
  133.         stc_port_init_t stcPortInit;
  134.         MEM_ZERO_STRUCT(stcPortInit);                                                //必须初始化结构体,否则IO口设置异常 21-06-08(IO翻转对比测试)
  135.         stcPortInit.enPinMode = Pin_Mode_Out;
  136.     stcPortInit.enExInt = Disable;
  137.     stcPortInit.enPullUp = Disable;

  138.         IO_TEST_OUT_H;                                                                                //IO输出高低必须写在前面,初始化默认是低电平,否则会有一个脉冲
  139.         PORT_Init(IO_TEST_PORT, IO_TEST_PIN, &stcPortInit);
  140. }


  141. /**
  142. *******************************************************************************
  143. ** \brief  Main function of project
  144. **
  145. ** \param  None
  146. **
  147. ** \retval int32_t return value, if needed
  148. **
  149. ******************************************************************************/
  150. int32_t main(void)
  151. {
  152.     uint16_t                         u16Period;
  153.     uint16_t                         u16Compare;
  154.     stc_timer6_basecnt_cfg_t         stcTIM6BaseCntCfg;
  155.     stc_timer6_port_output_cfg_t     stcTIM6PWMxCfg;
  156.     stc_timer6_port_input_cfg_t      stcTIM6CapxCfg;
  157.     stc_timer6_gcmp_buf_cfg_t        stcGCMPBufCfg;
  158.     stc_port_init_t                  stcPortInit;
  159.     stc_irq_regi_conf_t              stcIrqRegiConf;
  160.     stc_timer6_sw_sync_t             stcSwSyncStart;

  161.     MEM_ZERO_STRUCT(stcTIM6BaseCntCfg);
  162.     MEM_ZERO_STRUCT(stcTIM6PWMxCfg);
  163.     MEM_ZERO_STRUCT(stcTIM6CapxCfg);
  164.     MEM_ZERO_STRUCT(stcGCMPBufCfg);
  165.     MEM_ZERO_STRUCT(stcPortInit);
  166.     MEM_ZERO_STRUCT(stcIrqRegiConf);
  167.     MEM_ZERO_STRUCT(stcSwSyncStart);

  168.     SysClkIni();                                                                                        //系统时钟,PCLK0 168MHz
  169.     PWC_Fcg2PeriphClockCmd(PWC_FCG2_PERIPH_TIM62, Enable);        //TIM62时钟使能

  170.         //设置1:PB2设置捕获输入口
  171.     PORT_SetFunc(PortB, Pin02, Func_Tim6, Disable);                  //Timer62 TrigB

  172.     /******************Config Timer62 count mode*************************/
  173.     stcTIM6BaseCntCfg.enCntMode   = Timer6CntSawtoothMode;              //Sawtooth wave mode
  174.     stcTIM6BaseCntCfg.enCntDir    = Timer6CntDirUp;                     //Counter counting up
  175.     stcTIM6BaseCntCfg.enCntClkDiv = Timer6PclkDiv1024;                  //Count clock: pclk0/1024
  176.     Timer6_Init(M4_TMR62, &stcTIM6BaseCntCfg);                          //timer6 PWM frequency, count mode and clk config
  177.     u16Period = 0xFFFFu;                                                                                                //168MHz/1024/0xffff=2.5Hz   164K频率,计满400mS
  178.     Timer6_SetPeriod(M4_TMR62, Timer6PeriodA, u16Period);               //Period set
  179.        
  180.         /*捕获输入源设置*/
  181.         stcTIM6CapxCfg.enPortSel  = Timer6TrigB;                           //Capture Input Port: TIME6_TRIGB
  182.         stcTIM6CapxCfg.enPortMode = Timer6ModeCaptureInput;                //Capture input function
  183.         stcTIM6CapxCfg.bFltEn     = false;                                 //Input filter disable
  184.         stcTIM6CapxCfg.enFltClk   = Timer6FltClkPclk0Div16;                //Filter clock,不影响,不使能filter
  185.         Timer6_PortInputConfig(M4_TMR62, &stcTIM6CapxCfg);                 //Input config TMR6x->FCONR_f.NOFIENTB
  186.        
  187.         /*脉宽测量,上升沿启动,下降沿清0,停止条件下降沿*/
  188.         Timer6_ConfigHwCaptureB(M4_TMR62, Timer6HwTrigTimTriBRise);               //HW Capture: timer6TrigB port rise trig
  189.         Timer6_ConfigHwClear(M4_TMR62, Timer6HwTrigTimTriBRise);                  //HW Clear: 配置硬件清零事件选择寄存器(HCLRR),使得每次发生捕获事件后,计数器从0开始重新计数。
  190.         Timer6_ConfigHwStop(M4_TMR62, Timer6HwTrigTimTriBFall);                                //HW Stop: imer6TrigB port fall trig
  191.         Timer6_EnableHwClear(M4_TMR62);
  192.        
  193.     /*config interrupt*/
  194.     /* Enable timer62 GCMAR interrupt */
  195.     Timer6_ConfigIrq(M4_TMR62, Timer6INTENB, true);                                                //捕获中断

  196.     stcIrqRegiConf.enIRQn = Int003_IRQn;                                            //Register INT_TMR61_GUDF Int to Vect.No.002
  197.     stcIrqRegiConf.enIntSrc = INT_TMR62_GCMB;                                       //Select Event interrupt function
  198.     stcIrqRegiConf.pfnCallback = &Timer62_CapInputCallBack;                          //Callback function
  199.     enIrqRegistration(&stcIrqRegiConf);                                             //Registration IRQ

  200.     NVIC_ClearPendingIRQ(stcIrqRegiConf.enIRQn);                                    //Clear Pending
  201.     NVIC_SetPriority(stcIrqRegiConf.enIRQn, DDL_IRQ_PRIORITY_04);                //Set priority
  202.     NVIC_EnableIRQ(stcIrqRegiConf.enIRQn);                                           //Enable NVIC

  203.     /*start timer6*/
  204. //    stcSwSyncStart.bTimer62 = true;
  205. //    Timer6_SwSyncStart(&stcSwSyncStart);

  206.         IO_OUT_Init();
  207.         while(1){
  208.                 __NOP();                        //断点
  209.                 IO_TEST_OUT_H;                //高电平1mS捕获测试
  210.                 Delay_ms(1);
  211.                 IO_TEST_OUT_L;                //低电平5S
  212.                 Delay_ms(5000);
  213.         }
  214. }






martinhu 发表于 2021-9-1 13:54 | 显示全部楼层
你前面配置的代码并不能启动Timer62,缺少了启动Timer62计数的语句。这句得释放开注释。或者Timer6_StartCount(M4_TMR62);
21003612f14cfa2711.png

martinhu 发表于 2021-9-1 14:03 | 显示全部楼层
楼主这样配置代码,其实是在每个上升沿的时候捕获计数值,并且清零,
配置了硬件停止,但是没有使能硬件停止功能,所以无效。
这样楼主的这段代码,其实是实现了测量每次的周期,不是脉宽。
56116612f1638127c6.png
如果是要测量高电平脉宽,可以设置为每次上升沿的时候硬件清零计数器,下降沿的是硬件捕获
这样可以不需要停止定时器,自动捕获高电平脉宽。
51290612f178daa579.png
sf116 发表于 2021-9-1 16:21 | 显示全部楼层
/*PWMA input buffer config*/
    stcGCMPBufCfg.bEnGcmpTransBuf = true;
    stcGCMPBufCfg.enGcmpBufTransType = Timer6GcmpPrdSingleBuf;         //Single buffer transfer
    Timer6_SetGeneralBuf(M4_TMR61, Timer6PWMA, &stcGCMPBufCfg);        //GCMAR buffer transfer set
   
    stcTIM6CapxCfg.enPortSel  = Timer6xCHA;                            //Capture Input Port: PWM A port
    stcTIM6CapxCfg.enPortMode = Timer6ModeCaptureInput;                //Capture input function
    stcTIM6CapxCfg.bFltEn     = true;                                  //Input filter enable
    stcTIM6CapxCfg.enFltClk   = Timer6FltClkPclk0Div16;                //Filter clock
    Timer6_PortInputConfig(M4_TMR61, &stcTIM6CapxCfg);                 //Input config

        //Capture Cycle&H
    Timer6_ConfigHwCaptureA(M4_TMR61, Timer6HwTrigPWMAFall);       //HW Capture: Timer6 PWMA port rise trig
    Timer6_ConfigHwCaptureA(M4_TMR61, Timer6HwTrigPWMARise);       //HW Capture: Timer6 PWMA port rise trig
   
    Timer6_ConfigHwClear(M4_TMR61, Timer6HwTrigPWMAFall);          //HW Clear: Timer6 PWMA port rise trig,条件匹配时,硬件清零有效
    Timer6_EnableHwClear(M4_TMR61);

启用单缓存,同时捕获高电平脉宽和周期脉宽

void Timer62_A_CapInputCallBack(void)
{
        static uint16_t HPulseGcmarShadow, LPulseGcmarShadow;
        HPulseGcmarShadow = Timer6_GetGeneralCmpValue(M4_TMR62, Timer6GenCompareA);
    LPulseGcmarShadow = Timer6_GetGeneralCmpValue(M4_TMR62, Timer6GenCompareC);
    //if(1u == M4_PORT->PCRE11_f.PIN)
    {
        TIM62_PWMA.HPulseGcmar = HPulseGcmarShadow;
                TIM62_PWMA.LPulseGcmar = LPulseGcmarShadow;
    }
}
skyred 发表于 2021-9-2 15:44 | 显示全部楼层
定时器,学习了
您需要登录后才可以回帖 登录 | 注册

本版积分规则

6

主题

13

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部

6

主题

13

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部