51單片機使用八位重裝定時器實作PWM輸出同時實作DAC轉換
??最近想要做一個數控電源,打算使用51單片機實作電壓和電流的倍訓,但是手頭上的51單片機為STC89C51系列的單片機,沒有ADC采樣功能,同時這款單片機也不具備可編程輸出的PWM功能,
??經過思考對于ADC采樣可以使用外擴芯片XPT2046,不僅廉價而且可以實作4路的ADC采樣通道,支持SPI通訊使用起來比較方便,對于PWM輸出,51單片機雖然可以使用定時器中斷來實作較精準的PWM輸出,但是在輸出高頻的PWM信號時(需要實作的開關頻率為65KHZ-100KHZ),其占空比解析度非常小,不能滿足要求,然后又想到可以使用51單片機產生低頻的PWM信號,然后經過有源低通濾波器實作DAC輸出模擬電壓,再經高頻鋸齒波發生器和電壓比較器實作高頻PWM輸出,高頻鋸齒波發生器使用手頭上現有的NE555芯片實作,電壓比較器可以使用LM393,有源低通濾波器也使用手頭現有的LM358實作,
??可能有人說我這么做是多此一舉,使用帶ADC和PWM輸出的單片機或者DSP芯片問題就沒有這么復雜了,考慮到我手頭現有的材料以及通過思考去解決一些實際問題想必更有識訓,
一、使用八位重裝定時器實作PWM輸出
??STC89C51單片機具有兩個16位的定時/計數器,每個定時器擁有八位自動重裝載定時功能,采用八位自動重裝載定時功能可以免去在中斷函式內的手動定時初值裝載,實作更精準的PWM輸出,
(1)實作思路
??下圖為采用兩個定時器實作PWM輸出的基本原理圖,定時器T1的定時周期控制PWM的周期,定時器T0的定時周期控制PWM的占空比,定時器T1的中斷函式始終將IO拉高,定時器T0的中斷函式始終將IO拉低,兩個定時器的中斷函式交替執行就可以實作較為精準的PWM輸出,這里需要注意的是定時器T0在達到一個PWM周期的高電平的延時時間后,會溢位進入中斷拉低對應IO,這時還要在定時器T0的中斷中暫停定時器T0,等到定時器T1進入中斷再開啟T0,

(2)程式
程式實作1:
#include"reg52.h"
sbit PWM0=P0^0;
unsigned char duty_high=(256-128);//這里占空比為50%
void main()
{
PWM0=1;//初始為高電平
TMOD=0x22; //定時器0和定時器1,都為作業方式2,定時器0和1僅用TR1打開啟動,
TH0=duty_high;//定時器0調節占空比計時高電平時間然后進入中斷拉低PWM0
TL0=duty_high;
TH1=0x00; //定時器1產生周期信號,定時周期為256us
TL1=0x00;
ET0=1;//打開定時器0中斷允許
ET1=1;//打開定時器1中斷允許
EA=1;//打開總中斷
TR1=1;//打開定時器1
TR0=1;//打開定時器0
while(1)
{
}
}
void Timer0() interrupt 1
{
TR0=0;//停止定時器T0
PWM0=0;//拉低IO口
}
void Timer1() interrupt 3
{
TR0=1; //開啟定時器T0
PWM0=1;//拉高IO口
}
??考慮到在中斷中關斷T0和開啟T0還是會造成最少1us的延時輸出,想到采用第二種方法來實作定時器T0的自動關斷和起動,原理如下,下圖為定時器的作業方式控制暫存器,GATE為門控位,當GATE置一時定時器的起動不僅需要TR0/1的控制還要求外部中斷引腳INT0/1為高電平,


下圖所示當把外部中斷0引腳和PWM0輸出引腳連接,同時由于P0口內部沒有上拉電阻,所以加一個10K的上拉電阻,這樣當定時器T0產生中斷拉低PWM0,同時INT0口也被拉低(INT0初始化為高電平),由于門控位GATE的作用定時器T0自動關斷,而當定時器T1產生中斷拉高PWM0,同時INT0恢復高電平,定時器T0自動打開開始計時,

程式實作2:
#include"reg52.h"
sbit PWM0=P0^0;
unsigned char duty_high=(256-128);//占空比50%
void main()
{
PWM0=1;//初始為高電平
PWM1=1;
TMOD=0x2a;//定時器0和定時器1,都為作業方式2,定時器0的起動受INTO和TR0影響,定時器1僅用TR1打開啟動,
TH0=duty_high;//定時器0調節占空比計時高電平時間然后進入中斷拉低PWM0
TL0=duty_high;
TH1=0x00; //定時器1產生周期信號,定時周期為256us
TL1=0x00;
ET0=1;//打開定時器0中斷允許
ET1=1;//打開定時器1中斷允許
EA=1;//打開總中斷
TR1=1;//打開定時器1
TR0=1;//打開定時器0
while(1)
{
}
}
void Timer0() interrupt 1
{
PWM0=0;
}
void Timer1() interrupt 3
{
PWM0=1;
}
使用方式2實作占空比為5%(13/256)

使用方式2實作占空比為95%(243/256)

經過仿真測驗在占空比為5%-95%時的PWM波形輸出較為精準,
二、利用產生的PWM輸出信號實作8位DAC轉換
??上面已經實作了較為精準的PWM波形輸出,將PWM波形經過有源低通濾波即可實作DAC轉換,參考這篇文章:怎樣利用PWM實作DAC電路設計
??在這篇文章中使用了六階巴特沃斯有源低通濾波器,這里因為PWM輸出波形頻率比文章中要高且只需要實作8位DAC,所以只采用三階巴特沃斯有源低通濾波器,當把PWM周期固定為256us,可實作8位DAC,最小解析度為1/256,這里因為采用LM358實作有源低通濾波,其不是軌到軌輸出的運放,采用5V供電的話并不能實作滿量程輸出,所以考慮采用電阻分壓來實作高電平為3V的PWM輸出,然后采用一路運放實作阻抗的匹配實作低阻輸出,然后連接后級的三階巴特沃斯有源低通濾波器,同時需要注意的是圖中使用20K和30K電阻想要實作高電平為3V的分壓,但實際上P0.0口也連接P3.2口,P3.2口內部有較大的上拉電阻,所以實際的分壓電阻要根據測量進行修改,

測驗:
unsigned char duty_high=(256+1-(Uq*256.0/3-0.5));//期望電壓Uq,-0.5的目的是四舍五入,256加1的目的是補償

??經過測驗在0.145V-2.9V的輸出范圍內其精度能夠接受,理論上8位DAC的精度為3*1/256=0.0117V,這里對比下誤差雖然不均勻但在精度要求不高的場合還是闊以的,當然這里僅僅是protues的仿真結果,實際做出來的誤差還有待考究,
??另外后來思考了一下,如果將51單片機模擬的DAC用于電壓或者電流倍訓的調制波,其調制頻率倒是有點低,以8位DAC為例,PWM的周期為256us,頻率就是3.9KHZ,直觀考慮DAC建立輸出最少需要一個周期,但是接下來還要完成比例和離散積分的運算,這樣算下來就不只一個周期,假如完成一次比例和離散積分的運算和占空比更新值的裝載需要一個DAC轉換周期,那么調節頻率就為3.9KHZ/2=1.95KHZ,如果MOSFET管的開關頻率做到65KHZ-100KHZ,1.95KHZ的調節頻率顯然是很低了,可以考慮降低DAC的解析度采用7位的DAC,這樣一個DAC轉換周期為7.8KHZ,假如一個調節周期仍然為兩個DAC轉換周期,這樣調節頻率為3.9KHZ,而DAC精度降低到了0.0234V,總的來說調節頻率還是比較低,只能考慮采用2倍頻模式或者更換更高頻率的晶振,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/413990.html
標籤:其他
上一篇:電氣PLC控制技術
