PWM的全称是Pulse Width Modulation,即:脉冲宽度调制,它是通过改变输出方波的占空比来改变等效的输出电压。广泛地用于电动机调速和阀门控制。SPWM(Sinusoidal PWM) “正弦脉冲宽度调制”就是在PWM的基础上改变了调制脉冲方式,脉冲宽度时间占空比按正弦规律排列,这样输出波形经过适当的滤波可以做到正弦波输出。 很多直流电机需要使用SPWM控制电机的电压和频率,从而实现电机的变频调速功能。但是大部分单片机的GPIO只能输出高(On)低(Off)电平,无法直接输出正弦波。我们可以通过调整GPIO 的ON/OFF的时间长度来改变电压,在一个较小的时间片内(1ms)改变ON时间和OFF时间的比率(占空比)变化。若ON的比率较高,可以得到和提高电压相同的效果。若ON的比率下降,则可以得到和电压降低相同的效果,如下图。
在一个较长的时间(正弦曲线周期)是由很多个较小的时间片内(1ms)组成的,根据正弦波的曲线调节小的时间片内(1ms)的On/Off占空比,就能得出类似正弦波控制的效果。
以1秒为周期(兀),以1ms为时间片,GPIO模拟SPWM的代码。 /*****************************************************************************************Function description:simulate Sine curveParameter:voidReturn value:Remark:*****************************************************************************************/void Smallmotorcode(void){ unsigned int tempmodetime=0; if(VibrationLevel) { if((Mode2and3time==0)||(Mode2and3time==945)) { PWMMotorA=sinewave_level[VibrationLevel-1][0]; } else if((Mode2and3time==47)||(Mode2and3time==892)) { PWMMotorA=sinewave_level[VibrationLevel-1][1]; } else if((Mode2and3time==94)||(Mode2and3time==850)) { PWMMotorA=sinewave_level[VibrationLevel-1][2]; } else if((Mode2and3time==141)||(Mode2and3time==802)) { PWMMotorA=sinewave_level[VibrationLevel-1][3]; } else if((Mode2and3time==189)||(Mode2and3time==755)) { PWMMotorA=sinewave_level[VibrationLevel-1][4]; } else if((Mode2and3time==236)||(Mode2and3time==708)) { PWMMotorA=sinewave_level[VibrationLevel-1][5]; } else if((Mode2and3time==283)||(Mode2and3time==660)) { PWMMotorA=sinewave_level[VibrationLevel-1][6]; } else if((Mode2and3time==330)||(Mode2and3time==613)) { PWMMotorA=sinewave_level[VibrationLevel-1][7]; } else if((Mode2and3time==377)||(Mode2and3time==566)) { PWMMotorA=sinewave_level[VibrationLevel-1][8]; } else if((Mode2and3time==425)||(Mode2and3time==514)) { PWMMotorA=sinewave_level[VibrationLevel-1][9]; } else if(Mode2and3time==472) { PWMMotorA=sinewave_level[VibrationLevel-1][10]; } } else { VibrationLevel = 1; TurnOffMassager(); OnAndOff=0x5F; OffFlag=1; }}/*****************************************************************************************Function description:interrupt service routineParameter:voidReturn value:Remark:*****************************************************************************************/__interrupt void timer0_ISR(){ __disable_interrupt(); if((T0CON & 0x03) == 0x03) { T0CON &= 0xFE; //Sine curve slow if(AllDutyTime<PWMMotorA) { TURN_ON_MOTOR_A; } else if(AllDutyTime<=MAX_DUTY_COUNTER) { TURN_OFF_MOTOR_A; } } else if(T0CON & 0x01) { TurnOffMassager(); } AllDutyTime++; if(AllDutyTime>ALL_DUTY_TIME_COUNTER) { //Time count for mode 2 and mode 3 Mode2and3time++; if(Mode2and3time > 1000) { Mode2and3time=0; } AllDutyTime = 0; } __enable_interrupt();}
|