单片机SPWM的产生

2019-04-15 12:20发布

电赛刚结束不久,期间我做的题目需要用单片产生一个三相的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 #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 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公式算出来的。