微控制器SPWM的產生
阿新 • • 發佈:2019-02-19
電賽剛結束不久,期間我做的題目需要用單片產生一個三相的SPWM波,然後再通過硬體電路LC濾波形成正弦波。
我用的微控制器是STC15F2K60S2,然後通過自然數查表法控制內部3路PWM產生SPWM訊號,而且生成的正弦波相位是相差120°,並且頻率是50Hz。
要讓微控制器產生正確可用的SPWM,需要程式設計一定的演算法來產生波形。
我們根據整合為1的思想,將正弦波分成305等分,因為頻率需要50HZ,那麼週期就是20MS,20MS除於305分,相除出來的值非常接近65US,然後我們利用定時器0進行中斷定時,每進入一次中斷產生一個相對應占空比的值,然後在示波器上顯示出來的SPWM。將一個週期的正弦波用正弦公式計算出相應的佔空比,然後通過驅動電路以及濾波電路生成了正弦波形。
我電賽的論文: http://blog.csdn.net/hpf247/article/details/77206898
程式碼:
#include <STC15F2K60S2.H>
#define uchar unsigned char
#define uint unsigned int
#define CCP_S0 0x10 //P_SW1.4
#define CCP_S1 0x20 //P_SW1.5
uchar code pwm[]={ //pwm產生陣列
124,122,119,116,114,111,108,106,103,100,98,95,93,90,87,85,82,80,77,75,73,70,68,65,63,61,58,56,54,52,50,47,45,43,
41,39,37,36,34,32,30,28,27,25,23,22,20,19,18,16,15,14,12,11,10,9,8,7,6,5,4,4,3,2,2,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,2,2,3,4,4,5,4,7,8,9,10,11,12,14,15,16,18,19,20,22,23,25,27,28,30,32,34,36,37,39,41,43,45,47,50,52,54,56,58,61,63,
65,68,70,73,75,77,80,82,85,87,90,93,95,98,100,103,106,108,111,114,116,119,122,124,127,130,132,135,138,140,143,146,148,151,
154,156,159,161,164,167,169,172,174,177,179,181,184,186,189,191,193,196,198,200,202,204,207,209,211,213,215,217,218,220,
222,224,226,227,229,231,232,234,235,236,238,239,240,242,243,244,245,246,247,248,249,250,250,251,252,252,253,253,254,254,
254,255,255,255,255,255,255,255,255,255,254,254,254,
253,253,252,252,251,250,250,249,248,247,246,245,244,243,242,240,239,238,236,235,234,232,231,229,227,226,224,222,220,218,
217,215,213,211,209,207,204,202,200,198,196,193,191,189,186,184,181,179,177,174,172,169,167,164,161,159,156,154,151,148,146,
143,140,138,135,132,130,127,124,122,119,116,114
};
uint sine_1 = 0; //A相位查表數值
uint sine_2 = 100; //B相位查表數值
uint sine_3 = 200; //C相位查表數值
//內部與外部晶振時週期數的增減
uint cry_in = 302;
uint cry_out = 298;
void Delay_ms(unsigned int ms)
{
unsigned int i;
while( (ms--) != 0)
{
for(i = 0; i < 580; i++);
}
}
/**********************************************************
函式說明: 短暫延時程式
**********************************************************/
void delay(uchar t)
{
uint j;
uchar i;
for(i=0;i<t;i++)
for(j=0;j<1000;j++);
}
/**********************************************************
函式說明: PWM初始化
**********************************************************/
void Init_pwm()
{
ACC = P_SW1;
ACC &= ~(CCP_S0 | CCP_S1); //CCP_S0=1 CCP_S1=0
ACC |= CCP_S0; //(P3.4/ECI_2, P3.5/CCP0_2, P3.6/CCP1_2, P3.7/CCP2_2)
P_SW1 = ACC;
CCON = 0; //初始化PCA控制暫存器//PCA定時器停止//清除CF標誌//清除模組中斷標誌
CL = 0; //復位PCA暫存器
CH = 0;
CMOD=0x08; //計數器0的溢位為PCA計數器的時鐘源,允許pca中斷使能.
PCA_PWM0 = 0x00; //PCA模組0工作於8位PWM
CCAP0H = CCAP0L = 128; //PWM0佔空比初始化,((255-CCAP0L)/255)
CCAPM0 = 0x42; //PCA模組0為8位PWM模式(PWM0設定PCA工作方式為PWM方式)
PCA_PWM1 = 0x00; //PCA模組1工作於8位PWM
CCAP1H = CCAP1L = 128; //PWM1佔空比初始化,((255-CCAP1L)/255)
CCAPM1 = 0x42; //PCA模組1為8位PWM模式
PCA_PWM2 = 0x00; //PCA模組2工作於8位PWM
CCAP2H = CCAP2L = 128; //PWM2佔空比初始化,((255-CCAP2L)/255)
CCAPM2 = 0x42; //PCA模組2為8位PWM模式
CR = 1; //PCA定時器開始工作
}
/**********************************************************
函式說明: 計數器0初始化函式
**********************************************************/
void InitTimer0(void)
{
TMOD = 0x01;
TH0 = 0x0FE;
TL0 = 0x20;
EA = 1;
ET0 = 1;
TR0 = 1;
}
/**************************************
短延時
**************************************/
void delay5ms()
{
uchar i,v,k;
for(i=1;i>0;i--)
for(v=168;v>0;v--)
for(k=22;k>0;k--);
}
/**********************************************************
函式說明: 主函式
**********************************************************/
void main(void)
{
Delay_ms(2); //
P3M0=0xFC;
P3M1=0x00;
P2M0=0x01;
P2M1=0x00;
Init_pwm();
InitTimer0();
EA=1;//開總中斷
while(1)//主迴圈
{
}
}
/**********************************************************
函式說明: 定時器0中斷
**********************************************************/
void Timer0Interrupt(void) interrupt 1
{
//外部或者內部晶振(12M)
TH0 = 0xFF; //重灌定時器初始值高8位
TL0 = 0xBF; //重灌定時器初始值低8位(初值大,頻率大)
sine_1++; //A相位查表數值
sine_2++; //B相位查表數值
sine_3++; //C相位查表數值
CCAP0H = CCAP0L = pwm[sine_1];
CCAP1H = CCAP1L = pwm[sine_2];
CCAP2H = CCAP2L = pwm[sine_3];
if(sine_1>cry_out) sine_1=0; //數值大,頻率小
if(sine_2>cry_out) sine_2=0;
if(sine_3>cry_out) sine_3=0;
}
形成的SPWM影象:
附:pwm陣列是用excel表的sin公式算出來的。