打印
[研电赛技术支持]

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

[复制链接]
368|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
xiaoqizi|  楼主 | 2024-10-30 10:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
因为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 TIMEPERIOD  9000000.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[150]={
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[PhraseA]/32767;
                        TIM1->CCR2 = TIMEPERIOD*spwm[PhraseB]/32767;
                        TIM1->CCR3 = TIMEPERIOD*spwm[PhraseC]/32767;

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

使用特权

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

本版积分规则

85

主题

4090

帖子

3

粉丝