因为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
|
共1人点赞
|