4677 views|1 replies

9

Posts

0

Resources
The OP
 

Timer capture [Copy link]

This article records the capture function of the timer

1. Can capture square waves of any length, test millisecond and second level capture is no problem

2. A 10s timeout (TIMER_CAP_TIMEOUT) is added to get_period and get_freq in the code to only capture square waves with a period of less than 10s.

3. Select one of the channels for the capture function through macro definition TIMER1_CH0_GPIO_A0, TIMER1_CH1_GPIO_A1, TIMER1_CH2_GPIO_B10, TIMER1_CH3_GPIO_B11

4. Call timer_capture_config() first, then call timer_start_capture(), then get_freq() or get_period()

The source code is as follows:

#include "timer.h"
#include "gd32l23x_timer.h"
#include "systick.h"


//#define TIMER1_CH0_GPIO_A0
//#define TIMER1_CH1_GPIO_A1
//#define TIMER1_CH2_GPIO_B10
#define TIMER1_CH3_GPIO_B11

/*
  capture timeout, 10s ,  unit: ms 
  The capture period is within TIMER_CAP_TIMEOUT 
*/
#define TIMER_CAP_TIMEOUT    10000U

#if defined TIMER1_CH0_GPIO_A0
    #define CAPTURE_TIMER_RCU  RCU_TIMER1
    #define CAPTURE_TIMER      TIMER1
    #define CAPTURE_CHN        TIMER_CH_0
    #define CAPTURE_INT_CHN    TIMER_INT_CH0
    #define CAPTURE_TIMER_IRQ  TIMER1_IRQn

    #define CAPTURE_GPIO_RCU   RCU_GPIOA
    #define CAPTURE_GPIO       GPIOA
    #define CAPTURE_GPIO_PIN   GPIO_PIN_0
    #define CAPTURE_GPIO_AF    GPIO_AF_1

#elif defined TIMER1_CH1_GPIO_A1
    #define CAPTURE_TIMER_RCU  RCU_TIMER1
    #define CAPTURE_TIMER      TIMER1
    #define CAPTURE_CHN        TIMER_CH_1
    #define CAPTURE_INT_CHN    TIMER_INT_CH1
    #define CAPTURE_TIMER_IRQ  TIMER1_IRQn

    #define CAPTURE_GPIO_RCU   RCU_GPIOA
    #define CAPTURE_GPIO       GPIOA
    #define CAPTURE_GPIO_PIN   GPIO_PIN_1
    #define CAPTURE_GPIO_AF    GPIO_AF_1

#elif defined TIMER1_CH2_GPIO_B10
    #define CAPTURE_TIMER_RCU  RCU_TIMER1
    #define CAPTURE_TIMER      TIMER1
    #define CAPTURE_CHN        TIMER_CH_2
    #define CAPTURE_INT_CHN    TIMER_INT_CH2
    #define CAPTURE_TIMER_IRQ  TIMER1_IRQn

    #define CAPTURE_GPIO_RCU   RCU_GPIOB
    #define CAPTURE_GPIO       GPIOB
    #define CAPTURE_GPIO_PIN   GPIO_PIN_10
    #define CAPTURE_GPIO_AF    GPIO_AF_1

#elif defined TIMER1_CH3_GPIO_B11
    #define CAPTURE_TIMER_RCU  RCU_TIMER1
    #define CAPTURE_TIMER      TIMER1
    #define CAPTURE_CHN        TIMER_CH_3
    #define CAPTURE_INT_CHN    TIMER_INT_CH3
    #define CAPTURE_TIMER_IRQ  TIMER1_IRQn

    #define CAPTURE_GPIO_RCU   RCU_GPIOB
    #define CAPTURE_GPIO       GPIOB
    #define CAPTURE_GPIO_PIN   GPIO_PIN_11
    #define CAPTURE_GPIO_AF    GPIO_AF_1

#endif

uint32_t readvalue1 = 0, readvalue2 = 0;
__IO uint16_t ccnumber = 0;
__IO uint32_t ccount = 0;
__IO uint16_t cap_finish_flag = 0;

/*!
    \brief      configure the GPIO ports
    \param[in]  none
    \param[out] none
    \retval     none
*/
static void timer_gpio_config(void)
{
    rcu_periph_clock_enable(CAPTURE_GPIO_RCU);
    /* TIMER1 GPIO */
    gpio_af_set(CAPTURE_GPIO, CAPTURE_GPIO_AF, CAPTURE_GPIO_PIN);
    gpio_mode_set(CAPTURE_GPIO, GPIO_MODE_AF, GPIO_PUPD_NONE, CAPTURE_GPIO_PIN);
    gpio_output_options_set(CAPTURE_GPIO, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, CAPTURE_GPIO_PIN);
}
/*!
    \brief      configure the TIMER peripheral
    \param[in]  none
    \param[out] none
    \retval     none
*/
void timer_capture_config(void)
{
    /* TIMER1 configuration: input capture mode -------------------
    the external signal is connected to TIMER1 CHx pin 
    the rising edge is used as active edge
    the TIMER1 CHxCV is used to compute the frequency value
    ------------------------------------------------------------ */
    timer_parameter_struct timer_initpara;
    timer_ic_parameter_struct timer_icinitpara;

    timer_gpio_config();

    /* enable the peripherals clock */
    rcu_periph_clock_enable(CAPTURE_TIMER_RCU);

    /* deinit a TIMER */
    timer_deinit(CAPTURE_TIMER);
    /* initialize TIMER init parameter struct */
    timer_struct_para_init(&timer_initpara);
    /* TIMER1 configuration */
    timer_initpara.prescaler        = 63;
    timer_initpara.alignedmode      = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection = TIMER_COUNTER_UP;
    timer_initpara.period           = 65535;
    timer_initpara.clockdivision    = TIMER_CKDIV_DIV1;
    timer_init(CAPTURE_TIMER, &timer_initpara);

    /* TIMER1 CHx input capture configuration */
    timer_icinitpara.icpolarity  = TIMER_IC_POLARITY_RISING;
    timer_icinitpara.icselection = TIMER_IC_SELECTION_DIRECTTI;
    timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1;
    timer_icinitpara.icfilter = 0x00;
    timer_input_capture_config(CAPTURE_TIMER, CAPTURE_CHN, &timer_icinitpara);

    /* auto-reload preload enable */
    timer_auto_reload_shadow_enable(CAPTURE_TIMER);

    /* enable a TIMER */
    timer_enable(CAPTURE_TIMER);

}


/*!
    \brief      timer start capture
    \param[in]  none
    \param[out] none
    \retval     none
*/
void timer_start_capture(void)
{
    cap_finish_flag = 0;
    ccnumber = 0;
    /* clear channel interrupt bit */
    timer_interrupt_flag_clear(CAPTURE_TIMER, CAPTURE_INT_CHN);
    /* channel interrupt enable */
    timer_interrupt_enable(CAPTURE_TIMER, CAPTURE_INT_CHN);
    /* clear channel interrupt bit */
    timer_interrupt_flag_clear(CAPTURE_TIMER, TIMER_INT_UP);
    /* channel interrupt enable */
    timer_interrupt_enable(CAPTURE_TIMER, TIMER_INT_UP);

    nvic_irq_enable(CAPTURE_TIMER_IRQ, 0);

}

/*!
    \brief      get frequency
    \param[in]  none
    \param[out] none
    \retval     float frequency, unit: Hz
*/
float get_freq(void)
{
    uint32_t timeout = 0;
    float freq = 0.0f;

    while(0 == cap_finish_flag)
    {
        delay_1ms(1u);
        timeout++;
        if(timeout > TIMER_CAP_TIMEOUT)
        {
            freq = 0;
            nvic_irq_disable(CAPTURE_TIMER_IRQ);
            timer_interrupt_disable(CAPTURE_TIMER, CAPTURE_INT_CHN);
            timer_interrupt_disable(CAPTURE_TIMER, TIMER_INT_UP);
            break;
        }
    }
    if (0 != ccount)
    {
        freq = 1000000.0f / (float)ccount;
    }

    return freq;
}

/*!
    \brief      get period
    \param[in]  none
    \param[out] none
    \retval     float period, unit: ms
*/
float get_period(void)
{
    uint32_t timeout = 0;
    float period = 0.0f;

    while(0 == cap_finish_flag)
    {
        delay_1ms(1u);
        timeout++;
        if(timeout > TIMER_CAP_TIMEOUT)
        {
            period = 0;
            nvic_irq_disable(CAPTURE_TIMER_IRQ);
            timer_interrupt_disable(CAPTURE_TIMER, CAPTURE_INT_CHN);
            timer_interrupt_disable(CAPTURE_TIMER, TIMER_INT_UP);
            break;
        }
    }
    if (timeout < TIMER_CAP_TIMEOUT)
    {
        period = (float)ccount/1000.0f;
    }

    return period;
}

/*!
    \brief      this function handles TIMER1 interrupt request.
    \param[in]  none
    \param[out] none
    \retval     none
*/
void timer_isr(void)
{
    static uint8_t cnt = 0;
    if(SET == timer_interrupt_flag_get(CAPTURE_TIMER, TIMER_INT_FLAG_UP)) {
        timer_interrupt_flag_clear(CAPTURE_TIMER, TIMER_INT_FLAG_UP);
        if(1 == ccnumber)
        {
            cnt++;
        }
    }
    if(SET == timer_interrupt_flag_get(CAPTURE_TIMER, CAPTURE_INT_CHN)) {
        /* clear channel x interrupt bit */
        timer_interrupt_flag_clear(CAPTURE_TIMER, CAPTURE_INT_CHN);

        if(0 == ccnumber) {
            /* read channel x capture value */
            readvalue1 = timer_channel_capture_value_register_read(CAPTURE_TIMER, CAPTURE_CHN) + 1;
            ccnumber = 1;
        } else if(1 == ccnumber) {
            /* read channel x capture value */
            readvalue2 = timer_channel_capture_value_register_read(CAPTURE_TIMER, CAPTURE_CHN) + 1;

            if(readvalue2 > readvalue1) {
                ccount = (0xFFFF * cnt + readvalue2 - readvalue1);
            } else {
                ccount = (0xFFFF * (cnt - 1) + (0xFFFF - readvalue1) + readvalue2);
            }
            cap_finish_flag = 1;
            ccnumber = 0;
            cnt = 0;
            nvic_irq_disable(CAPTURE_TIMER_IRQ);
            timer_interrupt_disable(CAPTURE_TIMER, CAPTURE_INT_CHN);
            timer_interrupt_disable(CAPTURE_TIMER, TIMER_INT_UP);
        }
    }
}


Interrupt handling function

extern void timer_isr(void);
/*!
    \brief      this function handles TIMER1 interrupt request.
    \param[in]  none
    \param[out] none
    \retval     none
*/
void TIMER1_IRQHandler(void)
{
    timer_isr();
}

This post is from GD32 MCU

Latest reply

Which chip is used on? Can you explain it in the front?  Details Published on 2022-3-11 13:15
 

6818

Posts

11

Resources
2
 
Which chip is used on? Can you explain it in the front?
This post is from GD32 MCU
 
 
 

Guess Your Favourite
Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list