本帖最后由 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;重复上述比较即可。
- LIBRARY IEEE;
- USE IEEE.STD_LOGIC_1164.ALL;
- USE IEEE.STD_LOGIC_UNSIGNED.ALL;
- ENTITY spwm_test IS
- PORT(sysclk :IN STD_LOGIC;
- pwm_output :OUT STD_LOGIC);
- END ENTITY spwm_test;
- ARCHITECTURE rlt OF spwm_test IS
- COMPONENT sin_512 IS --声明ROM元件
- PORT
- (
- address : IN STD_LOGIC_VECTOR (8 DOWNTO 0); --ROM地址信号
- clock : IN STD_LOGIC := '1'; --时钟信号
- q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0) ---输出信号
- );
- END COMPONENT;
- SIGNAL counter :INTEGER RANGE 0 TO 256; --用于计数
- SIGNAL addr :STD_LOGIC_VECTOR (8 DOWNTO 0) ; --ROM地址
- SIGNAL rom_data :STD_LOGIC_VECTOR (6 DOWNTO 0) ; --ROM数据
- BEGIN
- u2: sin_512 PORT MAP(addr, sysclk, rom_data); --实例化ROM元件
- PROCESS(sysclk) IS
-
- BEGIN
- IF(sysclk'EVENT AND sysclk = '1') THEN
- counter <= counter + 1;
- IF(counter = 256) THEN
- counter <= 0;
- addr <= addr + 1; -- 比较完256个数据后ROM地址加1,读取下一ROM单元中的储存数据
- END IF;
- IF(rom_data > counter)THEN --比较生成PWM
- pwm_output <= '1';
- ELSE
- pwm_output <= '0';
- END IF;
- END IF;
- END PROCESS;
- END ARCHITECTURE;
复制代码
等等会更简单:lol
一周热门 更多>