GD32定时器输入捕获例程

官方的例程

/**
    \brief      configure the GPIO ports
    \param[in]  none
    \param[out] none
    \retval     none
  */
void gpio_configuration(void)
{
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_AF);

    /*configure PA6 (TIMER2 CH0) as alternate function*/
    gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
}

/**
    \brief      configure the nested vectored interrupt controller
    \param[in]  none
    \param[out] none
    \retval     none
  */
void nvic_configuration(void)
{
    nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3);
    nvic_irq_enable(TIMER2_IRQn, 1, 1);
}

/**
    \brief      configure the TIMER peripheral
    \param[in]  none
    \param[out] none
    \retval     none
  */
void timer_configuration(void)
{
    /* TIMER2 configuration: input capture mode -------------------
    the external signal is connected to TIMER2 CH0 pin (PA6)
    the rising edge is used as active edge
    the TIMER2 CH0CV is used to compute the frequency value
    ------------------------------------------------------------ */
    timer_ic_parameter_struct timer_icinitpara;
    timer_parameter_struct timer_initpara;

    rcu_periph_clock_enable(RCU_TIMER2);

    timer_deinit(TIMER2);

    /* TIMER2 configuration */
    timer_initpara.prescaler         = 107;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = 65535;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMER2,&timer_initpara);

    /* TIMER2  configuration */
    /* TIMER2 CH0 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    = 0x0;
    timer_input_capture_config(TIMER2,TIMER_CH_0,&timer_icinitpara);

    /* auto-reload preload enable */
    timer_auto_reload_shadow_enable(TIMER2);
    /* clear channel 0 interrupt bit */
    timer_interrupt_flag_clear(TIMER2,TIMER_INT_CH0);
    /* channel 0 interrupt enable */
    timer_interrupt_enable(TIMER2,TIMER_INT_CH0);

    /* TIMER2 counter enable */
    timer_enable(TIMER2);
}

/*!
    \brief      main function
    \param[in]  none
    \param[out] none
    \retval     none
*/
int main(void)
{
    gpio_configuration(); 
    gd_eval_com_init(EVAL_COM1);
    nvic_configuration();
    timer_configuration();

    while (1);
}

/**
  * @brief  This function handles TIMER2 interrupt request.
  * @param  None
  * @retval None
  */
void TIMER2_IRQHandler(void)
{
    if(SET == timer_interrupt_flag_get(TIMER2,TIMER_INT_CH0)){
        /* clear channel 0 interrupt bit */
        timer_interrupt_flag_clear(TIMER2,TIMER_INT_CH0);

        if(0 == ccnumber){
            /* read channel 0 capture value */
            readvalue1 = timer_channel_capture_value_register_read(TIMER2,TIMER_CH_0);
            ccnumber = 1;
        }else if(1 == ccnumber){
            /* read channel 0 capture value */
            readvalue2 = timer_channel_capture_value_register_read(TIMER2,TIMER_CH_0);

            if(readvalue2 > readvalue1){
                count = (readvalue2 - readvalue1); 
            }else{
                count = ((0xFFFF - readvalue1) + readvalue2); 
            }

            fre = (float)1000000 / count;
            printf("the value1 is %d,the value2 is %d\n",readvalue1,readvalue2);
            printf("the count is %d\n",count);
            printf("the frequence is %f\n",fre);
            ccnumber = 0;
        }
    }
}

自己修改使用的

void ACSig_In_Capture_Init(void)  //TIM2_CH0    AC_SIG-PB4
{
    timer_ic_parameter_struct timer_icinitpara;
    timer_parameter_struct timer_initpara;
	
	rcu_periph_clock_enable(RCU_TIMER2);
    rcu_periph_clock_enable(RCU_GPIOB);
    rcu_periph_clock_enable(RCU_AF);

	//重映射
	gpio_pin_remap_config(GPIO_TIMER2_PARTIAL_REMAP, ENABLE);	   
    gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_4);	
	
    nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3);
    nvic_irq_enable(TIMER2_IRQn, 1, 1);	
	
    /* TIMER2 configuration: input capture mode -------------------
    the external signal is connected to TIMER2 CH0 pin (PB4)
    the rising edge is used as active edge
    the TIMER2 CH0CV is used to compute the frequency value
    ------------------------------------------------------------ */   
    timer_deinit(TIMER2);

    /* TIMER2 configuration */
    timer_initpara.prescaler         = 215;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;  
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = 65535;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMER2,&timer_initpara);

    /* TIMER2  configuration */
    /* TIMER2 CH0 input capture configuration */
    timer_icinitpara.icpolarity  = TIMER_IC_POLARITY_FALLING;     //下降沿
    timer_icinitpara.icselection = TIMER_IC_SELECTION_DIRECTTI;
    timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1;
    timer_icinitpara.icfilter    = 0x4;                          //使能滤波功能 
    timer_input_capture_config(TIMER2,TIMER_CH_0,&timer_icinitpara);

    /* auto-reload preload enable */
    timer_auto_reload_shadow_enable(TIMER2);
    /* clear channel 0 interrupt bit */
    timer_interrupt_flag_clear(TIMER2,TIMER_INT_CH0);
    /* channel 0 interrupt enable */
    timer_interrupt_enable(TIMER2,TIMER_INT_CH0);

    /* TIMER2 counter enable */
    timer_enable(TIMER2);	
}

可以看到上面的例程使能了滤波功能,下面对滤波功能做一下介绍,并说明为什么要用。
在这里插入图片描述

  输入捕获1滤波器CH0CAPFLT[3:0], 这个用来设置输入采样频率和数字滤波器长度。 其中,fPCLK是定时器的输入频率(TIMxCLK) ,一般为 108Mhz,而 fDTS则是根据 TIMERx_CTL0 的 CKDIV[1:0]的设置来确定的,如果 CKD[1:0]设置为 00,那么fDTS=fTIMER_CK=fPCLK。
在这里插入图片描述

  N 值就是滤波长度,举个简单的例子:假设 CH0CAPFLT[3:0]=0011,并设置 IC1 映射到通道 1 上,且为上升沿触发,那么在捕获到上升沿的时候,再以fPCLK的频率,连续采样到 8 次通道 1 的电平,如果都是高电平,则说明确实是一个有效的触发,就会触发输入捕获中断(如果开启了的话) 。这样可以滤除那些高电平脉宽低于 8 个采样周期的脉冲信号,从而达到滤波的效果。

  此处我是用来采集下降沿信号,但是信号下降的比较慢。当我把滤波关掉,情况如下图,蓝色是采集信号,黄色是测试信号,进一次触发中断就翻转一次黄色信号的电平。可以看到因为蓝色信号下降太慢,在临界处触发了多次中断。
在这里插入图片描述
  当我把滤波打开后,定时器就会采集多次才会触发,这样就可以解决信号边沿慢的问题了。

<think>嗯,用户想在GD32F303微控制器上配置霍尔传感器,需要教程或示例代码。首先,我需要回忆一下GD32定时器配置,因为霍尔传感器通常需要定时器输入捕获功能。根据引用[2],霍尔传感器模式使用定时器输入捕获,触发源是内部触发0,也就是TIMER_SMCFG_TRGSEL_ITI0。所以配置定时器的时候需要注意这一点。 接下来,用户可能需要知道如何初始化定时器,包括时钟使能、GPIO配置、定时器参数设置。GD32的库函数和STM32类似,但可能有细微差别,比如头文件或者寄存器名称的不同。例如,定时器的结构体名称可能是timer_parameter_struct,而STM32可能用TIM_HandleTypeDef。 然后,霍尔传感器的三个输入引脚需要配置为输入模式,通常是上拉输入,因为霍尔信号可能是高有效或低有效。需要根据具体的传感器规格来定。配置输入捕获通道时,需要设置边沿检测,比如上升沿、下降沿或者双沿触发,这取决于霍尔信号的变化方式。 中断配置也是关键,需要开启定时器的中断,并在中断服务函数中处理捕获事件,比如计算转速或者位置。在GD32中,可能需要使用timer_interrupt_enable函数来使能中断,并且编写对应的中断处理函数,记得清除中断标志位。 另外,用户可能需要示例代码,所以需要参考引用[2]和引用[3]中的部分内容,尤其是输入捕获和中断处理的配置部分。例如,引用[3]中的AS5600示例虽然涉及磁编码器,但中断处理的部分可能有共通之处,比如如何读取寄存器的值或者处理捕获的比较值。 需要注意的是,GD32的库函数可能与STM32的HAL库不同,所以代码结构会有差异。比如,GD32可能更直接操作寄存器,或者使用自己的外设库。因此,在提供代码示例时,要确保使用GD32的标准外设库函数,而不是STM32的HAL库。 最后,用户可能在实际操作中遇到问题,比如信号捕获不稳定或者中断无法触发,这时需要建议检查GPIO配置、定时器时钟是否使能、中断优先级设置是否正确,以及是否在中断服务函数中及时清除了标志位。此外,引用[1]中的实战项目可能提供电机驱动相关的实际应用参考,帮助用户将霍尔传感器应用于无刷电机控制。</think>### GD32F303霍尔传感器配置步骤说明 在GD32F303微控制器上配置霍尔传感器需要以下关键步骤: 1. **定时器时钟使能** ```c rcu_periph_clock_enable(RCU_TIMER2); // 以TIMER2为例 rcu_periph_clock_enable(RCU_GPIOA); // 根据实际引脚选择 ``` 2. **GPIO配置** ```c gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2); // 霍尔传感器三路输入 ``` 3. **定时器基础配置** ```c timer_parameter_struct timer_initpara; timer_struct_para_init(&timer_initpara); timer_initpara.prescaler = 71; // 72MHz/(71+1)=1MHz timer_initpara.period = 65535; timer_init(TIMER2, &timer_initpara); ``` 4. **输入捕获配置** ```c timer_ic_parameter_struct icpara; timer_channel_input_struct_para_init(&icpara); icpara.icpolarity = TIMER_IC_POLARITY_RISING; // 根据传感器信号调整 icpara.icselection = TIMER_IC_SELECTION_DIRECTTI; icpara.icprescaler = TIMER_IC_PSC_DIV1; timer_input_capture_config(TIMER2, TIMER_CH_0, &icpara); // 三通道需分别配置 timer_input_capture_config(TIMER2, TIMER_CH_1, &icpara); timer_input_capture_config(TIMER2, TIMER_CH_2, &icpara); ``` 5. **霍尔接口模式配置** ```c timer_hall_mode_config(TIMER2); timer_slave_mode_select(TIMER2, TIMER_SLAVE_MODE_HALL); timer_smaster_trigger_source_select(TIMER2, TIMER_SMCFG_TRGSEL_ITI0); // 关键配置[^2] ``` 6. **中断配置** ```c timer_interrupt_enable(TIMER2, TIMER_INT_CH0 | TIMER_INT_CH1 | TIMER_INT_CH2); nvic_irq_enable(TIMER2_IRQn, 1, 0); ``` 7. **中断服务函数** ```c void TIMER2_IRQHandler(void) { if(timer_interrupt_flag_get(TIMER2, TIMER_INT_FLAG_CH0)){ uint16_t cap_val = timer_channel_capture_value_register_read(TIMER2, TIMER_CH_0); // 处理捕获值 timer_interrupt_flag_clear(TIMER2, TIMER_INT_FLAG_CH0); } // 类似处理其他通道 } ``` ### 关键配置说明: 1. **霍尔接口模式**:需通过`timer_hall_mode_config()`使能专用接口 2. **输入滤波**:可通过`timer_input_capture_filter_config()`设置数字滤波器 3. **信号极性**:根据霍尔传感器类型设置`icpolarity`参数 4. **转速计算**:需结合捕获值和定时器频率进行时间差计算
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qlexcel

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值