STM32
直播中

efwedfd

8年用户 1045经验值
擅长:EMC/EMI设计
私信 关注
[问答]

如何去计算正弦波半个周期的SPWM的周期和占空比呢

SPWM波形生成的原理是什么?
如何利用matlab产生三角波与正弦波叠加呢?
如何去计算正弦波半个周期的SPWM的周期和占空比呢?

回帖(1)

王丽娟

2021-11-18 09:13:11
  先上一张spwm波形生成原理图:
  
  首先利用MATLAB产生三角波与正弦波叠加:
  %% 产生正弦波与三角波叠加
  y1=abs(sawtooth(a*2*pi*m,0.5));%三角波
  y2=0.8*sin(a*pi);%正弦波
  figure(1)
  plot(a,y1,a,y2)
  如图:
  
  接着取交点,想了两种方法:
  1.直接图片上取点,该方法不精确,毕竟只能目测和用鼠标点击。
  [X Y]=ginput(40)%图像中取点(不精确)
  save(‘kuan’,‘X’);
  2.做差,使用阈值。
  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个,所以假设正弦波与三角波交点附近正弦波斜率不变,所以采用平均的方法:
  for i=0:m*4-1%取平均值
  x(i+1)=(X((i+1)*5)+X(i*5+1))/2;
  end
  然后就可以画出spwm波形:
  %% 画出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波):
  %% 计算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描点:
  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源代码:
  %% 变量初始化
  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):
  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};
  在中断中改变寄存器的值(三路输出):
  TIM3-》ARR = indexcycle[pwm_index];
  TIM3-》CCR2 = indexWave[pwm_index];
  TIM3-》CCR3 = indexWave[pwm_index];
  TIM3-》CCR4 = indexWave[pwm_index];
  pwm_index++;
  定时器配置
  /*基本定时器配置*/
  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);
  /*PWM模式配置*/
  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;
  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波形。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分