在逆变器中,必不可少的则是spwm,那么什么是spwm呢?所谓SPWM,就是在PWM的基础上改变了调制脉冲方式,脉冲宽度时间占空比按正弦规律排列。说直白点,SPWM是在PWM的基础上用正弦波来调制合成的具有正弦波规律变化的方波。SPWM原理正弦波基于PWM的信号波为正弦波,是正弦波等效成一系列等幅不等宽的矩形脉冲波形,其脉冲宽度是由正弦波和三角波自然相交生成的(可见图3)
图 1由四百个采样点形成的正弦规律排列
这样输出波形经过适当的滤波可以做到正弦波输出。
图 2经过低通滤波器滤波后的spwm
Spwm有两种调制方法,一种是单极性调制,另一种是双极性调制。
我采用的是第二种方法,第二种调制的工作的好处是:逆变桥在工作时,同一桥臂的两个逆变器件总是按相电压脉冲系列的规律交替地导通和关断,毫不停息,而流过负载的是按线电压规律变化的交变电流。
图 3双极性正弦脉宽调制
在程序中,可以通过改变pwm的占空比来使波形达到正弦的效果,使用spwm产生器,取了400个按正弦变化的采样点,将这些点依次填入重装载值,来改变pwm的占空比,然后输出的波形就是spwm的方波正弦信号。
u32 spwm1[400]={//调制度 100% 0x8201,0x8404,0x8606,0x8808,0x8A09,0x8C0A,0x8E0A,0x9009,0x9207, 0x9404,0x9600,0x97FA,0x99F3,0x9BEA,0x9DE0,0x9FD3,0xA1C5,0xA3B4,0xA5A1, 0xA78C,0xA974,0xAB5A,0xAD3D,0xAF1D,0xB0FA,0xB2D4,0xB4AB,0xB67E,0xB84E, 0xBA1A,0xBBE3,0xBDA8,0xBF69,0xC126,0xC2DF,0xC494,0xC644,0xC7F0,0xC998, 0xCB3A,0xCCD8,0xCE72,0xD006,0xD195,0xD31F,0xD4A4,0xD623,0xD79D,0xD911, 0xDA80,0xDBE9,0xDD4D,0xDEAA,0xE001,0xE153,0xE29E,0xE3E3,0xE522,0xE65A, 0xE78C,0xE8B7,0xE9DB,0xEAF9,0xEC11,0xED21,0xEE2A,0xEF2D,0xF028,0xF11D, 0xF20A,0xF2F0,0xF3CF,0xF4A6,0xF577,0xF63F,0xF700,0xF7BA,0xF86C,0xF917, 0xF9BA,0xFA55,0xFAE8,0xFB74,0xFBF8,0xFC74,0xFCE8,0xFD55,0xFDB9,0xFE16, 0xFE6A,0xFEB7,0xFEFB,0xFF38,0xFF6C,0xFF98,0xFFBD,0xFFD9,0xFFED,0xFFF9, 0xFFFE,0xFFF9,0xFFED,0xFFD9,0xFFBD,0xFF98,0xFF6C,0xFF38,0xFEFB,0xFEB7, 0xFE6A,0xFE16,0xFDB9,0xFD55,0xFCE8,0xFC74,0xFBF8,0xFB74,0xFAE8,0xFA55, 0xF9BA,0xF917,0xF86C,0xF7BA,0xF700,0xF63F,0xF577,0xF4A6,0xF3CF,0xF2F0, 0xF20A,0xF11D,0xF028,0xEF2D,0xEE2A,0xED21,0xEC11,0xEAF9,0xE9DB,0xE8B7, 0xE78C,0xE65A,0xE522,0xE3E3,0xE29E,0xE153,0xE001,0xDEAA,0xDD4D,0xDBE9, 0xDA80,0xD911,0xD79D,0xD623,0xD4A4,0xD31F,0xD195,0xD006,0xCE72,0xCCD8, 0xCB3A,0xC998,0xC7F0,0xC644,0xC494,0xC2DF,0xC126,0xBF69,0xBDA8,0xBBE3, 0xBA1A,0xB84E,0xB67E,0xB4AB,0xB2D4,0xB0FA,0xAF1D,0xAD3D,0xAB5A,0xA974, 0xA78C,0xA5A1,0xA3B4,0xA1C5,0x9FD3,0x9DE0,0x9BEA,0x99F3,0x97FA,0x9600, 0x9404,0x9207,0x9009,0x8E0A,0x8C0A,0x8A09,0x8808,0x8606,0x8404,0x8201, 0x7FFF,0x7DFC,0x7BF9,0x79F7,0x77F5,0x75F4,0x73F3,0x71F3,0x6FF4,0x6DF6, 0x6BF9,0x69FD,0x6803,0x660A,0x6413,0x621D,0x602A,0x5E38,0x5C49,0x5A5C, 0x5871,0x5689,0x54A3,0x52C0,0x50E0,0x4F03,0x4D29,0x4B52,0x497F,0x47AF, 0x45E3,0x441A,0x4255,0x4094,0x3ED7,0x3D1E,0x3B69,0x39B9,0x380D,0x3665, 0x34C3,0x3325,0x318B,0x2FF7,0x2E68,0x2CDE,0x2B59,0x29DA,0x2860,0x26EC, 0x257D,0x2414,0x22B0,0x2153,0x1FFC,0x1EAA,0x1D5F,0x1C1A,0x1ADB,0x19A3, 0x1871,0x1746,0x1622,0x1504,0x13EC,0x12DC,0x11D3,0x10D0,0x0FD5,0x0EE0, 0x0DF3,0x0D0D,0x0C2E,0x0B57,0x0A86,0x09BE,0x08FD,0x0843,0x0791,0x06E6, 0x0643,0x05A8,0x0515,0x0489,0x0405,0x0389,0x0315,0x02A8,0x0244,0x01E7, 0x0193,0x0146,0x0102,0x00C5,0x0091,0x0065,0x0040,0x0024,0x0010,0x0004, 0x0000,0x0004,0x0010,0x0024,0x0040,0x0065,0x0091,0x00C5,0x0102,0x0146, 0x0193,0x01E7,0x0244,0x02A8,0x0315,0x0389,0x0405,0x0489,0x0515,0x05A8, 0x0643,0x06E6,0x0791,0x0843,0x08FD,0x09BE,0x0A86,0x0B57,0x0C2E,0x0D0D, 0x0DF3,0x0EE0,0x0FD5,0x10D0,0x11D3,0x12DC,0x13EC,0x1504,0x1622,0x1746, 0x1871,0x19A3,0x1ADB,0x1C1A,0x1D5F,0x1EAA,0x1FFC,0x2153,0x22B0,0x2414, 0x257D,0x26EC,0x2860,0x29DA,0x2B59,0x2CDE,0x2E68,0x2FF7,0x318B,0x3325, 0x34C3,0x3665,0x380D,0x39B9,0x3B69,0x3D1E,0x3ED7,0x4094,0x4255,0x441A, 0x45E3,0x47AF,0x497F,0x4B52,0x4D29,0x4F03,0x50E0,0x52C0,0x54A3,0x5689, 0x5871,0x5A5C,0x5C49,0x5E38,0x602A,0x621D,0x6413,0x660A,0x6803,0x69FD, 0x6BF9,0x6DF6,0x6FF4,0x71F3,0x73F3,0x75F4,0x77F5,0x79F7,0x7BF9,0x7DFC, 0x7FFF }; u16 count = 0;
配置高级定时器TIM1:
void TIM1_PWM_Init(u16 pfreq ,u16 psc) //pfreq为不分频时的PWM频率,psc为预分频值 { u16 i; GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; //输出通道配置 TIM_BDTRInitTypeDef TIM_BDTRInitStructure; //死区和刹车配置 TimerPeriod = SystemCoreClock / (pfreq + 1); //自动重装载周期值 /* ChannelxPulse = DutyCycle * (TIM1_Period - 1) / 100 */ Channel1Pulse = (u16)((u32)(50 * (TimerPeriod - 1)) / 100 ); //占空比50% /* 使能TIM1,GPIOA,GPIOB,GPIOE */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE); /*channel1 , -->A.8,* *channel1N,-->B.13*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_Init(GPIOB, &GPIO_InitStructure); /* 初始化TIM1 */ TIM_TimeBaseStructure.TIM_Period = pfreq; //设置重装载周期值 TIM_TimeBaseStructure.TIM_Prescaler = psc; //设置预分频值 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //时钟分频因子,仅与输入捕获有关(定时器与滤波器的频率比) TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//TIM向上计数模式 TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; //重复溢出中断 TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //初始化定时器基本配置 /* Channel_1 TIM_OCMode_PWM1模式 */ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为有效电平 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能 TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; //PWM互补输出使能 TIM_OCInitStructure.TIM_Pulse = Channel1Pulse; //占空比 = TIM_Pulse/TIM_Period; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //有效电平为高电平 TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; //互补PWM极性 TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; //输出空闲状态 TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset; //PWM互补输出空闲状态 TIM_OC1Init(TIM1, &TIM_OCInitStructure); //根据指定的参数初始化外设TIM1 OC1 TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); //使能TIM1在CCR1上的预装载寄存器 /*死区和刹车功能配置 */ TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable; TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable; TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_OFF; //bit7~5 = 111,则deadtime = (32 + (bit4~bit0)* 16*1/fosc)ns = (32+31)*16*1/72000000 = 14us TIM_BDTRInitStructure.TIM_DeadTime = 0x07; //这里调整死区大小0-0xff 死区97ns TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable; TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High; TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable; TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure); //TIM_Cmd(TIM1, ENABLE); //使能TIM1 TIM_CtrlPWMOutputs(TIM1,ENABLE); //PWM输出使能
通过TIM2产生中断来改变TIM1产生的PWM占空比:
//定时器2中断服务程序 void TIM2_IRQHandler(void) { extern float Period_percent; if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) //检查TIM2更新中断发生与否 { TIM_SetCompare1(TIM1,(u16)(Period_percent*spwm1[count])) ; } //修改TIM1通道1的PWM占空比,后者为捕获/比较寄存器1的值 TIM_SetCounter(TIM1, 0); count++; if(count == 400) //一周期采样400个点 { count = 0; } TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除TIM2更新中断标志 } }