打印

GD32E230C8T6定时器输出比较中断触发与比较值不符!

[复制链接]
6684|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
MrZZS|  楼主 | 2021-8-20 18:43 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
在使用GD32E230这款芯片的时候,遇到了点问题,问题表现为:高级定时器timer0的非互补通道3的输出比较中断触发情况不正常,timer0的计数周期为1499,有效电平为高电平,输出比较模式为PWM2,在设置通道3比较器值为0的时候不进入比较中断,在设置比较器值为1-1499,大于1499都会触发该比较中断,如下是我的配置:
void timer0_gpio_config(void)
{
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_GPIOB);

    /*configure PA8/PA9/PA10(TIMER0/CH0/CH1/CH2) as alternate function*/
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_8);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_8);

    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_9);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_9);

    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_10);
       
        gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
  gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_11);

    gpio_af_set(GPIOA, GPIO_AF_2, GPIO_PIN_8);
    gpio_af_set(GPIOA, GPIO_AF_2, GPIO_PIN_9);
    gpio_af_set(GPIOA, GPIO_AF_2, GPIO_PIN_10);
        gpio_af_set(GPIOA, GPIO_AF_2, GPIO_PIN_11);

    /*configure PB13/PB14/PB15(TIMER0/CH0N/CH1N/CH2N) as alternate function*/
    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_13);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_13);

    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_14);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_14);

    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_15);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_15);

    gpio_af_set(GPIOB, GPIO_AF_2, GPIO_PIN_13);
    gpio_af_set(GPIOB, GPIO_AF_2, GPIO_PIN_14);
    gpio_af_set(GPIOB, GPIO_AF_2, GPIO_PIN_15);

    /*configure PB12(TIMER0 BKIN) as alternate function*/
    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_12);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_12);
    gpio_af_set(GPIOB, GPIO_AF_2, GPIO_PIN_12);
}

void timer0_config(void)
{
    /* -----------------------------------------------------------------------
    TIMER0 configuration:
    generate 3 complementary PWM signal.
    TIMER0CLK is fixed to systemcoreclock, the TIMER0 prescaler is equal to 1
    so the TIMER0 counter clock used is 72MHz.
    insert a dead time equal to 164/systemcoreclock = 2.28us
    configure the break feature, active at low level, and using the automatic
    output enable feature.
    use the locking parameters level 0.
    ----------------------------------------------------------------------- */
    timer_oc_parameter_struct timer_ocinitpara;
    timer_parameter_struct timer_initpara;
    timer_break_parameter_struct timer_breakpara;
          /* enable the TIMER clock */
    rcu_periph_clock_enable(RCU_TIMER0);
                /* deinit a TIMER */
    timer_deinit(TIMER0);
    /* initialize TIMER init parameter struct */
    timer_struct_para_init(&timer_initpara);
    /* TIMER0 configuration */
    timer_initpara.prescaler         = 72 - 1;
    timer_initpara.alignedmode       = TIMER_COUNTER_CENTER_UP;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = 1500 - 1;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMER0, &timer_initpara);

    /* initialize TIMER channel output parameter struct */
    timer_channel_output_struct_para_init(&timer_ocinitpara);
    /* CH0/CH0N, CH1/CH1N and CH2/CH2N configuration in timing mode */
    timer_ocinitpara.outputstate  = TIMER_CCX_ENABLE;
    timer_ocinitpara.outputnstate = TIMER_CCXN_ENABLE;
    timer_ocinitpara.ocpolarity   = TIMER_OC_POLARITY_HIGH;
    timer_ocinitpara.ocnpolarity  = TIMER_OCN_POLARITY_HIGH;
    timer_ocinitpara.ocidlestate  = TIMER_OC_IDLE_STATE_LOW;
    timer_ocinitpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;

    timer_channel_output_config(TIMER0, TIMER_CH_0, &timer_ocinitpara);
    timer_channel_output_config(TIMER0, TIMER_CH_1, &timer_ocinitpara);
    timer_channel_output_config(TIMER0, TIMER_CH_2, &timer_ocinitpara);
               
                timer_ocinitpara.outputnstate = TIMER_CCXN_DISABLE;
                timer_channel_output_config(TIMER0, TIMER_CH_3, &timer_ocinitpara);

    /* configure TIMER channel 0 */
    timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_0, TIM0_DUTY_INIT - 1);
    timer_channel_output_mode_config(TIMER0, TIMER_CH_0, TIMER_OC_MODE_PWM1);                //PWM输出模式1
    timer_channel_output_shadow_config(TIMER0, TIMER_CH_0, TIMER_OC_SHADOW_DISABLE);
   
    /* configure TIMER channel 1 */
    timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_1, TIM0_DUTY_INIT - 1);
    timer_channel_output_mode_config(TIMER0, TIMER_CH_1, TIMER_OC_MODE_PWM1);
    timer_channel_output_shadow_config(TIMER0, TIMER_CH_1, TIMER_OC_SHADOW_DISABLE);

    /* configure TIMER channel 2 */
    timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_2, TIM0_DUTY_INIT - 1);
    timer_channel_output_mode_config(TIMER0, TIMER_CH_2, TIMER_OC_MODE_PWM1);
    timer_channel_output_shadow_config(TIMER0, TIMER_CH_2, TIMER_OC_SHADOW_DISABLE);
       
                /* configure TIMER channel 3 */
    timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_3, 4000);
    timer_channel_output_mode_config(TIMER0, TIMER_CH_3, TIMER_OC_MODE_PWM1);
    timer_channel_output_shadow_config(TIMER0, TIMER_CH_3, TIMER_OC_SHADOW_DISABLE);

    /* initialize TIMER break parameter struct */
    timer_break_struct_para_init(&timer_breakpara);
    /* automatic output enable, break, dead time and lock configuration*/
    timer_breakpara.runoffstate      = TIMER_ROS_STATE_ENABLE;
    timer_breakpara.ideloffstate     = TIMER_IOS_STATE_ENABLE;
    timer_breakpara.deadtime         = DEAD_TIME;
    timer_breakpara.breakpolarity    = TIMER_BREAK_POLARITY_LOW;
    timer_breakpara.outputautostate  = TIMER_OUTAUTO_ENABLE;
    timer_breakpara.protectmode      = TIMER_CCHP_PROT_OFF;      //互补寄存器写保护模式
    timer_breakpara.breakstate       = TIMER_BREAK_ENABLE;
    timer_break_config(TIMER0, &timer_breakpara);
   
    /* TIMER0 primary output function enable */
    timer_primary_output_config(TIMER0, ENABLE);

    /* TIMER0 break/channel interrupt enable */
                timer_interrupt_flag_clear(TIMER0, TIMER_INT_FLAG_BRK);
                timer_interrupt_flag_clear(TIMER0, TIMER_INT_FLAG_CH3);
                timer_interrupt_flag_clear(TIMER0, TIMER_INT_FLAG_UP);
    timer_interrupt_enable(TIMER0, TIMER_INT_BRK);
                timer_interrupt_enable(TIMER0, TIMER_INT_CH3);
                timer_interrupt_enable(TIMER0, TIMER_INT_UP);
               
    /* TIMER0 counter enable */
    timer_enable(TIMER0)
}
配置通道3的比较器值为4000,大于计数周期1499,硬件Debug截图如下:


具体结果为:当通道3的比较器值设为4000,也会触发进入比较中断!且在调试句柄执行完标志清零语句后,通道中断标志位CH3IF仍然处于置位状态!!(可以参考图中红框标记)更改通道3的输出比较方式、有效电平极性产生的现象均相同!!只有在比较器值设为0的时候才不会进入中断!!!很迷惑,新人请教,希望大家帮帮忙解答!!!


使用特权

评论回复
沙发
MrZZS|  楼主 | 2021-8-20 18:46 | 只看该作者
该通道的中断服务函数如下:
/****定时器中断服务函数************************************/
void TIMER0_Channel_IRQHandler(void)
{
if(timer_interrupt_flag_get(TIMER0, TIMER_INT_FLAG_CH3) == SET)
{
timer0_flag_dir = (TIMER_CTL0(TIMER0) & (uint32_t)TIMER_CTL0_DIR) >> 4;
timer_interrupt_flag_clear(TIMER0, TIMER_INT_FLAG_CH3);
if(timer0_flag_dir == 0)
{
timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_0, buffer_ccr[0]);
timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_1, buffer_ccr[1]);
timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_2, buffer_ccr[2]);
}
else if(timer0_flag_dir == 1)
{
timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_0, buffer_ccr[3]);
timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_1, buffer_ccr[4]);
timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_2, buffer_ccr[5]);
}
}
}


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

2

帖子

0

粉丝