基于FPGA的正弦脉宽调制波设计(二)

2020-02-17 19:52发布

本帖最后由 IT举人 于 2015-5-16 21:24 编辑

    在上一篇帖子中我们已经保存了我们所需的正弦波数据点,现在我们需要的就是把它输出来。由于实验板上无数模转换(D/A)芯片,因此需设计一PWM发生器。正弦波数据输入PWM发生器,产生PWM信号,PWM信号经过RC低通滤波器输出模拟电压。如图2-1所示图2-1    低通滤波器选取R 为108欧,C选104,即可。    好,接下来说说怎么根据正弦波数据产生PWM,即是完成PWM发生器部分。在这里再说一下,这个PWM实际上也是SPWM来的,即是脉冲宽度时间占空比按正弦规律排列。那么它和上面那个由三角波比较产生的spwm有什么不同呢?不同在于三角波比较获得的spwm频率比较低,从而可以在示波器上显示出来,但不能通过低通滤波器产生模拟正弦波。相反PWM发生器产生的spwm频率比较高,在示波器上不能很好地显示出来,但可以通过低通滤波器产生模拟正弦波。
    大家看回我们上一贴中产生的正弦波
图2-2这个波形的峰顶值为256,峰谷为0。那么大家想象一下就能知道,它的峰顶值对应的PWM的占空比为100%,峰谷对应PWM的占空比为0%,那么设一数据78对应的占空比呢?理想当然是78/256 。所以这里我们就可以很自然地设定我们的PWM输出的周期为256个时钟周期,那么任一数据点对应的占空比就为Yn/256(Yn/为上一贴中存储在ROM中的sin的值)。好,接下来就是重点,程序实现了。其实也不是很难,我们只需要设置一个计数值counter,每个时钟周期来就自加1(从0加到256),然后再和Yn比较,当Yn > counter时,PWM输出端口(即是一个普通的io口,我们用它来输出PWM)置‘1’,当Yn  < counter时,PWM输出端口置‘0’。例如当Yn = 78时,那么PWM输出端口就有78个时钟周期处于高电平,178个时钟周期处于低电平,它的占空比是不是就是78/256了呢?比较完256个数据后,ROM的地址加1,读取出另一个正弦值Yn+1;重复上述比较即可。
  1. LIBRARY IEEE;
  2. USE IEEE.STD_LOGIC_1164.ALL;
  3. USE IEEE.STD_LOGIC_UNSIGNED.ALL;

  4. ENTITY spwm_test IS
  5. PORT(sysclk :IN STD_LOGIC;
  6.                 pwm_output :OUT STD_LOGIC);
  7. END ENTITY spwm_test;

  8. ARCHITECTURE rlt OF spwm_test IS

  9. COMPONENT sin_512 IS   --声明ROM元件
  10.         PORT
  11.         (
  12.                 address                : IN STD_LOGIC_VECTOR (8 DOWNTO 0);  --ROM地址信号
  13.                 clock                : IN STD_LOGIC  := '1';            --时钟信号
  14.                 q                : OUT STD_LOGIC_VECTOR (7 DOWNTO 0)   ---输出信号
  15.         );
  16. END COMPONENT;

  17. SIGNAL counter :INTEGER RANGE 0 TO 256;   --用于计数
  18. SIGNAL addr :STD_LOGIC_VECTOR (8 DOWNTO 0) ;   --ROM地址
  19. SIGNAL rom_data :STD_LOGIC_VECTOR (6 DOWNTO 0) ;  --ROM数据
  20. BEGIN

  21. u2: sin_512 PORT MAP(addr, sysclk, rom_data);  --实例化ROM元件

  22. PROCESS(sysclk) IS
  23.         
  24.         BEGIN
  25.                 IF(sysclk'EVENT AND sysclk = '1') THEN
  26.                         counter <= counter + 1;   
  27.                         IF(counter = 256) THEN
  28.                                 counter <= 0;
  29.                                 addr <= addr + 1;    -- 比较完256个数据后ROM地址加1,读取下一ROM单元中的储存数据
  30.                         END IF;
  31.                         IF(rom_data > counter)THEN  --比较生成PWM        
  32.                                 pwm_output <= '1';
  33.                         ELSE
  34.                                 pwm_output <= '0';
  35.                         END IF;
  36.                 END IF;
  37.         END PROCESS;        
  38. END ARCHITECTURE;
复制代码

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。