问答

汇集网友智慧,解决技术难题

21ic问答首页 - GD32F305VG timer0输入捕获无反应

输入捕获 GD32 高级定时器 GD32F305 TIMER0 ic

GD32F305VG timer0输入捕获无反应

CapSean2021-04-25
各位大佬好!      我按照GD32F30x的标准库配置了GD32F305VG 的timer0定时器并开启了输入捕获功能,配置代码如下:
void timer_config(void)
{
/* -----------------------------------------------------------------------
    timer_parameter_struct timer_initpara;
    timer_ic_parameter_struct timer_icinitpara;

    rcu_periph_clock_enable(RCU_TIMER0);

    timer_deinit(TIMER0);

    /*NVIC config*/
    nvic_irq_enable(TIMER0_UP_TIMER9_IRQn, 1, 1);
    nvic_irq_enable(TIMER0_Channel_IRQn, 1, 0);
    /* TIMER0 configuration */
    timer_initpara.prescaler         = 119;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = 999;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMER0, &timer_initpara);

    timer_icinitpara.icpolarity      = TIMER_IC_POLARITY_RISING;
    timer_icinitpara.icselection     = TIMER_IC_SELECTION_DIRECTTI;
    timer_icinitpara.icprescaler     = TIMER_IC_PSC_DIV1;
    timer_icinitpara.icfilter        = 0x0;
    timer_input_capture_config(TIMER0, TIMER_CH_0, &timer_icinitpara);

    timer_input_capture_config(TIMER0, TIMER_CH_3, &timer_icinitpara);

    /* auto-reload preload enable */
    timer_auto_reload_shadow_enable(TIMER0);
    timer_interrupt_flag_clear(TIMER0,TIMER_INT_FLAG_CH0);
    timer_interrupt_flag_clear(TIMER0,TIMER_INT_FLAG_CH3);
    timer_interrupt_enable(TIMER0,TIMER_INT_CH0);
    timer_interrupt_enable(TIMER0,TIMER_INT_CH3);
    timer_interrupt_enable(TIMER0,TIMER_INT_UP);
    timer_enable(TIMER0);
}


/*中断服务程序*/
void TIMER0_UP_TIMER9_IRQHandler(void) {

  if ( timer_interrupt_flag_get(TIMER0, TIMER_INT_FLAG_UP) != RESET ) {
    timer_interrupt_flag_clear(TIMER0, TIMER_INT_FLAG_UP);
    timer0tick++;
  }
}

void TIMER0_Channel_IRQHandler() {

  if ( timer_interrupt_flag_get(TIMER0, TIMER_INT_FLAG_CH0) != RESET) {
    timer_interrupt_flag_clear(TIMER0, TIMER_INT_FLAG_CH0);
  }
  else if (timer_interrupt_flag_get(TIMER0, TIMER_INT_FLAG_CH3) != RESET){   
    timer_interrupt_flag_clear(TIMER0, TIMER_INT_FLAG_CH3);
    rcvcnt++;
  }
}


    TIMER0 CH0和CH3的GPIO口确定可以正常检测到高低电平,然而软件在运行中,只有更新中断是正常的,输入捕获中断一直触发不了,不知道各位大佬们是否有遇到过此类问题,恳请指点一二,感谢!
回答 +关注 6
2229人浏览 5人回答问题 分享 举报
5 个回答
  • 另外附上在GD标准库main()函数基础上修改的代码,已测试验证过。
    /*!
        \file    main.c
        \brief   TIMER0 complementary signals demo for gd32f30x

        \version 2017-02-10, V1.0.0, firmware for GD32F30x
        \version 2018-10-10, V1.1.0, firmware for GD32F30x
        \version 2018-12-25, V2.0.0, firmware for GD32F30x
        \version 2020-09-30, V2.1.0, firmware for GD32F30x
    */

    /*
        Copyright (c) 2020, GigaDevice Semiconductor Inc.

        Redistribution and use in source and binary forms, with or without modification,
    are permitted provided that the following conditions are met:

        1. Redistributions of source code must retain the above copyright notice, this
           list of conditions and the following disclaimer.
        2. Redistributions in binary form must reproduce the above copyright notice,
           this list of conditions and the following disclaimer in the documentation
           and/or other materials provided with the distribution.
        3. Neither the name of the copyright holder nor the names of its contributors
           may be used to endorse or promote products derived from this software without
           specific prior written permission.

        THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
    OF SUCH DAMAGE.
    */

    #include <stdio.h>
    #include "gd32f30x_it.h"
    #include "systick.h"

    void gpio_config(void);
    void timer0_config(void);

    extern uint32_t timer0tick;
    /*!
        \brief      configure the GPIO ports
        \param[in]  none
        \param[out] none
        \retval     none
    */
    void gpio_config(void) {
      rcu_periph_clock_enable(RCU_GPIOC);
      /*cofig PC11 as output PP mdoe*/
      gpio_init(GPIOC, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, GPIO_PIN_11);
    }

    void timer0_gpio_config(void)
    {
        rcu_periph_clock_enable(RCU_GPIOE);
        rcu_periph_clock_enable(RCU_AF);

        /*configure PE9 PE14(TIMER0 CH0 CH3) as alternate function*/
        gpio_init(GPIOE,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_10MHZ,GPIO_PIN_9|GPIO_PIN_14);
       
        /*
        * GD32F30x标准库提供的例程虽然在GPIO初始化时有注释“configre xxx as alternate function”,
        * 但是只对GPIO做了基本的初始化,并未进行端口重映射,当然这一点对于老手来说应该很容易注意到,
        * 但是对外设配置不熟悉的新人来说很容易被误导,注意添加下方的端口重映射函数!  
        */
        gpio_pin_remap_config(GPIO_TIMER0_FULL_REMAP, ENABLE);
    }

    /*!
        \brief      configure the TIMER peripheral
        \param[in]  none
        \param[out] none
        \retval     none
    */
    void timer0_config(void)
    {

        timer_parameter_struct timer_initpara;
        timer_ic_parameter_struct timer_icinitpara;

        timer0_gpio_config();

        rcu_periph_clock_enable(RCU_TIMER0);

        timer_deinit(TIMER0);
       
        /*NVIC config*/
        nvic_irq_enable(TIMER0_UP_TIMER9_IRQn, 1, 1);
        nvic_irq_enable(TIMER0_Channel_IRQn, 1, 0);
        /* TIMER0 configuration */
        timer_initpara.prescaler         = 119;
        timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
        timer_initpara.counterdirection  = TIMER_COUNTER_UP;
        timer_initpara.period            = 999;
        timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
        timer_initpara.repetitioncounter = 0;
        timer_init(TIMER0, &timer_initpara);

        timer_icinitpara.icpolarity      = TIMER_IC_POLARITY_RISING;
        timer_icinitpara.icselection     = TIMER_IC_SELECTION_DIRECTTI;
        timer_icinitpara.icprescaler     = TIMER_IC_PSC_DIV1;
        timer_icinitpara.icfilter        = 0x0;
        timer_input_capture_config(TIMER0, TIMER_CH_0, &timer_icinitpara);

        timer_input_capture_config(TIMER0, TIMER_CH_3, &timer_icinitpara);
       
        /* auto-reload preload enable */
        timer_auto_reload_shadow_enable(TIMER0);
       
        timer_interrupt_flag_clear(TIMER0,TIMER_INT_FLAG_CH0);
        timer_interrupt_flag_clear(TIMER0,TIMER_INT_FLAG_CH3);
        timer_interrupt_enable(TIMER0,TIMER_INT_CH0);
        timer_interrupt_enable(TIMER0,TIMER_INT_CH3);
        timer_interrupt_enable(TIMER0,TIMER_INT_UP);
       
       
        timer_enable(TIMER0);
    }


    void gpio_togglepin(uint32_t gpio_periph, uint32_t pin) {
      
      if ( GPIO_OCTL(gpio_periph) & pin) {
        GPIO_BC(gpio_periph) = pin;
      }
      else {
        GPIO_BOP(gpio_periph) = pin;
      }

    }
    /*!
        \brief      main function
        \param[in]  none
        \param[out] none
        \retval     none
    */
    int main(void)
    {
        static uint32_t tick = 0;
        nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
        systick_config();
        gpio_config();
        timer0_config();  
        tick = timer0tick;
        while (1) {
          gpio_bit_set(GPIOC, GPIO_PIN_11);
          delay_1ms(500);
          gpio_bit_reset(GPIOC, GPIO_PIN_11);
          delay_1ms(500);
        }
    }
  • sonicll 发表于 2021-4-25 15:39
    PE9和PE14需要配置remap才能作为TIMER0的通道使用:

    rcu_periph_clock_enable(RCU_AF);

    再此感谢答复,问题已经解决!确实问题在你说的端口重映射上,增加端口重映射后,输入捕获可以正常工作了。GD提供的标准库没有添加端口重映射函数,可能是因为有多种重映射方式可选择,所以留给了用户自己添加。这点对于老手来说应该很容易注意到,但感觉比较容易误导新人。
  • CapSean 发表于 2021-4-25 15:08
    谢谢回复!
    Timer0的CH0和CH3分别用的PE9和PE14管脚,因为管脚输入端口上拉并用二极管做了输入保护,所以 ...

    PE9和PE14需要配置remap才能作为TIMER0的通道使用:

    rcu_periph_clock_enable(RCU_AF);
    gpio_pin_remap_config(GPIO_TIMER0_FULL_REMAP, ENABLE);
  • sonicll 发表于 2021-4-25 14:17
    timer配置应该没有问题,你用的是哪两个GPIO,确定这个两个GPIO是TIMER0的CH0和CH3吗? ...

    谢谢回复!
    Timer0的CH0和CH3分别用的PE9和PE14管脚,因为管脚输入端口上拉并用二极管做了输入保护,所以先通过给这两个管脚高电平和低电平检查输入回路信号是否可以正确到达MCU, 现在确定在IO模式下两个端口可以正确测到高低电平。但是在定时器输入捕获模式下,信号边沿检测始终没有触发。最初我是用的ST F10X标准库做的功能,输入捕获没有成功所以又基于GD32 的F30x标准库做了改动来验证功能,结果还是没有成功。现在因为没有输入捕获功能正常的Demo来比对,所以不太清楚是硬件问题还是软件没有配置对。再次感谢关注这个问题。
  • timer配置应该没有问题,你用的是哪两个GPIO,确定这个两个GPIO是TIMER0的CH0和CH3吗?

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