标题:
单片机驱动cpld的pwm正弦信号发生器设计
[打印本页]
作者:
苹果也疯狂
时间:
2015-8-17 10:05
标题:
单片机驱动cpld的pwm正弦信号发生器设计
脉宽调制pwm(pulse width modulation)是利用数字输出信号对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。
一、pwm原理
pwm 是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。pwm 信号仍然是数字的,因为在给定的任何时刻,满幅值的直流供电要么完全有(on),要么完全无(off)。电压或电流源是以一种通(on) 或断(off) 的重复脉冲序列被加到模拟负载上去的。通的时候即是直流供电被加到负载上的时候,断的时候即是供电被断开的时候。
只要带宽足够,任何模拟值都可以使用pwm 进行编码。
如图1 所示,用一系列等幅不等宽的脉冲来代替一个正弦半波,正弦半波n 等分,看成n 个相连的脉冲序列,宽度相等,但幅值不等;用矩形脉冲代替,等幅,不等宽,中点重合,面积(冲量)相等,宽度按正弦规律变化。
图1 用pwm波代替正弦半波
spwm 波形——脉冲宽度按正弦规律变化而和正弦波等效的pwm 波形。
二、基于cpld的pwm方案
一个pwm 发生器必须包括计数器,数据比较器,另外就是配置pwm 参数的时钟分频寄存器和占空比寄存器,结构框图如图2 所示,这些电路都可以用cpld 来实现。
图2 pwm
控制器
结构框图
高频时钟信号经分频器驱动计数器,计数器如图3 所示,总是从bottom 到top 的循环计数,计数器的输出和占空比寄存器里的数据经数据比较器比较,输出pwm 信号,当计数器输出小于占空比设定值时输出低电平(0),否则输出高电平(1),如图3(b)(c)所示。
图3 pwm信号发生器时序波形图
从图中还可以看出,计数器的周期就是pwm 信号的周期,通过修改占空比寄存器从而实现对输出pwm 信号高低电平比例控制,图3(b)是占空比为p1 的pwm输出,图3(c)是占空比为p2 的pwm 输出,它们周期相同,高低电平的比例不同。
下面用硬件描述语言来设计cpld 的内部电路,这里给出veriloghdl 版本的参考代码。
module mini51b_pwm(p0,ale,p27,wr,pwm);// 模块电路命名和端口说明。
input [7:0]p0;// 数据输入接mcu 数据p0 口
input ale,p27,wr;// 几个mcu 读写控制引脚
output pwm;//pwm 信号输出
wire [7:0]addr;// 内部地址线
reg [7:0]dapwmc,dapwms;// 定义计数器和占空比设定寄存器
reg [3:0]divpwm,divpwmc;// 分频控制变量
reg pwm;// 输出锁存器
assign addr = ale?p0 : addr; // 低八位地址锁存
always @(negedge wr)// 在mcu 写信号有效时执行寄存器设定
begin
case({p27,addr[4:0]}) // 根据地址选择寄存器
6'b10_1000: dapwms <= p0;// 写带地址的寄存器
6'b10_1001: divpwm <= p0[3:0];// 写带地址的寄存器
default:begin// 其它地址则让寄存器保持不变
dapwms <= dapwms;
divpwm <= divpwm;
end
endcase
end
always @(posedge ale) begin// 这里利用mcu 的ale 做时钟信号
if(divpwmc == divpwm) begin // 与分频系数比较
divpwmc<=0;
if(dapwmc<100) dapwmc <= dapwmc+1; //pwm 调整精度1%
else dapwmc <= 0;
if(dapwms < dapwmc) pwm <= 0;//pwm 发生器
else pwm <= 1;
end
else divpwmc <= divpwmc+1;// 时钟分频
end
endmodule
关于单片机与cpld 之间的接口请读者参考本刊前几期笔者撰写的文章。
与之对应的mcu 测试程序为:
#include <reg51.h>
#include <absacc.h>
#define pwm xbyte[0xffe8]
#define div xbyte[0xffe9]
void main()
{
div = 15; //pwm 信号频率计算晶振22.1184m/6/100/
(div+1)=2.30k(实测2.281k)
pwm=50; // 设定占空比50%,前面计数器范围为0~99
while(1) ;
}
执行单片机程序,选择不同的分频系数和占空比值,从cpld 的引脚输出pwm 信号示波器截图如图4所示。
图4 不同占空比的pwm信号示波器截图
三、spwm
如果将占空比按正弦规律随着时间变化,就可以得到正弦调制的pwm 信号,也就是spwm。如图5 所示,该信号经过阻容滤波可以得到正弦模拟信号,这里的运放做电压跟随器用,对信号驱动能力进行放大。实际得到的正弦信号示波器截图效果如图6 所示。
图5 spwm阻容滤波电路
图6 正弦信号示波器截图
正弦信号发生器mcu 演示程序:
#include <reg51.h>
#include <absacc.h>
#define pwm xbyte[0xffe8]
unsigned char code sine_dot[32]={49,59,68,77,84,90,95,98,99,98,95,90,84,77,68,59,49,40,30,22,14,8,4,1,0,1,4,8,14,22,30,40};// 正弦表
void main()
{
unsigned char i=0;
while(1) {
pwm = sine_dot
;
i=(i++)&0x1f;
}// 如果要严格控制spwm 的周期,这里的while 循环请用定时器来驱动
}
四、三路精确相位差正弦信号发生器
对cpld 改进设计,很容易实现多路pwm 输出。
例如设计具有精确相位差的三相正弦信号,cpld 电路veriloghdl 程序如下:
module mini51b_pwm(p0,ale,p27,wr,pwm);
input [7:0]p0;
input ale,p27,wr;
output [2:0]pwm;
wire [3:0]addr;
reg [7:0]dapwmc;
reg [7:0]dapwms0,dapwms1,dapwms2;
reg [2:0]pwm;
wire clk,nclk,a,b,c,d;
assign addr= (ale)?p0[3:0]:addr; // 低八位地址锁存
always @(negedge wr)
begin
case({p27,addr})
5'h10: dapwms0 <= p0;// 写带地址的寄存器
5'h11: dapwms1 <= p0;// 写带地址的寄存器
5'h12: dapwms2 <= p0;// 写带地址的寄存器
default:
begin
dapwms0 <= dapwms0;
dapwms1 <= dapwms1;
dapwms2 <= dapwms2;
end
endcase
end
always @(posedge clk) begin
dapwmc <= dapwmc+1; //pwm 调整精度1%
if(dapwms0 < dapwmc) pwm[0] <= 0;//pwm 发生器
else pwm[0] <= 1;
if(dapwms1 < dapwmc) pwm[1] <= 0;//pwm 发生器
else pwm[1] <= 1;
if(dapwms2 < dapwmc) pwm[2] <= 0;//pwm 发生器
else pwm[2] <= 1;
end
assign nclk=!clk;
lcell a0(。in(nclk), .out(a));
lcell a1(。in(a), .out(b));
lcell a2(。in(b), .out(c));
lcell a3(。in(c), .out(d));
lcell a4(。in(d), .out(clk));//pwm 时钟来自cpld 内部
lcell 延迟电路振荡器
endmodule
与之对应的mcu 演示程序:
#include <reg51.h>
#include <absacc.h>
#define pwm0 xbyte[0xfff0]
#define pwm1 xbyte[0xfff1]
#define pwm2 xbyte[0xfff2]
unsigned char code sine_dot[36]= //8 阶,36 点正弦表
{
0x80,0x96,0xab,0xbf,0xd2,0xe2,0xee,0xf8,0xfe,0xff,0xfe,0xf8,
0xee,0xe2,0xd2,0xc0,0xab,0x96,0x80,0x69,0x54,0x40,0x2
d,0x1e,
0x11,0x07,0x01,0x00,0x01,0x07,0x10,0x1d,0x2d,0x3f,0x53,
0x69
};
void main()
{
unsigned char a,b,c;
a=0;
while(1) {
a %= 36;// 对36 取余数及0~35
b=(a+12)%36;// 较a 路滞后120 度相位
c=(a+24)%36;// 较a 路滞后240 度相位
pwm0 = sine_dot[a];
pwm1 = sine_dot
;
pwm2 = sine_dot[c];
a++;
}
}
实际得到的三相正弦信号示波器截图效果如图7所示,只是双踪示波器同时只能看两路信号。
图7 具有精确相位差的三相正弦信号示波器截图
五、结束语
今后,mcu+cpld 结构将是很多电子系统设计的一种基本架构,mcu 可以用程序实现复杂智能的控制与检测,cpld 又可以实现灵活多变的外围扩展电路设计,尤其是可以用硬件实现特殊的mcu 无法实现的功能,弥补mcu 响应速度慢影响实时性问题,两者互补,完全实现硬件软设计,使得同一硬件平台能够通过软件实现更多的功能。
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/)
Powered by Discuz! 7.0.0