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

xiaoxiao2021-02-28  72

转自 光电科技协会 王诚博

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

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

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

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

如图:

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

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

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

2.做差,使用阈值。

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

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

取出了200个点,如图:

放大观察:

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

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

然后就可以画出spwm波形:

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

如图:

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

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

如果使用DAC描点:

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

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

下面粘上MATLAB源代码:

[cpp] view plain copy print ? %% 变量初始化  t=0.02;%正弦波周期  th=t/2;%半波周期  m=10;%三角波周期数  a=0:0.0001:1;  y3=0:0.0001:1;  P=1;  x=zeros(1);%分配空间  tp=zeros(1);  ti=zeros(1);  %% 产生正弦波与三角波叠加  y1=abs(sawtooth(a*2*pi*m,0.5));%三角波  y2=0.8*sin(a*pi);%正弦波  figure(1)  plot(a,y1,a,y2)  %% 取点  %[X Y]=ginput(40)%图像中取点(不精确)  % save('kuan','X');  for i=1:length(y1)%利用差值取点,设定阈值      if(abs(y1(i)-y2(i))<0.01)          X(P)=a(i);          P=P+1;      end  end  figure(2)  plot(a,y1,a,y2,X,1,'*')  for i=0:m*4-1%取平均值          x(i+1)=(X((i+1)*5)+X(i*5+1))/2;  end  figure(3)  plot(a,y1,a,y2,x,1,'*')  %% 画出SPWM波形  for n=1:m*2         y3(1:floor(x(1)*10000))=0;         y3(floor(x(2*n-1)*10000):floor(x(2*n)*10000))=0.8;         if(n==20)         break         end         y3(floor(x(2*n)*10000):floor(x(2*(n+1)-1)*10000))=0;         y3(floor(x(40)*10000):length(y3))=0;  end  figure(4)  plot(a,y3)  axis([0 1 0 1])  %% DAC描点法(速度太慢舍弃)  % b=floor(linspace(0,1,258)*10000);  % for i=1:256  % y4(i)=floor(y3(b(i+1))*4095);  % end  % dlmwrite('dac_SPWM.c',y4);  %% 计算SPWM的周期,占空比(利用输出比较器)  for i=1:m      tp(i)=(x(2*(i+1)-1)-x(2*i-1))*th;%spwm周期      ti(i)=(x(2*i)-x(2*i-1))*th;%脉冲宽度  end  tc=[floor(tp./max(tp)*255),fliplr(floor(tp./max(tp)*255))];%单片机定时器从1计到255(最大spwm周期)  dlmwrite('cycle.c',tc);%写入c文件  p=ti./tp;%计算spwm占空比  p1=[p fliplr(p)];%半个正弦波周期spwm的占空比序列  p1=floor(p1.*tc);%单片机定时器基准脉冲宽度  dlmwrite('dac_sinWave.c',p1);      %% 变量初始化 t=0.02;%正弦波周期 th=t/2;%半波周期 m=10;%三角波周期数 a=0:0.0001:1; y3=0:0.0001:1; P=1; x=zeros(1);%分配空间 tp=zeros(1); ti=zeros(1); %% 产生正弦波与三角波叠加 y1=abs(sawtooth(a*2*pi*m,0.5));%三角波 y2=0.8*sin(a*pi);%正弦波 figure(1) plot(a,y1,a,y2) %% 取点 %[X Y]=ginput(40)%图像中取点(不精确) % save('kuan','X'); for i=1:length(y1)%利用差值取点,设定阈值 if(abs(y1(i)-y2(i))<0.01) X(P)=a(i); P=P+1; end end figure(2) plot(a,y1,a,y2,X,1,'*') for i=0:m*4-1%取平均值 x(i+1)=(X((i+1)*5)+X(i*5+1))/2; end figure(3) plot(a,y1,a,y2,x,1,'*') %% 画出SPWM波形 for n=1:m*2 y3(1:floor(x(1)*10000))=0; y3(floor(x(2*n-1)*10000):floor(x(2*n)*10000))=0.8; if(n==20) break end y3(floor(x(2*n)*10000):floor(x(2*(n+1)-1)*10000))=0; y3(floor(x(40)*10000):length(y3))=0; end figure(4) plot(a,y3) axis([0 1 0 1]) %% DAC描点法(速度太慢舍弃) % b=floor(linspace(0,1,258)*10000); % for i=1:256 % y4(i)=floor(y3(b(i+1))*4095); % end % dlmwrite('dac_SPWM.c',y4); %% 计算SPWM的周期,占空比(利用输出比较器) for i=1:m tp(i)=(x(2*(i+1)-1)-x(2*i-1))*th;%spwm周期 ti(i)=(x(2*i)-x(2*i-1))*th;%脉冲宽度 end tc=[floor(tp./max(tp)*255),fliplr(floor(tp./max(tp)*255))];%单片机定时器从1计到255(最大spwm周期) dlmwrite('cycle.c',tc);%写入c文件 p=ti./tp;%计算spwm占空比 p1=[p fliplr(p)];%半个正弦波周期spwm的占空比序列 p1=floor(p1.*tc);%单片机定时器基准脉冲宽度 dlmwrite('dac_sinWave.c',p1);

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

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

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

[cpp] view plain copy print ? TIM3->ARR = indexcycle[pwm_index];     TIM3->CCR2 = indexWave[pwm_index];     TIM3->CCR3 = indexWave[pwm_index];        TIM3->CCR4 = indexWave[pwm_index];     pwm_index++;                                                   TIM3->ARR = indexcycle[pwm_index]; TIM3->CCR2 = indexWave[pwm_index]; TIM3->CCR3 = indexWave[pwm_index]; TIM3->CCR4 = indexWave[pwm_index]; pwm_index++;

定时器配置

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

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

看出这是SPWM波形。

转载请注明原文地址: https://www.6miu.com/read-63904.html

最新回复(0)