利用MATLAB计算SPWM脉冲宽度与并应用STM32输出

来源:互联网 发布:淘宝达摩盘是什么 编辑:程序博客网 时间:2024/05/16 04:44

转自 光电科技协会 王诚博

http://blog.csdn.net/wcb425499094/article/details/76703042

先上一张spwm波形生成原理图:


首先利用MATLAB产生三角波与正弦波叠加:

[cpp] view plain copy print?
  1. %% 产生正弦波与三角波叠加  
  2. y1=abs(sawtooth(a*2*pi*m,0.5));%三角波  
  3. y2=0.8*sin(a*pi);%正弦波  
  4. figure(1)  
  5. plot(a,y1,a,y2)  

如图:


接着取交点,想了两种方法:

1.直接图片上取点,该方法不精确,毕竟只能目测和用鼠标点击。

[cpp] view plain copy print?
  1. [X Y]=ginput(40)%图像中取点(不精确)  
  2. save('kuan','X');  

2.做差,使用阈值。

[cpp] view plain copy print?
  1. for i=1:length(y1)%利用差值取点,设定阈值  
  2.     if(abs(y1(i)-y2(i))<0.01)  
  3.         X(P)=a(i);  
  4.         P=P+1;  
  5.     end  
  6. end  


阈值设置为0.001只取出20个点,但如上图应该有40个点,所以增大阈值,设为0.01。

取出了200个点,如图:


放大观察:

可知每个交点取出了5个点,40个点刚好200个,所以假设正弦波与三角波交点附近正弦波斜率不变,所以采用平均的方法:

[html] view plain copy print?
  1. for i=0:m*4-1%取平均值  
  2.         x(i+1)=(X((i+1)*5)+X(i*5+1))/2;  
  3. end  

然后就可以画出spwm波形:

[cpp] view plain copy print?
  1. %% 画出SPWM波形  
  2. for n=1:m*2  
  3.        y3(1:floor(x(1)*10000))=0;  
  4.        y3(floor(x(2*n-1)*10000):floor(x(2*n)*10000))=0.8;  
  5.        if(n==20)  
  6.        break  
  7.        end  
  8.        y3(floor(x(2*n)*10000):floor(x(2*(n+1)-1)*10000))=0;  
  9.        y3(floor(x(40)*10000):length(y3))=0;  
  10. end  
  11. figure(4)  
  12. plot(a,y3)  
  13. axis([0 1 0 1])  


如图:


最后,计算正弦波半个周期的spwm的周期和占空比(使用stm32输出比较器输出pwm波):

[cpp] view plain copy print?
  1. %% 计算SPWM的周期,占空比(利用输出比较器)  
  2. for i=1:m  
  3.     tp(i)=(x(2*(i+1)-1)-x(2*i-1))*th;%spwm周期  
  4.     ti(i)=(x(2*i)-x(2*i-1))*th;%脉冲宽度  
  5. end  
  6. tc=[floor(tp./max(tp)*255),fliplr(floor(tp./max(tp)*255))];%单片机定时器从1计到255(最大spwm周期)  
  7. dlmwrite('cycle.c',tc);%写入c文件  
  8. p=ti./tp;%计算spwm占空比  
  9. p1=[p fliplr(p)];%半个正弦波周期spwm的占空比序列  
  10. p1=floor(p1.*tc);%单片机定时器基准脉冲宽度  
  11. dlmwrite('dac_sinWave.c',p1);  

如果使用DAC描点:

[cpp] view plain copy print?
  1. b=floor(linspace(0,1,258)*10000);  
  2. for i=1:256  
  3. y4(i)=floor(y3(b(i+1))*4095);  
  4. end  
  5. dlmwrite('dac_SPWM.c',y4);  

但该方法速度太慢,而且单片机利用效率太低,所以舍弃。

下面粘上MATLAB源代码:

[cpp] view plain copy print?
  1. %% 变量初始化  
  2. t=0.02;%正弦波周期  
  3. th=t/2;%半波周期  
  4. m=10;%三角波周期数  
  5. a=0:0.0001:1;  
  6. y3=0:0.0001:1;  
  7. P=1;  
  8. x=zeros(1);%分配空间  
  9. tp=zeros(1);  
  10. ti=zeros(1);  
  11. %% 产生正弦波与三角波叠加  
  12. y1=abs(sawtooth(a*2*pi*m,0.5));%三角波  
  13. y2=0.8*sin(a*pi);%正弦波  
  14. figure(1)  
  15. plot(a,y1,a,y2)  
  16. %% 取点  
  17. %[X Y]=ginput(40)%图像中取点(不精确)  
  18. % save('kuan','X');  
  19. for i=1:length(y1)%利用差值取点,设定阈值  
  20.     if(abs(y1(i)-y2(i))<0.01)  
  21.         X(P)=a(i);  
  22.         P=P+1;  
  23.     end  
  24. end  
  25. figure(2)  
  26. plot(a,y1,a,y2,X,1,'*')  
  27. for i=0:m*4-1%取平均值  
  28.         x(i+1)=(X((i+1)*5)+X(i*5+1))/2;  
  29. end  
  30. figure(3)  
  31. plot(a,y1,a,y2,x,1,'*')  
  32. %% 画出SPWM波形  
  33. for n=1:m*2  
  34.        y3(1:floor(x(1)*10000))=0;  
  35.        y3(floor(x(2*n-1)*10000):floor(x(2*n)*10000))=0.8;  
  36.        if(n==20)  
  37.        break  
  38.        end  
  39.        y3(floor(x(2*n)*10000):floor(x(2*(n+1)-1)*10000))=0;  
  40.        y3(floor(x(40)*10000):length(y3))=0;  
  41. end  
  42. figure(4)  
  43. plot(a,y3)  
  44. axis([0 1 0 1])  
  45. %% DAC描点法(速度太慢舍弃)  
  46. % b=floor(linspace(0,1,258)*10000);  
  47. for i=1:256  
  48. % y4(i)=floor(y3(b(i+1))*4095);  
  49. % end  
  50. % dlmwrite('dac_SPWM.c',y4);  
  51. %% 计算SPWM的周期,占空比(利用输出比较器)  
  52. for i=1:m  
  53.     tp(i)=(x(2*(i+1)-1)-x(2*i-1))*th;%spwm周期  
  54.     ti(i)=(x(2*i)-x(2*i-1))*th;%脉冲宽度  
  55. end  
  56. tc=[floor(tp./max(tp)*255),fliplr(floor(tp./max(tp)*255))];%单片机定时器从1计到255(最大spwm周期)  
  57. dlmwrite('cycle.c',tc);%写入c文件  
  58. p=ti./tp;%计算spwm占空比  
  59. p1=[p fliplr(p)];%半个正弦波周期spwm的占空比序列  
  60. p1=floor(p1.*tc);%单片机定时器基准脉冲宽度  
  61. dlmwrite('dac_sinWave.c',p1);  
  62.    


stm32程序是用野火的例程改的,经过MATLAB计算得出周期与占空比(放入定时器的自动重装载寄存器ARR和比较寄存器CRR):

[cpp] view plain copy print?
  1. uint8_t indexWave[] = {16,47,78,106,132,155,174,188,198,203,203,198,  
  2. 188,174,155,132,106,78,47,16};  
  3. uint8_t indexcycle[] = {241,241,242,243,244,246,248,250,252,255,255,  
  4. 252,250,248,246,244,243,242,241,241};  


在中断中改变寄存器的值(三路输出):

[cpp] view plain copy print?
  1. TIM3->ARR = indexcycle[pwm_index];     
  2. TIM3->CCR2 = indexWave[pwm_index];     
  3. TIM3->CCR3 = indexWave[pwm_index];        
  4. TIM3->CCR4 = indexWave[pwm_index];     
  5. pwm_index++;                                                  


定时器配置

[cpp] view plain copy print?
  1. /*基本定时器配置*/  
[cpp] view plain copy print?
  1. TIM_TimeBaseStructure.TIM_Period = 255;                                    
  2. TIM_TimeBaseStructure.TIM_Prescaler = 0;                                      
  3. TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1 ;              
  4. TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;    
  5. TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);  
[cpp] view plain copy print?
  1. /*PWM模式配置*/  
[cpp] view plain copy print?
  1. TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;                         
  2.  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;    
  3.  TIM_OCInitStructure.TIM_Pulse = 0;                                                   
  4.  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;                                                          <span style="font-family: Arial, Helvetica, sans-serif;">   </span>  
[cpp] view plain copy print?
  1. TIM_OC2Init(TIM3, &TIM_OCInitStructure);  
  2. TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);  
  3.     
  4. TIM_OC3Init(TIM3, &TIM_OCInitStructure);      
  5. TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);  
  6.     
  7. TIM_OC4Init(TIM3, &TIM_OCInitStructure);  
  8. TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);  
  9. TIM_ARRPreloadConfig(TIM3, ENABLE);  
  10. /* TIM3 enable counter */  
  11. TIM_Cmd(TIM3, ENABLE);    
  12.   
  13. TIM_ITConfig(TIM3,TIM_IT_Update, ENABLE);  
  14.           
  15. NVIC_Config_PWM();  



使用示波器观察得到SPWM输出:

看出这是SPWM波形。


原创粉丝点击