首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

单片机驱动cpld的pwm正弦信号发生器设计

单片机驱动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 响应速度慢影响实时性问题,两者互补,完全实现硬件软设计,使得同一硬件平台能够通过软件实现更多的功能。
返回列表