4953|1

9

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

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论坛

最新回复

是用在哪款芯片上的,可以在前面说明一下。  详情 回复 发表于 2022-3-11 13:15
点赞 关注
 

回复
举报

6992

帖子

11

TA的资源

版主

沙发
 
是用在哪款芯片上的,可以在前面说明一下。
此帖出自GD32 MCU论坛
 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
推荐帖子
硬件工程师必须知道的知识

目的:基于实际经验与实际项目详细理解并掌握成为合格的硬件工程师的最基本知识。 1) 基本设计规范 2) CPU基本知识、架构、 ...

Altera FPGA、CPLD 设计学习笔记

硬件设计基本原则 1) 速度与面积平衡和互换原则:一个设计如果时序余量较大,所能跑的频率远高于设计要求,能可以通过模块复用 ...

DSP基础知识集锦之二 DSP芯片的基本结构和特征

第2章 DSP芯片的基本结构和特征 2.1 引 言 可编程DSP芯片是一种具有特殊结构的微处理器,为了达到快速进行数字信号处理的目的,D ...

IAR-AVR常用例程一锅端:PS2键盘+红外遥控器+1602+12864+DS1302+AT24C02+UART等

各个功能的文件封装的比较规矩,方便大家移植过去用,IDE环境是IAR511B版本。 发贴的目的是方便大家移植常用的程序。 此板是我 ...

基于STM32F7的视觉小球颜色识别系统--完结

本帖最后由 wwchang 于 2015-12-28 10:29 编辑 项目名称:基于STM32F7的视觉小球颜色识别系统项目简介:用STM32F7驱动摄像头, ...

差分线后面并联一个三极管在串联一个10欧姆电阻有起什么作用

差分线后面并联一个三极管在串联一个10欧姆电阻有起什么作用

负离子发生器出口认证

目前有个项目,可能做出全球项目需要出口。 请问一下,除了满足车厂的企标之外,要怎么符合各地的安规标准呢? 做 ...

Silicon Labs BG22-EK4108A 开发套件 用科技连接未来 申请进行时!

Silicon Labs BG22-EK4108A 开发套件 用科技连接未来 申请进行时! >>点击申请 申请时间: 即日起-2021年1 ...

MATLAB Simulink系统仿真超级学习手册

全书共分为12章,首先介绍了MATLAB的基础知识,Simulink的仿真基础,Simulink高级仿真技术,以 及Simulink仿真应用。其中,Simul ...

开关电源产生振荡或者振铃该如何解决?

开关电源的输出波形存在震荡或者振铃波形,这和信号的反射引起的信号叠加,以及IGBT驱动波形在开通关断引起的过冲振铃等是否是同 ...

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

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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

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

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

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