xiaoqizi 发表于 2024-10-30 10:44

基于GD32F407ZGT6 的spwm波 (逆变器开环)

因为gd32f4的资源真的很少

所以想写一点点

很菜

勿喷

SPWM波的代码 通过 TIM2   和TIM7实现生成两路互补SPWM波

void timer2_config(void) {
    timer_parameter_struct timer_initpara;

    // 使能TIM2时钟
    rcu_periph_clock_enable(RCU_TIMER2);

    // 重置TIM2到默认状态
    timer_deinit(TIMER2);

    // 配置TIM2的基本参数
    timer_initpara.prescaler         = 2799;// 预分频值,使得定时器时钟为 168MHz / (8399 + 1) = 20kHz
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;// 向上计数模式
    timer_initpara.counterdirection= TIMER_COUNTER_UP;   // 向上计数
    timer_initpara.period            = 7;               // 自动重装载寄存器周期值,产生20kHz更新事件
    timer_initpara.clockdivision   = TIMER_CKDIV_DIV1;    // 时钟不分频
    timer_initpara.repetitioncounter = 0;

    // 初始化TIM2
    timer_init(TIMER2, &timer_initpara);

    // 使能TIM2的更新中断
    timer_interrupt_enable(TIMER2, TIMER_INT_UP);

    // 使能TIM2
    timer_enable(TIMER2);

    // 如果使用NVIC管理中断,还需要使能TIM2的中断
    nvic_irq_enable(TIMER2_IRQn, 0, 0);
}

// TIM2的中断服务例程

#define TIMEPERIOD9000000.0/(150*FREQUENCY) //载波周期值 如果乘以计数器时钟即为一个载波周期,9000000经系统时钟8分频得到,
__IO uint16_t PhraseA=0;
__IO uint16_t PhraseB=75;
                                          //150是正弦波采样点数。注意在调频时TIMEPERIOD最大不能超出65535
int FREQUENCY=66;//设置基波频率
double Voltage = 1.0;//调压系数
uint32_t sinpwm;
const uint32_t spwm={
0x4000,0x42AE,0x455B,0x4805,0x4AAC,0x4D4E,0x4FEA,0x527F,0x550C,0x578F,0x5A08,0x5C74,0x5ED5,0x6127,0x636A,
0x659E,0x67C0,0x69D1,0x6BCF,0x6DB9,0x6F8F,0x714F,0x72FA,0x748D,0x7609,0x776C,0x78B7,0x79E8,0x7AFF,0x7BFB,
0x7CDD,0x7DA3,0x7E4E,0x7EDD,0x7F4F,0x7FA5,0x7FDF,0x7FFB,0x7FFB,0x7FDF,0x7FA5,0x7F4F,0x7EDD,0x7E4E,0x7DA3,
0x7CDD,0x7BFB,0x7AFF,0x79E8,0x78B7,0x776C,0x7609,0x748D,0x72FA,0x714F,0x6F8F,0x6DB9,0x6BCF,0x69D1,0x67C0,
0x659E,0x636A,0x6127,0x5ED5,0x5C74,0x5A08,0x578F,0x550C,0x527F,0x4FEA,0x4D4E,0x4AAC,0x4805,0x455B,0x42AE,
0x4000,0x3D52,0x3AA5,0x37FB,0x3554,0x32B2,0x3016,0x2D81,0x2AF4,0x2871,0x25F8,0x238C,0x212B,0x1ED9,0x1C96,
0x1A62,0x1840,0x162F,0x1431,0x1247,0x1071,0x0EB1,0x0D06,0x0B73,0x09F7,0x0894,0x0749,0x0618,0x0501,0x0405,
0x0323,0x025D,0x01B2,0x0123,0x00B1,0x005B,0x0021,0x0005,0x0005,0x0021,0x005B,0x00B1,0x0123,0x01B2,0x025D,
0x0323,0x0405,0x0501,0x0618,0x0749,0x0894,0x09F7,0x0B73,0x0D06,0x0EB1,0x1071,0x1247,0x1431,0x162F,0x1840,
0x1A62,0x1C96,0x1ED9,0x212B,0x238C,0x25F8,0x2871,0x2AF4,0x2D81,0x3016,0x32B2,0x3554,0x37FB,0x3AA5,0x3D52
};                
void GPIO_SPWM_config(void){// PB01    PC7 PC8       PC7 为AF3 上TIM7 CH1 通道 与PB0 互补
        //GPIOB时钟使能
       
uint32_t presc=100;//欲分频值
uint32_t period=100; //计数   //200 000 000 /presc/period=freq

//输出频率为f=200M/(100*100)=20K;==>200 000 000 /100*100=20K
                rcu_periph_clock_enable(RCU_GPIOB);
                rcu_periph_clock_enable(RCU_GPIOC);
          
       
          gpio_mode_set(GPIOB,GPIO_MODE_AF,GPIO_OSPEED_50MHZ, GPIO_PIN_0|GPIO_PIN_1);
          gpio_af_set(GPIOB, GPIO_AF_3, GPIO_PIN_0|GPIO_PIN_1); // TIM3_CH1复用功能在AF3上(根据数据手册确认)
          
       
       
          gpio_mode_set(GPIOC,GPIO_MODE_AF,GPIO_OSPEED_50MHZ, GPIO_PIN_7|GPIO_PIN_8);
          gpio_af_set(GPIOC, GPIO_AF_3, GPIO_PIN_7|GPIO_PIN_8); // TIM3_CH1复用功能在AF3上(根据数据手册确认)


    timer_oc_parameter_struct timer_ocintpara;
    timer_parameter_struct timer_initpara;
    timer_break_parameter_struct timer_breakpara;

    // 使能TIMER7时钟
    rcu_periph_clock_enable(RCU_TIMER7);

    // 设置TIMER7时钟预分频,得到所需的计数时钟
    rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);

    // 复位TIMER7配置
    timer_deinit(TIMER7);
    // TIMER7基本配置:
    timer_initpara.prescaler         = 7;// PSC
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection= TIMER_COUNTER_UP;
    timer_initpara.period            = TIMEPERIOD-1;// ARR
    timer_initpara.clockdivision   = TIMER_CKDIV_DIV1;// 168MHz /10/ (599 + 1) = 16.8MHz / 600 = 28kHz
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMER7, &timer_initpara);

    // 配置TIMER7的CH0, CH1为PWM模式,输出使能,极性高电平,空闲状态下也为高电平
    timer_ocintpara.outputstate= TIMER_CCX_ENABLE;
    timer_ocintpara.outputnstate = TIMER_CCXN_ENABLE;
    timer_ocintpara.ocpolarity   = TIMER_OC_POLARITY_HIGH;
    timer_ocintpara.ocnpolarity= TIMER_OCN_POLARITY_HIGH;
    timer_ocintpara.ocidlestate= TIMER_OC_IDLE_STATE_HIGH;
    timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_HIGH;

    // 分别对CH1, CH2应用上述配置
    timer_channel_output_config(TIMER7, TIMER_CH_1, &timer_ocintpara);
    timer_channel_output_config(TIMER7, TIMER_CH_2, &timer_ocintpara);

    // 设置各通道脉冲宽度
    timer_channel_output_pulse_value_config(TIMER7, TIMER_CH_1, 299);// CCR
    timer_channel_output_pulse_value_config(TIMER7, TIMER_CH_2, 299);

    // 设置PWM模式
    timer_channel_output_mode_config(TIMER7, TIMER_CH_1, TIMER_OC_MODE_PWM1);
    timer_channel_output_mode_config(TIMER7, TIMER_CH_2, TIMER_OC_MODE_PWM1);

    // 取消影子成保护
    timer_channel_output_shadow_config(TIMER7, TIMER_CH_1, TIMER_OC_SHADOW_DISABLE);
    timer_channel_output_shadow_config(TIMER7, TIMER_CH_2, TIMER_OC_SHADOW_DISABLE);

    // 配置死区时间为164个计数器周期
    timer_breakpara.deadtime = 164;   // 配置死区

    // 禁用断点功能
    timer_breakpara.breakstate = TIMER_BREAK_DISABLE;

    // 注意:此处不调用 timer_primary_output_config(TIMER7, DISABLE);
    // 因为在TIMER7的上下文中,可能不需要该设置
                timer_primary_output_config(TIMER7,ENABLE);
    timer_enable(TIMER7);
}


void TIMER2_IRQHandler(void) {

    if (timer_interrupt_flag_get(TIMER2, TIMER_INT_FLAG_UP)) {
#if 0 //不使用调压功能
                        TIM1->CCR1 = TIMEPERIOD*spwm/32767;
                        TIM1->CCR2 = TIMEPERIOD*spwm/32767;
                        TIM1->CCR3 = TIMEPERIOD*spwm/32767;

//                printf("%d%d%d\r\n",spwm,spwm,spwm);               
               
//                TIM_SetCompare1(TIM1,TIMEPERIOD*sin_table);       
//                TIM_SetCompare2(TIM1,TIMEPERIOD*sin_table);       
//                TIM_SetCompare3(TIM1,TIMEPERIOD*sin_table);
               
#else       //开启调压功能 正负半周要分开乘        (VVVF改变占空比实现调压 驱动三相电机时使用)
               if(FREQUENCY<=50)Voltage=0.1+0.9*FREQUENCY/50;//基频设置为50HZ 基频以下为恒转矩调速(变频变压 压频比保持不变) 基频以上为恒功率调速(变频不变压)
               
           if(spwm>16384)
      {
                                       
         sinpwm = Voltage * (spwm-16384);
                                       timer_channel_output_pulse_value_config(TIMER7, TIMER_CH_1, TIMEPERIOD * (sinpwm + 16384)/32767 );
      }
                                          
      else if(spwm<=16384)
      {
            sinpwm = Voltage * (16384 - spwm);
         timer_channel_output_pulse_value_config(TIMER7, TIMER_CH_1, TIMEPERIOD * (16384 - sinpwm)/32767);        //修改TIM1通道1的PWM占空比,后者为捕获/比较寄存器1的值
      }
           if(spwm>16384)
      {
            sinpwm = Voltage * (spwm-16384);
            timer_channel_output_pulse_value_config(TIMER7, TIMER_CH_2,TIMEPERIOD * (sinpwm + 16384)/32767);
      }
      else if(spwm<=16384)
      {
                                          sinpwm = Voltage * (16384 - spwm);
            timer_channel_output_pulse_value_config(TIMER7,TIMER_CH_2, TIMEPERIOD * (16384 - sinpwm)/32767);
      }


//Voltage=1;               
#endif       
                        PhraseA=(PhraseA+1)%(150);
                        PhraseB=(PhraseB+1)%(150);
       
                }
      timer_interrupt_flag_clear(TIMER2, TIMER_INT_FLAG_UP);

      // 在这里添加你的中断处理代码
    }

————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/2301_79851789/article/details/143192311

星辰大海不退缩 发表于 2024-10-31 11:10

基于GD32F407ZGT6 的spwm波参考很实用
页: [1]
查看完整版本: 基于GD32F407ZGT6 的spwm波 (逆变器开环)