1012|1

16

帖子

0

资源

一粒金砂(中级)

Timer定时器捕获 [复制链接]

本文记录timer定时器的捕获功能

 

1. 可以捕获任意长度的方波,测试毫秒级和秒级捕获没问题

2. 代码中的get_period和get_freq加了一个10s超时(TIMER_CAP_TIMEOUT),只捕获周期为10s以内的方波

3. 通过宏定义TIMER1_CH0_GPIO_A0、TIMER1_CH1_GPIO_A1、TIMER1_CH2_GPIO_B10、 TIMER1_CH3_GPIO_B11 选择其中一个通道用于捕获功能

4. 先调用timer_capture_config(),再调用timer_start_capture(),然后get_freq()或get_period()

 

源码如下:

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


中断处理函数

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

 

此帖出自GD32 MCU论坛

回复

1409

帖子

3

资源

版主

是用在哪款芯片上的,可以在前面说明一下。

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

查找数据手册?

EEWorld Datasheet 技术支持

最新文章 更多>>
    推荐帖子
    转——拆解——特斯拉的电动机

    437787作者:机械前线 最佳拆解小组又行动了,今天他们拆解了一部进水的特斯拉电动发动机,带大家一起看看特斯拉电动 ...

    PT1000电路求助

    X1端为PT1000外接电阻,温度-40°-180°。现在测得误差大概正负1℃。怎么修改能降低误差。

    点评下载资料,参加幸运抽奖,让我们迈开技术交流分享的步伐!!

    活动链接:点评下载资料,参加幸运抽奖,让我们迈开技术交流分享的步伐!! 请获得评论标兵奖的网友在确认期限前确认 ...

    Altium Designer19.1.6,Reports BOM 不生成BOM表,还会让AD19卡死,请问什么原因?

    本帖最后由 oyhprince 于 2021-3-27 17:55 编辑 软件:Altium Designer,版本19.1.6 问题:不管是原理图还是PCB界面,Repo ...

    DIY一个数控开关电源,你需要掌握这些知识

    想要成为一名合格的硬件工程师,熟练掌握电源知识至关重要—— 凡是在工作着的系统都必须要有电源,而电源是 ...

    颁奖:票选靠谱国产芯片MCU篇

    感谢坛友参与>> 票选靠谱国芯-MCU篇:测测测,一线坛友们都探测哪些靠谱国芯 活动。 本次活动获奖者如下,请获奖者在 ...

    关闭
    站长推荐上一条 1/8 下一条

    About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

    站点相关: 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

    北京市海淀区知春路23号集成电路设计园量子银座1305 电话:(010)82350740 邮编:100191

    电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2022 EEWORLD.com.cn, Inc. All rights reserved
    快速回复 返回顶部 返回列表