單片機(jī)驅(qū)動(dòng)CPLD的PWM正弦信號(hào)發(fā)生器設(shè)計(jì)
掃描二維碼
隨時(shí)隨地手機(jī)看文章
前面幾期給讀者介紹了單片機(jī)+CPLD 系統(tǒng)設(shè)計(jì),本篇繼續(xù)挖掘CPLD 潛力,給出一種單片機(jī)驅(qū)動(dòng)CPLD的PWM 正弦信號(hào)發(fā)生器設(shè)計(jì),充分體現(xiàn)了CPLD 的靈活多變,配合單片機(jī)控制,其妙無(wú)窮,以下方案均在Mini51 板上實(shí)現(xiàn)。
脈寬調(diào)制PWM(Pulse Width Modulation)是利用數(shù)字輸出信號(hào)對(duì)模擬電路進(jìn)行控制的一種非常有效的技術(shù),廣泛應(yīng)用在從測(cè)量、通信到功率控制與變換的許多領(lǐng)域中。
一、PWM原理
PWM 是一種對(duì)模擬信號(hào)電平進(jìn)行數(shù)字編碼的方法。通過(guò)高分辨率計(jì)數(shù)器的使用,方波的占空比被調(diào)制用來(lái)對(duì)一個(gè)具體模擬信號(hào)的電平進(jìn)行編碼。PWM 信號(hào)仍然是數(shù)字的,因?yàn)樵诮o定的任何時(shí)刻,滿(mǎn)幅值的直流供電要么完全有(ON),要么完全無(wú)(OFF)。電壓或電流源是以一種通(ON) 或斷(OFF) 的重復(fù)脈沖序列被加到模擬負(fù)載上去的。通的時(shí)候即是直流供電被加到負(fù)載上的時(shí)候,斷的時(shí)候即是供電被斷開(kāi)的時(shí)候。
只要帶寬足夠,任何模擬值都可以使用PWM 進(jìn)行編碼。
如圖1 所示,用一系列等幅不等寬的脈沖來(lái)代替一個(gè)正弦半波,正弦半波N 等分,看成N 個(gè)相連的脈沖序列,寬度相等,但幅值不等;用矩形脈沖代替,等幅,不等寬,中點(diǎn)重合,面積(沖量)相等,寬度按正弦規(guī)律變化。
圖1 用PWM波代替正弦半波
SPWM 波形——脈沖寬度按正弦規(guī)律變化而和正弦波等效的PWM 波形。
二、基于CPLD的PWM方案
一個(gè)PWM 發(fā)生器必須包括計(jì)數(shù)器,數(shù)據(jù)比較器,另外就是配置PWM 參數(shù)的時(shí)鐘分頻寄存器和占空比寄存器,結(jié)構(gòu)框圖如圖2 所示,這些電路都可以用CPLD 來(lái)實(shí)現(xiàn)。
圖2 PWM控制器結(jié)構(gòu)框圖
高頻時(shí)鐘信號(hào)經(jīng)分頻器驅(qū)動(dòng)計(jì)數(shù)器,計(jì)數(shù)器如圖3 所示,總是從Bottom 到Top 的循環(huán)計(jì)數(shù),計(jì)數(shù)器的輸出和占空比寄存器里的數(shù)據(jù)經(jīng)數(shù)據(jù)比較器比較,輸出PWM 信號(hào),當(dāng)計(jì)數(shù)器輸出小于占空比設(shè)定值時(shí)輸出低電平(0),否則輸出高電平(1),如圖3(b)(c)所示。
圖3 PWM信號(hào)發(fā)生器時(shí)序波形圖
從圖中還可以看出,計(jì)數(shù)器的周期就是PWM 信號(hào)的周期,通過(guò)修改占空比寄存器從而實(shí)現(xiàn)對(duì)輸出PWM 信號(hào)高低電平比例控制,圖3(b)是占空比為P1 的PWM輸出,圖3(c)是占空比為P2 的PWM 輸出,它們周期相同,高低電平的比例不同。
下面用硬件描述語(yǔ)言來(lái)設(shè)計(jì)CPLD 的內(nèi)部電路,這里給出VerilogHDL 版本的參考代碼。
module Mini51b_PWM(P0,ALE,P27,WR,PWM);// 模塊電路命名和端口說(shuō)明。
input [7:0]P0;// 數(shù)據(jù)輸入接MCU 數(shù)據(jù)P0 口
input ALE,P27,WR;// 幾個(gè)MCU 讀寫(xiě)控制引腳
output PWM;//PWM 信號(hào)輸出
wire [7:0]addr;// 內(nèi)部地址線(xiàn)
reg [7:0]daPWMc,daPWMs;// 定義計(jì)數(shù)器和占空比設(shè)定寄存器
reg [3:0]divPWM,divPWMc;// 分頻控制變量
reg PWM;// 輸出鎖存器
assign addr = ALE?P0 : addr; // 低八位地址鎖存
always @(negedge WR)// 在MCU 寫(xiě)信號(hào)有效時(shí)執(zhí)行寄存器設(shè)定
begin
case({P27,addr[4:0]}) // 根據(jù)地址選擇寄存器
6'b10_1000: daPWMs <= P0;// 寫(xiě)帶地址的寄存器
6'b10_1001: divPWM <= P0[3:0];// 寫(xiě)帶地址的寄存器
default:begin// 其它地址則讓寄存器保持不變
daPWMs <= daPWMs;
divPWM <= divPWM;
end
endcase
end
always @(posedge ALE) begin// 這里利用MCU 的ALE 做時(shí)鐘信號(hào)
if(divPWMc == divPWM) begin // 與分頻系數(shù)比較
divPWMc<=0;
if(daPWMc<100) daPWMc <= daPWMc+1; //PWM 調(diào)整精度1%
else daPWMc <= 0;
if(daPWMs < daPWMc) PWM <= 0;//PWM 發(fā)生器
else PWM <= 1;
end
else divPWMc <= divPWMc+1;// 時(shí)鐘分頻
end
endmodule
關(guān)于單片機(jī)與CPLD 之間的接口請(qǐng)讀者參考本刊前幾期筆者撰寫(xiě)的文章。
與之對(duì)應(yīng)的MCU 測(cè)試程序?yàn)椋?/p>
#include
#include
#define PWM XBYTE[0xffe8]
#define DIV XBYTE[0xffe9]
void main()
{
DIV = 15; //PWM 信號(hào)頻率計(jì)算晶振22.1184M/6/100/
(DIV+1)=2.30K(實(shí)測(cè)2.281K)
PWM=50; // 設(shè)定占空比50%,前面計(jì)數(shù)器范圍為0~99
while(1) ;
}
執(zhí)行單片機(jī)程序,選擇不同的分頻系數(shù)和占空比值,從CPLD 的引腳輸出PWM 信號(hào)示波器截圖如圖4所示。
圖4 不同占空比的PWM信號(hào)示波器截圖
三、SPWM
如果將占空比按正弦規(guī)律隨著時(shí)間變化,就可以得到正弦調(diào)制的PWM 信號(hào),也就是SPWM。如圖5 所示,該信號(hào)經(jīng)過(guò)阻容濾波可以得到正弦模擬信號(hào),這里的運(yùn)放做電壓跟隨器用,對(duì)信號(hào)驅(qū)動(dòng)能力進(jìn)行放大。實(shí)際得到的正弦信號(hào)示波器截圖效果如圖6 所示。
圖5 SPWM阻容濾波電路[!--empirenews.page--]
圖6 正弦信號(hào)示波器截圖
正弦信號(hào)發(fā)生器MCU 演示程序:
#include
#include
#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=(i++)&0x1f;
}// 如果要嚴(yán)格控制SPWM 的周期,這里的while 循環(huán)請(qǐng)用定時(shí)器來(lái)驅(qū)動(dòng)
}
四、三路精確相位差正弦信號(hào)發(fā)生器
對(duì)CPLD 改進(jìn)設(shè)計(jì),很容易實(shí)現(xiàn)多路PWM 輸出。
例如設(shè)計(jì)具有精確相位差的三相正弦信號(hào),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;// 寫(xiě)帶地址的寄存器
5'H11: daPWMs1 <= P0;// 寫(xiě)帶地址的寄存器
5'H12: daPWMs2 <= P0;// 寫(xiě)帶地址的寄存器
default:
begin
daPWMs0 <= daPWMs0;
daPWMs1 <= daPWMs1;
daPWMs2 <= daPWMs2;
end
endcase
end
always @(posedge clk) begin
daPWMc <= daPWMc+1; //PWM 調(diào)整精度1%
if(daPWMs0 < daPWMc) PWM[0] <= 0;//PWM 發(fā)生器
else PWM[0] <= 1;
if(daPWMs1 < daPWMc) PWM[1] <= 0;//PWM 發(fā)生器
else PWM[1] <= 1;
if(daPWMs2 < daPWMc) PWM[2] <= 0;//PWM 發(fā)生器
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 時(shí)鐘來(lái)自CPLD 內(nèi)部
LCELL 延遲電路振蕩器
endmodule
與之對(duì)應(yīng)的MCU 演示程序:
#include
#include
#define PWM0 XBYTE[0xfff0]
#define PWM1 XBYTE[0xfff1]
#define PWM2 XBYTE[0xfff2]
unsigned char code sine_dot[36]= //8 階,36 點(diǎn)正弦表
{
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;// 對(duì)36 取余數(shù)及0~35
b=(a+12)%36;// 較a 路滯后120 度相位
c=(a+24)%36;// 較a 路滯后240 度相位
PWM0 = sine_dot[a];
PWM1 = sine_dot[b];
PWM2 = sine_dot[c];
a++;
}
}
實(shí)際得到的三相正弦信號(hào)示波器截圖效果如圖7所示,只是雙蹤示波器同時(shí)只能看兩路信號(hào)。
圖7 具有精確相位差的三相正弦信號(hào)示波器截圖
五、結(jié)束語(yǔ)
今后,MCU+CPLD 結(jié)構(gòu)將是很多電子系統(tǒng)設(shè)計(jì)的一種基本架構(gòu),MCU 可以用程序?qū)崿F(xiàn)復(fù)雜智能的控制與檢測(cè),CPLD 又可以實(shí)現(xiàn)靈活多變的外圍擴(kuò)展電路設(shè)計(jì),尤其是可以用硬件實(shí)現(xiàn)特殊的MCU 無(wú)法實(shí)現(xiàn)的功能,彌補(bǔ)MCU 響應(yīng)速度慢影響實(shí)時(shí)性問(wèn)題,兩者互補(bǔ),完全實(shí)現(xiàn)硬件軟設(shè)計(jì),使得同一硬件平臺(tái)能夠通過(guò)軟件實(shí)現(xiàn)更多的功能。