打印
[技术问答]

HC32F460 Timer6 捕获脉宽(高电平)

[复制链接]
6120|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
HC32F460 Timer6想要测量高电平脉宽时间(超声波模块),参考示例,使用PB2 TrigB引脚,MCU给一个仿真脉冲时没有任何反应,大家帮看下是什么原因
#include "hc32_ddl.h"
#include "hal_CLK.h"
#include "hc32f46x_timer6.h"
#include "sysGeneralFunc.h"

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

#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')
******************************************************************************/
uint16_t u16CaptureA;
uint16_t u16CaptureC;
float ftCapDuty;

//问题,溢出怎么办?-->溢出直接进入中断了
//捕获中断但是下降沿怎么获取?
uint8_t capFlag=0;
void Timer62_CapInputCallBack(void)
{
        if(!capFlag){
                capFlag=1;
                u16CaptureA = Timer6_GetGeneralCmpValue(M4_TMR62, Timer6GenCompareB);
        }else{
                capFlag=0;
                u16CaptureC = Timer6_GetGeneralCmpValue(M4_TMR62, Timer6GenCompareB);
                //计算 u16CaptureC - u16CaptureA
        }
   
//    if(0u == M4_PORT->PCRE11_f.PIN)
//    {
//        ftCapDuty = (float)u16CaptureC / (float)u16CaptureA;
//    }
}

/**
******************************************************************************
** \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;

    MEM_ZERO_STRUCT(enSysClkSrc);
    MEM_ZERO_STRUCT(stcSysClkCfg);
    MEM_ZERO_STRUCT(stcMpllCfg);

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

    stcSysClkCfg.enPclk0Div = ClkSysclkDiv1;  // 168MHz
    stcSysClkCfg.enPclk1Div = ClkSysclkDiv2;  // 84MHz
    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);
}


#define IO_TEST_PORT        (PortB)
#define IO_TEST_PIN                (Pin10)
#define IO_TEST_OUT_H        PORT_SetBits(IO_TEST_PORT, IO_TEST_PIN)
#define IO_TEST_OUT_L        PORT_ResetBits(IO_TEST_PORT, IO_TEST_PIN)


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

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


/**
*******************************************************************************
** \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_port_input_cfg_t      stcTIM6CapxCfg;
    stc_timer6_gcmp_buf_cfg_t        stcGCMPBufCfg;
    stc_port_init_t                  stcPortInit;
    stc_irq_regi_conf_t              stcIrqRegiConf;
    stc_timer6_sw_sync_t             stcSwSyncStart;

    MEM_ZERO_STRUCT(stcTIM6BaseCntCfg);
    MEM_ZERO_STRUCT(stcTIM6PWMxCfg);
    MEM_ZERO_STRUCT(stcTIM6CapxCfg);
    MEM_ZERO_STRUCT(stcGCMPBufCfg);
    MEM_ZERO_STRUCT(stcPortInit);
    MEM_ZERO_STRUCT(stcIrqRegiConf);
    MEM_ZERO_STRUCT(stcSwSyncStart);

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

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

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

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

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

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

        IO_OUT_Init();
        while(1){
                __NOP();                        //断点
                IO_TEST_OUT_H;                //高电平1mS捕获测试
                Delay_ms(1);
                IO_TEST_OUT_L;                //低电平5S
                Delay_ms(5000);
        }
}






使用特权

评论回复
沙发
martinhu| | 2021-9-1 13:54 | 只看该作者
你前面配置的代码并不能启动Timer62,缺少了启动Timer62计数的语句。这句得释放开注释。或者Timer6_StartCount(M4_TMR62);


使用特权

评论回复
板凳
martinhu| | 2021-9-1 14:03 | 只看该作者
楼主这样配置代码,其实是在每个上升沿的时候捕获计数值,并且清零,
配置了硬件停止,但是没有使能硬件停止功能,所以无效。
这样楼主的这段代码,其实是实现了测量每次的周期,不是脉宽。

如果是要测量高电平脉宽,可以设置为每次上升沿的时候硬件清零计数器,下降沿的是硬件捕获
这样可以不需要停止定时器,自动捕获高电平脉宽。

使用特权

评论回复
地板
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;
    }
}

使用特权

评论回复
5
skyred| | 2021-9-2 15:44 | 只看该作者
定时器,学习了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

6

主题

13

帖子

1

粉丝