zeshoufx 发表于 2022-11-11 22:09

GD32F450高级定时器六步换相测试

GD32F450的高级定时器很适合用来驱动电机,比如直流无刷和永磁同步。六步换相在直流无刷驱动里运用广泛。

定时器设置函数:
#include "six_step.h"

vu32 step = 1;

void six_step_init(void)
{
        timer_oc_parameter_struct timer_ocintpara;
    timer_parameter_struct timer_initpara;
    timer_break_parameter_struct timer_breakpara;
       
        rcu_periph_clock_enable(RCU_GPIOE);
        rcu_periph_clock_enable(RCU_TIMER0);
        rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);
       
        gpio_mode_set(GPIOE,GPIO_MODE_AF,GPIO_PUPD_NONE,GPIO_PIN_8);
        gpio_output_options_set(GPIOE,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_8);
        gpio_af_set(GPIOE,GPIO_AF_1,GPIO_PIN_8);
       
        gpio_mode_set(GPIOE,GPIO_MODE_AF,GPIO_PUPD_NONE,GPIO_PIN_9);
        gpio_output_options_set(GPIOE,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_9);
        gpio_af_set(GPIOE,GPIO_AF_1,GPIO_PIN_9);
       
        gpio_mode_set(GPIOE,GPIO_MODE_AF,GPIO_PUPD_NONE,GPIO_PIN_10);
        gpio_output_options_set(GPIOE,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_10);
        gpio_af_set(GPIOE,GPIO_AF_1,GPIO_PIN_10);
       
        gpio_mode_set(GPIOE,GPIO_MODE_AF,GPIO_PUPD_NONE,GPIO_PIN_11);
        gpio_output_options_set(GPIOE,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_11);
        gpio_af_set(GPIOE,GPIO_AF_1,GPIO_PIN_11);
       
        gpio_mode_set(GPIOE,GPIO_MODE_AF,GPIO_PUPD_NONE,GPIO_PIN_12);
        gpio_output_options_set(GPIOE,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_12);
        gpio_af_set(GPIOE,GPIO_AF_1,GPIO_PIN_12);
       
        gpio_mode_set(GPIOE,GPIO_MODE_AF,GPIO_PUPD_NONE,GPIO_PIN_13);
        gpio_output_options_set(GPIOE,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_13);
        gpio_af_set(GPIOE,GPIO_AF_1,GPIO_PIN_13);
       
        gpio_mode_set(GPIOE,GPIO_MODE_AF,GPIO_PUPD_NONE,GPIO_PIN_14);
        gpio_output_options_set(GPIOE,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_14);
        gpio_af_set(GPIOE,GPIO_AF_1,GPIO_PIN_14);
       
        gpio_mode_set(GPIOE,GPIO_MODE_AF,GPIO_PUPD_NONE,GPIO_PIN_15);
        gpio_output_options_set(GPIOE,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_15);
        gpio_af_set(GPIOE,GPIO_AF_1,GPIO_PIN_15);
       
        timer_initpara.alignedmode=TIMER_COUNTER_EDGE;
        timer_initpara.clockdivision=TIMER_CKDIV_DIV1;
        timer_initpara.counterdirection=TIMER_COUNTER_UP;
        timer_initpara.period=599;
        timer_initpara.prescaler=199;
        timer_initpara.repetitioncounter=0;
        timer_init(TIMER0,&timer_initpara);
       
        timer_ocintpara.ocidlestate=TIMER_OC_IDLE_STATE_HIGH;
        timer_ocintpara.ocnidlestate=TIMER_OCN_IDLE_STATE_HIGH;
        timer_ocintpara.ocpolarity=TIMER_OC_POLARITY_HIGH;
        timer_ocintpara.ocnpolarity=TIMER_OCN_POLARITY_HIGH;
        timer_ocintpara.outputstate=TIMER_CCX_ENABLE;
        timer_ocintpara.outputnstate=TIMER_CCXN_ENABLE;
       
        timer_channel_output_config(TIMER0,TIMER_CH_0,&timer_ocintpara);
    timer_channel_output_config(TIMER0,TIMER_CH_1,&timer_ocintpara);
    timer_channel_output_config(TIMER0,TIMER_CH_2,&timer_ocintpara);
       
        timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_0,299);
    timer_channel_output_mode_config(TIMER0,TIMER_CH_0,TIMER_OC_MODE_TIMING);
    timer_channel_output_shadow_config(TIMER0,TIMER_CH_0,TIMER_OC_SHADOW_ENABLE);

    timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_1,299);
    timer_channel_output_mode_config(TIMER0,TIMER_CH_1,TIMER_OC_MODE_TIMING);
    timer_channel_output_shadow_config(TIMER0,TIMER_CH_1,TIMER_OC_SHADOW_ENABLE);

    timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_2,299);
    timer_channel_output_mode_config(TIMER0,TIMER_CH_2,TIMER_OC_MODE_TIMING);
    timer_channel_output_shadow_config(TIMER0,TIMER_CH_2,TIMER_OC_SHADOW_ENABLE);
       
        timer_breakpara.runoffstate= TIMER_ROS_STATE_ENABLE;
    timer_breakpara.ideloffstate= TIMER_IOS_STATE_ENABLE ;
    timer_breakpara.deadtime= 164;
    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);
       
        timer_primary_output_config(TIMER0,ENABLE);
       
        timer_interrupt_enable(TIMER0,TIMER_INT_CMT);
        timer_interrupt_disable(TIMER0,TIMER_INT_BRK);
        nvic_irq_enable(TIMER0_TRG_CMT_TIMER10_IRQn,1,1);
       
        timer_enable(TIMER0);
}


void TIMER0_TRG_CMT_TIMER10_IRQHandler(void)
{
    /* clear TIMER interrupt flag */
    timer_interrupt_flag_clear(TIMER0,TIMER_INT_CMT);

    switch(step){
    /* next step: step 2 configuration .A-C` breakover---------------------------- */
    case 1:
      /*channel0 configuration */
      timer_channel_output_mode_config(TIMER0,TIMER_CH_0,TIMER_OC_MODE_PWM0);
      timer_channel_output_state_config(TIMER0,TIMER_CH_0,TIMER_CCX_ENABLE);
      timer_channel_complementary_output_state_config(TIMER0,TIMER_CH_0,TIMER_CCXN_DISABLE);

      /*channel1 configuration */
      timer_channel_output_state_config(TIMER0,TIMER_CH_1,TIMER_CCX_DISABLE);
      timer_channel_complementary_output_state_config(TIMER0,TIMER_CH_1,TIMER_CCXN_DISABLE);

      /*channel2 configuration */
      timer_channel_output_mode_config(TIMER0,TIMER_CH_2,TIMER_OC_MODE_PWM0);
      timer_channel_output_state_config(TIMER0,TIMER_CH_2,TIMER_CCX_DISABLE);
      timer_channel_complementary_output_state_config(TIMER0,TIMER_CH_2,TIMER_CCXN_ENABLE);

      step++;
      break;

    /* next step: step 3 configuration .B-C` breakover---------------------------- */
    case 2:
      /*channel0 configuration */
      timer_channel_output_state_config(TIMER0,TIMER_CH_0,TIMER_CCX_DISABLE);
      timer_channel_complementary_output_state_config(TIMER0,TIMER_CH_0,TIMER_CCXN_DISABLE);

      /*channel1 configuration */
      timer_channel_output_mode_config(TIMER0,TIMER_CH_1,TIMER_OC_MODE_PWM0);
      timer_channel_output_state_config(TIMER0,TIMER_CH_1,TIMER_CCX_ENABLE);
      timer_channel_complementary_output_state_config(TIMER0,TIMER_CH_1,TIMER_CCXN_DISABLE);

      /*channel2 configuration */
      timer_channel_output_mode_config(TIMER0,TIMER_CH_2,TIMER_OC_MODE_PWM0);
      timer_channel_output_state_config(TIMER0,TIMER_CH_2,TIMER_CCX_DISABLE);
      timer_channel_complementary_output_state_config(TIMER0,TIMER_CH_2,TIMER_CCXN_ENABLE);

      step++;
      break;

    /* next step: step 4 configuration .B-A` breakover---------------------------- */
    case 3:
      /*channel0 configuration */
      timer_channel_output_mode_config(TIMER0,TIMER_CH_0,TIMER_OC_MODE_PWM0);
      timer_channel_output_state_config(TIMER0,TIMER_CH_0,TIMER_CCX_DISABLE);
      timer_channel_complementary_output_state_config(TIMER0,TIMER_CH_0,TIMER_CCXN_ENABLE);

      /*channel1 configuration */
      timer_channel_output_mode_config(TIMER0,TIMER_CH_1,TIMER_OC_MODE_PWM0);
      timer_channel_output_state_config(TIMER0,TIMER_CH_1,TIMER_CCX_ENABLE);
      timer_channel_complementary_output_state_config(TIMER0,TIMER_CH_1,TIMER_CCXN_DISABLE);

      /*channel2 configuration */
      timer_channel_output_state_config(TIMER0,TIMER_CH_2,TIMER_CCX_DISABLE);
      timer_channel_complementary_output_state_config(TIMER0,TIMER_CH_2,TIMER_CCXN_DISABLE);

      step++;
      break;

    /* next step: step 5 configuration .C-A` breakover---------------------------- */
    case 4:
      /*channel0 configuration */
      timer_channel_output_mode_config(TIMER0,TIMER_CH_0,TIMER_OC_MODE_PWM0);
      timer_channel_output_state_config(TIMER0,TIMER_CH_0,TIMER_CCX_DISABLE);
      timer_channel_complementary_output_state_config(TIMER0,TIMER_CH_0,TIMER_CCXN_ENABLE);

      /*channel1 configuration */      
      timer_channel_output_state_config(TIMER0,TIMER_CH_1,TIMER_CCX_DISABLE);
      timer_channel_complementary_output_state_config(TIMER0,TIMER_CH_1,TIMER_CCXN_DISABLE);

      /*channel2 configuration */
      timer_channel_output_mode_config(TIMER0,TIMER_CH_2,TIMER_OC_MODE_PWM0);
      timer_channel_output_state_config(TIMER0,TIMER_CH_2,TIMER_CCX_ENABLE);
      timer_channel_complementary_output_state_config(TIMER0,TIMER_CH_2,TIMER_CCXN_DISABLE);

      step++;
      break;

    /* next step: step 6 configuration .C-B` breakover---------------------------- */
    case 5:
      /*channel0 configuration */
      timer_channel_output_state_config(TIMER0,TIMER_CH_0,TIMER_CCX_DISABLE);
      timer_channel_complementary_output_state_config(TIMER0,TIMER_CH_0,TIMER_CCXN_DISABLE);

      /*channel1 configuration */
      timer_channel_output_mode_config(TIMER0,TIMER_CH_1,TIMER_OC_MODE_PWM0);
      timer_channel_output_state_config(TIMER0,TIMER_CH_1,TIMER_CCX_DISABLE);
      timer_channel_complementary_output_state_config(TIMER0,TIMER_CH_1,TIMER_CCXN_ENABLE);

      /*channel2 configuration */
      timer_channel_output_mode_config(TIMER0,TIMER_CH_2,TIMER_OC_MODE_PWM0);
      timer_channel_output_state_config(TIMER0,TIMER_CH_2,TIMER_CCX_ENABLE);
      timer_channel_complementary_output_state_config(TIMER0,TIMER_CH_2,TIMER_CCXN_DISABLE);

      step++;
      break;

    /* next step: step 1 configuration .A-B` breakover---------------------------- */      
    case 6:
      /*channel0 configuration */
      timer_channel_output_mode_config(TIMER0,TIMER_CH_0,TIMER_OC_MODE_PWM0);
      timer_channel_output_state_config(TIMER0,TIMER_CH_0,TIMER_CCX_ENABLE);
      timer_channel_complementary_output_state_config(TIMER0,TIMER_CH_0,TIMER_CCXN_DISABLE);

      /*channel1 configuration */
      timer_channel_output_mode_config(TIMER0,TIMER_CH_1,TIMER_OC_MODE_PWM0);
      timer_channel_output_state_config(TIMER0,TIMER_CH_1,TIMER_CCX_DISABLE);
      timer_channel_complementary_output_state_config(TIMER0,TIMER_CH_1,TIMER_CCXN_ENABLE);

      /*channel2 configuration */
      timer_channel_output_state_config(TIMER0,TIMER_CH_2,TIMER_CCX_DISABLE);
      timer_channel_complementary_output_state_config(TIMER0,TIMER_CH_2,TIMER_CCXN_DISABLE);

      step = 1;
      break;
    }
}

static u32 delay;

void systick_config(void)
{
    /* setup systick timer for 1000Hz interrupts */
    if (SysTick_Config(SystemCoreClock / 100U)){
      /* capture error */
      while (1){
      }
    }
    /* configure the systick handler priority */
    NVIC_SetPriority(SysTick_IRQn, 0x00U);
}

/*!
    \brief      delay a time in milliseconds
    \paramcount: count in milliseconds
    \param none
    \retval   none
*/
void delay_1ms(uint32_t count)
{
    delay = count;

    while(0U != delay){
    }
}

/*!
    \brief      delay decrement
    \paramnone
    \param none
    \retval   none
*/
void delay_decrement(void)
{
    if (0U != delay){
      delay--;
    }
}

void SysTick_Handler(void)
{
    timer_event_software_generate(TIMER0,TIMER_EVENT_SRC_CMTG);
}
主函数:

#include "bitband.h"
#include "usart.h"
#include "systick.h"
#include "led.h"
#include "six_step.h"

/*!
    \brief    main function
    \paramnone
    \param none
    \retval   none
*/




int main(void)
{
        nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
//        systick_set(200);
//        usart_init(9600);
//        led_init();
//        printf("hello c language...\r\n");
        systick_config();
        six_step_init();
    while(1)
        {
//                printf("hello gd32...\r\n");
//                led_toggle();
//                delay_ms(750);
    }
}


结果:




豌豆爹 发表于 2022-11-15 13:31

这个高级定时器挺厉害的

zeshoufx 发表于 2022-11-16 09:04

豌豆爹 发表于 2022-11-15 13:31
这个高级定时器挺厉害的

可以的{:biggrin:}

chenqianqian 发表于 2022-11-19 11:18

这个效果看起来不错啊

daichaodai 发表于 2022-11-19 17:37

实际测试效果如何,稳不稳?

zeshoufx 发表于 2022-11-20 13:55

chenqianqian 发表于 2022-11-19 11:18
这个效果看起来不错啊

是的

zeshoufx 发表于 2022-11-20 13:56

daichaodai 发表于 2022-11-19 17:37
实际测试效果如何,稳不稳?

还没正式测试,,

OKAKAKO 发表于 2022-11-24 21:35

这个高级定时器效果非常好,各个波形也稳定

zeshoufx 发表于 2022-11-25 16:57

OKAKAKO 发表于 2022-11-24 21:35
这个高级定时器效果非常好,各个波形也稳定

你们也在测试吗

OKAKAKO 发表于 2022-11-25 21:19

zeshoufx 发表于 2022-11-25 16:57
你们也在测试吗

看你的波形输出确实挺稳定,以前做过类似的

zeshoufx 发表于 2022-11-26 19:58

OKAKAKO 发表于 2022-11-25 21:19
看你的波形输出确实挺稳定,以前做过类似的

哦哦,,你们主要是做电机控制这块吗

OKAKAKO 发表于 2022-11-27 10:47

zeshoufx 发表于 2022-11-26 19:58
哦哦,,你们主要是做电机控制这块吗

我不是这个方向的,参与过类似的项目而已

tpgf 发表于 2022-12-5 09:56

请问六步换相是一种什么方式呢 适用于什么种类的电机呢

qcliu 发表于 2022-12-5 11:06

tpgf 发表于 2022-12-5 09:56
请问六步换相是一种什么方式呢 适用于什么种类的电机呢

电子换相无刷电机要对转子永磁体位置进行精确检测,并用电子开关切换不同绕组通电以获得持续向前的动力,在目前的绝大多数电动车三相无刷电机中均使用三个开关式的霍尔传感器检测永磁体相对于定子线圈的位置,控制器跟据三个霍尔传感器输出的六种不同信号输出相应的控制信号驱动电子开关向马达供电。这就是所谓六步换相法

drer 发表于 2022-12-5 12:03

从电机原理可以看出,换相必须及时,否则会导致电机失步,从而使电机噪音增大,效率降低

coshi 发表于 2022-12-5 13:05

为什么只有高级定时器适合呢   需要特殊的控制吗

kxsi 发表于 2022-12-5 14:12

coshi 发表于 2022-12-5 13:05
为什么只有高级定时器适合呢   需要特殊的控制吗

普通的定时器应该不能输出pwm波

wiba 发表于 2022-12-5 14:25

OKAKAKO 发表于 2022-11-24 21:35
这个高级定时器效果非常好,各个波形也稳定

有没有测试过抗干扰能力呢另外和频率挂钩吗

zeshoufx 发表于 2022-12-5 14:43

coshi 发表于 2022-12-5 13:05
为什么只有高级定时器适合呢   需要特殊的控制吗

高级定时器可以输出互补的PWM,方便设置死区,刹车

zeshoufx 发表于 2022-12-5 14:43

drer 发表于 2022-12-5 12:03
从电机原理可以看出,换相必须及时,否则会导致电机失步,从而使电机噪音增大,效率降低 ...

是的,,,
页: [1] 2
查看完整版本: GD32F450高级定时器六步换相测试