void juchi() //鋸齒波函數(shù)
我們提供的服務(wù)有:成都網(wǎng)站設(shè)計、成都網(wǎng)站建設(shè)、微信公眾號開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認證、互助ssl等。為上千多家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的互助網(wǎng)站制作公司
{ uchar i;
for(i=0;i255;i++)
{DAC0832=i;
dump(10+p);} //延時實現(xiàn)頻率可調(diào),p是變量
i=0x00; }
void zhengxian()
{
for(i=0;i256;i++)//i沒有聲明 上面那個程序都有uchar i; uchar類型的最大值也只有255
{DAC0832=sin[i];//查表取值
dump(2+p);
}
i=0;
}
//最簡單的方法就是復(fù)制juchi這個函數(shù)
//把DAC0832=i;改成DAC832=sin[i];就能看到效果了
void zhengxian() //正弦波函數(shù)
{ uchar i;
for(i=0;i255;i++)
{DAC0832=sin[i];
dump(10+p);} //延時實現(xiàn)頻率可調(diào),p是變量
i=0x00; }
如圖9-58所示, 由運算放大器進行電流→電壓轉(zhuǎn)換,使用內(nèi)部反饋電阻。輸出電壓值VOUT和輸入數(shù)字量D的關(guān)系:
VOUT = - VREF ×D/256
D = 0~255, VOUT = 0 ~ - VREF ×255/256
VREF = -5V, VOUT =0~5×(255/256)V
VREF = +5V, VOUT = 0 ~ -5×(255/256)V 如果實際應(yīng)用系統(tǒng)中要求輸出模擬電壓為雙極性,則需要用轉(zhuǎn)換電路實現(xiàn)。如圖9-59所示。
其中 R2=R3=2R1
VOUT= 2×VREF×D/256 -VREF= (2D/256-1)VREF
D = 0, VOUT= -VREF;
D = 128, VOUT= 0;
D = 255, VOUT= (2×255/256-1)×VREF= (254/255)VREF
即:輸入數(shù)字為0~255時,輸出電壓在- VREF ~+ VREF之間變化。
1. 運算放大器
運算放大器有三個特點:
⑴開環(huán)放大倍數(shù)非常高,一般為幾千,甚至可高達10萬。在正常情況下,運算放大器所需要的輸入電壓非常小。
⑵輸入阻抗非常大。運算放大器工作時,輸入端相當于一個很小的電壓加在一個很大的輸入阻抗上,所需要的輸入電流也極小。
⑶輸出阻抗很小,所以,它的驅(qū)動能力非常大。
2.由電阻網(wǎng)絡(luò)和運算放大器構(gòu)成的D/A轉(zhuǎn)換器
利用運算放大器各輸入電流相加的原理,可以構(gòu)成如圖10.7所示的、由電阻網(wǎng)絡(luò)和運算放大器組成的、最簡單的4位D/A轉(zhuǎn)換器。圖中,V0是一個有足夠精度的標準電源。運算放大器輸入端的各支路對應(yīng)待轉(zhuǎn)換資料的D0,D1,…,Dn-1位。各輸入支路中的開關(guān)由對應(yīng)的數(shù)字元值控制,如果數(shù)字元為1,則對應(yīng)的開關(guān)閉合;如果數(shù)字為0,則對應(yīng)的開關(guān)斷開。各輸入支路中的電阻分別為R,2R,4R,…這些電阻稱為權(quán)電阻。
假設(shè),輸入端有4條支路。4條支路的開關(guān)從全部斷開到全部閉合,運算放大器可以得到16種不同的電流輸入。這就是說,通過電阻網(wǎng)絡(luò),可以把0000B~1111B轉(zhuǎn)換成大小不等的電流,從而可以在運算放大器的輸出端得到相應(yīng)大小不同的電壓。如果數(shù)字0000B每次增1,一直變化到1111B,那么,在輸出端就可得到一個0~V0電壓幅度的階梯波形。
3.采用T型電阻網(wǎng)絡(luò)的D/A轉(zhuǎn)換器
從圖10.7可以看出,在D/A轉(zhuǎn)換中采用獨立的權(quán)電阻網(wǎng)絡(luò),對于一個8位二進制數(shù)的D/A轉(zhuǎn)換器,就需要R,2R,4R,…,128R共8個不等的電阻,最大電阻阻值是最小電阻阻值的128倍,而且對這些電阻的精度要求比較高。如果這樣的話,從工藝上實現(xiàn)起來是很困難的。所以,n個如此獨立輸入支路的方案是不實用的。
在DAC電路結(jié)構(gòu)中,最簡單而實用的是采用T型電阻網(wǎng)絡(luò)來代替單一的權(quán)電阻網(wǎng)絡(luò),整個電阻網(wǎng)絡(luò)只需要R和2R兩種電阻。在集成電路中,由于所有的組件都做在同一芯片上,電阻的特性可以做得很相近,而且精度與誤差問題也可以得到解決。
圖10.8是采用T型電阻網(wǎng)絡(luò)的4位D/A轉(zhuǎn)換器。4位元待轉(zhuǎn)換資料分別控制4條支路中開關(guān)的倒向。在每一條支路中,如果(資料為0)開頭倒向左邊,支路中的電阻就接到地;如果(資料為1)開關(guān)倒向右邊,電阻就接到虛地。所以,不管開關(guān)倒向哪一邊,都可以認為是接“地”。不過,只有開關(guān)倒向右邊時,才能給運算放大器輸入端提供電流。
T型電阻網(wǎng)絡(luò)中,節(jié)點A的左邊為兩個2R的電阻并聯(lián),它們的等效電阻為R,節(jié)點B的左邊也是兩個2R的電阻并聯(lián),它們的等效電阻也是R,…,依次類推,最后在D點等效于一個數(shù)值為R的電阻接在參考電壓VREF上。這樣,就很容易算出,C點、B點、A點的電位分別為-VREF/2,-VREF/4,-VREF/8。
在清楚了電阻網(wǎng)絡(luò)的特點和各節(jié)點的電壓之后,再來分析一下各支路的電流值。開關(guān)S3,S2,S1,S0分別代表對應(yīng)的1位二進制數(shù)。任一資料位Di=1,表示開關(guān)Si倒向右邊;Di=0,表示開關(guān)Si倒向左邊,接虛地,無電流。當右邊第一條支路的開關(guān)S3倒向右邊時,運算放大器得到的輸入電流為-VREF/(2R),同理,開關(guān)S2,S1,S0倒向右邊時,輸入電流分別為-VREF/(4R),-VREF/(8R),-VREF/(16R)。
如果一個二進制數(shù)據(jù)為1111,運算放大器的輸入電流
I=-VREF/(2R)-VREF/(4R)-VREF/(8R)-VREF/(16R)
=-VREF/(2R)(20+2-1+2-2+2-3)
=-VREF/(24R)(23+22+21+20)
相應(yīng)的輸出電壓
V0=IR0=-VREFR0(24R)(23+22+21+20)
將資料推廣到n位,輸出模擬量與輸入數(shù)字量之間關(guān)系的一般表達式為:
V0=-VREFR0/(2nR)(Dn-12n-1+Dn-2 2n-2+…+D121+D020) (Di=1或0)
上式表明,輸出電壓V0除了和待轉(zhuǎn)換的二進制數(shù)成比例外,還和網(wǎng)絡(luò)電阻R、運算放大器反饋電阻R0、標準參考電壓VREF有關(guān)。
2. D/A轉(zhuǎn)換器性能參數(shù)
在實現(xiàn)D/A轉(zhuǎn)換時,主要涉及下面幾個性能參數(shù)。
⑴分辨率。分辨率是指最小輸出電壓(對應(yīng)于輸入數(shù)字量最低位增1所引起的輸出電壓增量)和最大輸出電壓(對應(yīng)于輸入數(shù)字量所有有效位全為1時的輸出電壓)之比,
例如,4位DAC的分辨率為1/(16-1)=1/15=6.67%(分辨率也常用百分比來表示)。8位DAC的分辨率為1/255=0.39%。顯然,位數(shù)越多,分辨率越高。
⑵轉(zhuǎn)換精度。如果不考慮D/A轉(zhuǎn)換的誤差,DAC轉(zhuǎn)換精度就是分辨率的大小,因此,要獲得高精度的D/A轉(zhuǎn)換結(jié)果,首先要選擇有足夠高分辨率的DAC。
D/A轉(zhuǎn)換精度分為絕對和相對轉(zhuǎn)換精度,一般是用誤差大小表示。DAC的轉(zhuǎn)換誤差包括零點誤差、漂移誤差、增益誤差、噪聲和線性誤差、微分線性誤差等綜合誤差。
絕對轉(zhuǎn)換精度是指滿刻度數(shù)字量輸入時,模擬量輸出接近理論值的程度。它和標準電源的精度、權(quán)電阻的精度有關(guān)。相對轉(zhuǎn)換精度指在滿刻度已經(jīng)校準的前提下,整個刻度范圍內(nèi),對應(yīng)任一模擬量的輸出與它的理論值之差。它反映了DAC的線性度。通常,相對轉(zhuǎn)換精度比絕對轉(zhuǎn)換精度更有實用性。
相對轉(zhuǎn)換精度一般用絕對轉(zhuǎn)換精度相對于滿量程輸出的百分數(shù)來表示,有時也用最低位(LSB)的幾分之幾表示。例如,設(shè)VFS為滿量程輸出電壓5V,n位DAC的相對轉(zhuǎn)換精度為±0.1%,則最大誤差為±0.1%VFS=±5mV;若相對轉(zhuǎn)換精度為±1/2LSB,LSB=1/2n,則最大相對誤差為±1/2n+1VFS。
⑶非線性誤差。D/A轉(zhuǎn)換器的非線性誤差定義為實際轉(zhuǎn)換特性曲線與理想特性曲線之間的最大偏差,并以該偏差相對于滿量程的百分數(shù)度量。轉(zhuǎn)換器電路設(shè)計一般要求非線性誤差不大于±1/2LSB。
⑷轉(zhuǎn)換速率/建立時間。轉(zhuǎn)換速率實際是由建立時間來反映的。建立時間是指數(shù)字量為滿刻度值(各位全為1)時,DAC的模擬輸出電壓達到某個規(guī)定值(比如,90%滿量程或±1/2LSB滿量程)時所需要的時間。
建立時間是D/A轉(zhuǎn)換速率快慢的一個重要參數(shù)。很顯然,建立時間越大,轉(zhuǎn)換速率越低。不同型號DAC的建立時間一般從幾個毫微秒到幾個微秒不等。若輸出形式是電流,DAC的建立時間是很短的;若輸出形式是電壓,DAC的建立時間主要是輸出運算放大器所需要的響應(yīng)時間。
10.3.3 DAC0832及接口電路
DAC0832是美國資料公司研制的8位雙緩沖器D/A轉(zhuǎn)換器。芯片內(nèi)帶有資料鎖存器,可與數(shù)據(jù)總線直接相連。電路有極好的溫度跟隨性,使用了COMS電流開關(guān)和控制邏輯而獲得低功耗、低輸出的泄漏電流誤差。芯片采用R-2RT型電阻網(wǎng)絡(luò),對參考電流進行分流完成D/A轉(zhuǎn)換。轉(zhuǎn)換結(jié)果以一組差動電流IOUT1和IOUT2輸出。
1.DAC0832的內(nèi)部結(jié)構(gòu)
DAC0832中有兩級鎖存器,第一級鎖存器稱為輸入寄存器,它的鎖存信號為ILE;第二級鎖存器稱為DAC寄存器,它的鎖存信號為傳輸控制信號 。因為有兩級鎖存器,DAC0832可以工作在雙緩沖器方式,即在輸出模擬信號的同時采集下一個數(shù)字量,這樣能有效地提高轉(zhuǎn)換速度。此外,兩級鎖存器還可以在多個D/A轉(zhuǎn)換器同時工作時,利用第二級鎖存信號來實現(xiàn)多個轉(zhuǎn)換器同步輸出。
ILE為高電平、WR1 和 CS為低電平時, LE1為高電平,輸入寄存器的輸出跟隨輸入而變化;此后,當WR1 由低變高時, LE1為低電平,資料被鎖存到輸入寄存器中,這時的輸入寄存器的輸出端不再跟隨輸入資料的變化而變化。對第二級鎖存器來說, WR2和XFER 同時為低電平時, LE2為高電平,DAC寄存器的輸出跟隨其輸入而變化;此后,當WR2 由低變高時, LE2變?yōu)榈碗娖?,將輸入寄存器的資料鎖存到DAC寄存器中。
2. DAC0832的引腳特性
DAC0832是20引腳的雙列直插式芯片。各引腳的特性如下:
CS——片選信號,和允許鎖存信號ILE組合來決定 是否起作用,低有效。
ILE——允許鎖存信號,高有效。
WR1——寫信號1,作為第一級鎖存信號,將輸入資料鎖存到輸入寄存器(此時, 必須和 、ILE同時有效),低有效。
WR2——寫信號2,將鎖存在輸入寄存器中的資料送到DAC寄存器中進行鎖存(此時,傳輸控制信號 必須有效)低有效。
XFER——傳輸控制信號,低有效。
DI7~DI0——8位數(shù)據(jù)輸入端。
IOUT1——模擬電流輸出端1。當DAC寄存器中全為1時,輸出電流最大,當DAC寄存器中全為0時,輸出電流為0。
IOUT2——模擬電流輸出端2。IOUT1+IOUT2=常數(shù)。
Rfb——反饋電阻引出端。DAC0832內(nèi)部已經(jīng)有反饋電阻,所以,RFB端可以直接接到外部運算放大器的輸出端。相當于將反饋電阻接在運算放大器的輸入端和輸出端之間。
VREF——參考電壓輸入端??山与妷悍秶鸀椤?0V。外部標準電壓通過VREF與T型電阻網(wǎng)絡(luò)相連。
VCC——芯片供電電壓端。范圍為+5V~+15V,最佳工作狀態(tài)是+15V。
AGND——模擬地,即模擬電路接地端。
DGND——數(shù)字地,即數(shù)字電路接地端。
3.DAC0832的工作方式
DAC0832進行D/A轉(zhuǎn)換,可以采用兩種方法對數(shù)據(jù)進行鎖存。
第一種方法是使輸入寄存器工作在鎖存狀態(tài),而DAC寄存器工作在直通狀態(tài)。具體地說,就是使 和 都為低電平,DAC寄存器的鎖存選通端得不到有效電平而直通;此外,使輸入寄存器的控制信號ILE處于高電平、 處于低電平,這樣,當 端來一個負脈沖時,就可以完成1次轉(zhuǎn)換。
第二種方法是使輸入寄存器工作在直通狀態(tài),而DAC寄存器工作在鎖存狀態(tài)。就是使 和 為低電平,ILE為高電平,這樣,輸入寄存器的鎖存選通信號處于無效狀態(tài)而直通;當WR2 和XFER 端輸入1個負脈沖時,使得DAC寄存器工作在鎖存狀態(tài),提供鎖存數(shù)據(jù)進行轉(zhuǎn)換。
根據(jù)上述對DAC0832的輸入寄存器和DAC寄存器不同的控制方法,DAC0832有如下3種工作方式:
⑴單緩沖方式。單緩沖方式是控制輸入寄存器和DAC寄存器同時接收資料,或者只用輸入寄存器而把DAC寄存器接成直通方式。此方式適用只有一路模擬量輸出或幾路模擬量異步輸出的情形。
⑵雙緩沖方式。雙緩沖方式是先使輸入寄存器接收資料,再控制輸入寄存器的輸出資料到DAC寄存器,即分兩次鎖存輸入資料。此方式適用于多個D/A轉(zhuǎn)換同步輸出的情節(jié)。
⑶直通方式。直通方式是資料不經(jīng)兩級鎖存器鎖存,即 CS*,XFER* ,WR1* ,WR2* 均接地,ILE接高電平。此方式適用于連續(xù)反饋控制線路和不帶微機的控制系統(tǒng),不過在使用時,必須通過另加I/O接口與CPU連接,以匹配CPU與D/A轉(zhuǎn)換。
4. DAC0832的應(yīng)用舉例
⑴DAC0832實現(xiàn)一次D/A轉(zhuǎn)換,可以采用下面程序段。設(shè)定要轉(zhuǎn)換的數(shù)據(jù)放在1000H單元中。
MOV BX,100H
MOV AL,[BX] ;取轉(zhuǎn)換資料
OUT DX,AL
⑵在實際應(yīng)用中,經(jīng)常需要用到一個線性增長的電壓去控制某一個檢測過程,或者作為掃描電壓去控制一個電子束的移動。執(zhí)行下面的程序段,利用D/A轉(zhuǎn)換器產(chǎn)生一個鋸齒波電壓,實現(xiàn)此類控制作用。
MOV DX,PORTA ;PORTA為D/A轉(zhuǎn)換器端口地址
MOV AL,OFFH ;置初值
ROTAT:INC AL
OUT DX,AL ;往D/A轉(zhuǎn)換器輸出資料
CALL DELP ;調(diào)用延遲子程序
JMP ROTAT
DELY: MOV CX, DATA ;置延遲常數(shù)DATA
DELY1: LOOP DELY1
RET
如果需要一個負向的鋸齒波,只要將指令I(lǐng)NC AL改成DEC AL就可以了。
⑶從兩個不相關(guān)的文件中輸出一批X-Y資料,驅(qū)動X-Y記錄儀,或者控制加工復(fù)雜零件的走刀(X軸)和進刀(Y軸)。這些在控制過程中是很有用的。下面程序驅(qū)動X-Y記錄儀的100點輸出,并用軟件驅(qū)動記錄儀的抬筆和放筆控制。
MOV SI, XDATA ;X軸資料指針→SI
MOV DI, YDATA ;Y軸資料指針→DI
MOV CX, 100
WE0: MOV AL,[SI]
OUT PORTX, AL ;往X軸的D/A轉(zhuǎn)換器輸出資料
MOV AL,[DI]
OUT PORTY,AL;往Y軸的D/A轉(zhuǎn)換器輸出資料
CALL DELY1 ;調(diào)延遲子程序1,等待筆移動
MOV AL,01H
OUT PORTM,AL;輸出升脈沖,控制筆放下
CALL DELY2 ;調(diào)延遲子程序2,等待完成
MOV AL,00H
OUT PORTM,AL;輸出降脈沖,控制筆抬起
CALL DELY2 ;調(diào)延遲子程序2,等待完成
INC SI
INC DI
LOOP WE0
HLT
DELY1:┇
RET
DELY2:┇
RET
XDATA DB…
YDATA DB…
(4).利用C語言編程:
#pragma db oe sb
#i ncludereg51.h
#i ncludeabsacc.h
#define DAC0832 XBYTE[0x7fff] /* 定義DAC0832端口地址 */
#define uchar unsigned char
void delay(uchar t) { /* 延時函數(shù) */
while(t--);
}
void saw(void) { /* 鋸齒波發(fā)生函數(shù) */
uchar i;
for (i=0;i255;i++) {
DAC0832=i;
}
}
void square(void) { /* 方波發(fā)生函數(shù) */
DAC0832=0x00;
delay(0x10);
DAC0832=0xff;
delay(0x10);
}
void main(void) {
uchar i,j;
i=j=0xff;
while(i--) {
saw(); /* 產(chǎn)生一段鋸齒波 */
}
while(j--) {
square(); /* 產(chǎn)生一段方波 */
}
}
#includereg52.h
#define uchar unsigned char
#define uint unsigned int
//#define Fosc 24000000/12000000 //12分頻后的頻率
#define DAdata P0//DA數(shù)據(jù)端口
sbit DA_S1= P2^0; // 控制DAC0832的8位輸入寄存器,僅當都為0時,可以輸出數(shù)據(jù)(處于直通狀態(tài)),否則,輸出將被鎖存
sbit DA_S2= P2^1; // 控制DAC0832的8位DAC寄存器,僅當都為0時,可以輸出數(shù)據(jù)(處于直通狀態(tài)),否則,輸出將被鎖存
sbit key= P3^2;
uchar wavecount; //'抽點'計數(shù)
uchar THtemp,TLtemp;//傳遞頻率的中間變量
//uint T_temp;
uchar judge=1; //在方波輸出函數(shù)中用于簡單判別作用
uchar waveform; //當其為0、1、2時,分別代表三種波
uchar code freq_unit[4]={10,50,200,10}; //三種波的頻率單位 sawtooth
uchar idata wavefreq[4]={1,1,1,1}; //給每種波定義一個數(shù)組單元,用于存放單位頻率的個數(shù)
uchar code lcd_hang1[]={"Sine Wave " "Triangle Wave " "Square Wave " "sawtooth Wave ""Select Wave: " "press No.1 key! "};
uchar idata lcd_hang2[16]={"f= Hz "};
/*uchar code wave_freq_adjust[]={ //頻率調(diào)整中間值
0xff,0xb8,0x76,0x56,0x43,0x37,0x2e,0x26,0x20,0x1c, //正弦波頻率調(diào)整中間值
0xff,0x8e,0x5a,0x41,0x32,0x28,0x20,0x1b,0x17,0x0e,//三角波頻率調(diào)整中間值
0xff,0x8e,0x5a,0x41,0x32,0x28,0x20,0x1b,0x17,0x0e};
uint code wave_freq_adjust[]={ //頻率調(diào)整中間值
380,184,118,86,67,55,46,28,38,32,
295,142, 90,65,50,40,32,27,23,14,
295,142, 90,65,50,40,32,27,23,14}; */
/*uchar code waveTH[]={
0xfc,0xfe,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xfc,0xfe,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
uchar code waveTL[]={
0xf2,0x78,0xfb,0x3c,0x63,0x7d,0x8f,0x9d,0xa8,0xb1,
0x17,0x0b,0xb2,0x05,0x37,0x58,0x70,0x82,0x90,0x9b,
0x4d,0xa7,0xc4,0xd3,0xdc,0xe2,0xe6,0xea,0xec,0xee};*/
/***********這兩組數(shù)組很重要,需要根據(jù)波形來調(diào)試,選擇合適的值,使輸出波形達到頻率要求************/
uchar code waveTH[]={
0xfd,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xfd,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xec,0xf6,0xf9,0xfb,0xfc,0xfc,0xfd,0xfd,0xfd,0xfe};
uchar code waveTL[]={
0x06,0x8a,0x10,0x4e,0x78,0x93,0xa8,0xb3,0xbe,0xc6, //正弦波頻率調(diào)整中間值
0xac,0xde,0x48,0x7a,0x99,0xaf,0xbb,0xc8,0xd0,0xde,//三角波頻率調(diào)整中間值
0x88,0x50,0x90,0x32,0x34,0xbe,0x4a,0xa3,0xe5,0x2c};
/*************************************************************************************************/
uchar code triangle_tab[]={ //每隔數(shù)字8,采取一次
0x00,0x08,0x10,0x18,0x20,0x28,0x30,0x38,0x40,0x48,0x50,0x58,0x60,0x68,0x70,0x78,
0x80,0x88,0x90,0x98,0xa0,0xa8,0xb0,0xb8,0xc0,0xc8,0xd0,0xd8,0xe0,0xe8,0xf0,0xf8,0xff,
0xf8,0xf0,0xe8,0xe0,0xd8,0xd0,0xc8,0xc0,0xb8,0xb0,0xa8,0xa0,0x98,0x90,0x88,0x80,
0x78,0x70,0x68,0x60,0x58,0x50,0x48,0x40,0x38,0x30,0x28,0x20,0x18,0x10,0x08,0x00};
uchar code sine_tab[256]={
//輸出電壓從0到最大值(正弦波1/4部分)
0x80,0x83,0x86,0x89,0x8d,0x90,0x93,0x96,0x99,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,0xae,0xb1,0xb4,0xb7,0xba,0xbc,
0xbf,0xc2,0xc5,0xc7,0xca,0xcc,0xcf,0xd1,0xd4,0xd6,0xd8,0xda,0xdd,0xdf,0xe1,0xe3,0xe5,0xe7,0xe9,0xea,0xec,
0xee,0xef,0xf1,0xf2,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfd,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,
//輸出電壓從最大值到0(正弦波1/4部分)
0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfd,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf2,0xf1,0xef,
0xee,0xec,0xea,0xe9,0xe7,0xe5,0xe3,0xe1,0xde,0xdd,0xda,0xd8,0xd6,0xd4,0xd1,0xcf,0xcc,0xca,0xc7,0xc5,0xc2,
0xbf,0xbc,0xba,0xb7,0xb4,0xb1,0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c,0x99 ,0x96,0x93,0x90,0x8d,0x89,0x86,0x83,0x80,
//輸出電壓從0到最小值(正弦波1/4部分)
0x80,0x7c,0x79,0x76,0x72,0x6f,0x6c,0x69,0x66,0x63,0x60,0x5d,0x5a,0x57,0x55,0x51,0x4e,0x4c,0x48,0x45,0x43,
0x40,0x3d,0x3a,0x38,0x35,0x33,0x30,0x2e,0x2b,0x29,0x27,0x25,0x22,0x20,0x1e,0x1c,0x1a,0x18,0x16 ,0x15,0x13,
0x11,0x10,0x0e,0x0d,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
//輸出電壓從最小值到0(正弦波1/4部分)
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02 ,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0d,0x0e,0x10,
0x11,0x13,0x15 ,0x16,0x18,0x1a,0x1c,0x1e,0x20,0x22,0x25,0x27,0x29,0x2b,0x2e,0x30,0x33,0x35,0x38,0x3a,0x3d,
0x40,0x43,0x45,0x48,0x4c,0x4e,0x51,0x55,0x57,0x5a,0x5d,0x60,0x63,0x66 ,0x69,0x6c,0x6f,0x72,0x76,0x79,0x7c,0x80};
uchar code sawtooth_tab[]={
0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e,0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e,0x20,0x22,0x24,0x26,0x28,0x2a,0x2c,0x2e,
0x30,0x32,0x34,0x36,0x38,0x3a,0x3c,0x3e,0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x4e,0x50,0x52,0x54,0x56,0x58,0x5a,0x5c,0x5e,
0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6e,0x70,0x72,0x74,0x76,0x78,0x7a,0x7c,0x7e,0x80,0x82,0x84,0x86,0x88,0x8a,0x8c,0x8e};
//0x90,0x92,0x94,0x96,0x98,0x9a,0x9c,0x9e,0xa0,0xa2,0xa4,0xa6,0xa8,0xaa,0xac,0xae,0xb0,0xb2,0xb4,0xb6,0xb8,0xba,0xbc,0xbe,
//0xc0,0xc2,0xc4,0xc6,0xc8,0xca,0xcc,0xce,0xd0,0xd2,0xd4,0xd6,0xd8,0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xee};
void delay(uchar z)
{
uint x,y;
for(x=z;x0;x--)
for(y=110;y0;y--);
}
void triangle_out()//三角波輸出
{
DAdata=triangle_tab[wavecount++];
if(wavecount64) wavecount=0;
DA_S1=0; //打開8位輸入寄存器
DA_S1=1; //關(guān)閉8位輸入寄存器
}
void sine_out() //正弦波輸出
{
DAdata=sine_tab[wavecount++];
DA_S1=0; //打開8位輸入寄存器
DA_S1=1; //關(guān)閉8位輸入寄存器
}
void square_out() //方波輸出
{
judge=~judge;
if(judge==1) DAdata=0xff;
else DAdata=0x00;
DA_S1=0; //打開8位輸入寄存器
DA_S1=1; //關(guān)閉8位輸入寄存器
}
void sawtooth_out() //鋸齒波輸出
{
DAdata=sawtooth_tab[wavecount++];
if(wavecount71) wavecount=0;
DA_S1=0; //打開8位輸入寄存器
DA_S1=1; //關(guān)閉8位輸入寄存器
}
/************1602液晶的相關(guān)函數(shù)*************/
#define lcd_ports P1
sbit rs=P2^2;
sbit rw=P2^3;
sbit lcden=P2^4;
void write_com(uchar com)
{
rs=0;//置零,表示寫指令
lcden=0;
lcd_ports=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_date(uchar date)
{
rs=1;//置1,表示寫數(shù)據(jù)(在指令所指的地方寫數(shù)據(jù))
lcden=0;
lcd_ports=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void disp_lcd(uchar addr,uchar *temp1)
{
uchar num;
write_com(addr);
delay(1); //延時一會兒???
for(num=0;num16;num++)
{
write_date(temp1[num]);//或者這樣寫write_date(*(temp1+num));
delay(1);
}
}
void init_lcd()
{
//uchar num;
lcden=0; //可有可無???
rw=0; //初始化一定要設(shè)置為零,表示寫數(shù)據(jù)
write_com(0x38); //使液晶顯示點陣,為下面做準備
write_com(0x0c); //初始設(shè)置
write_com(0x06); //初始設(shè)置
write_com(0x01); //清零
write_com(0x80); //使指針指向第一行第一格
disp_lcd(0x80,lcd_hang1[4*16]); //在第一行顯示
disp_lcd(0xc0,lcd_hang1[5*16]); //在第二行顯示
/*for(num=0;num16;num++)
{
write_date(table[num]);
delay(5);
}
write_com(0x80+0x40); //給指針重新賦值,使之指向第二行第一格
for(num=0;num16;num++)
{
write_date(table1[num]);
delay(5);
} */
/*TMOD=0x01; //選用定時方式1
TH0=(65536-50000)/256; //賦初值
TL0=(65536-50000)%256;//
EA=1;//開總中斷
ET0=1; //開定時器中斷
TR0=1; //啟動定時器*/
}
/********************1602液晶函數(shù)聲明結(jié)束*********************/
void main()
{
uchar i=0;
DA_S2=0; //使DAC寄存器處于直通狀態(tài)
DAdata=0;
DA_S1=1; //關(guān)閉8位輸入寄存器
init_lcd();
waveform=0;
TMOD=0x01; //設(shè)置定時器0為16位工作方式
IT0=1; //設(shè)置外部中斷0為下降沿觸發(fā)
ET0=1; //開定時器中斷
EX0=1;
EA=1;
while(1)
{
//DAout(0xff); //可輸出TTL波形
//DAout(0x80);
//T_temp=32;
}
}
void timer0() interrupt 1
{
TH0=THtemp;
TL0=TLtemp;
if(waveform==0) sine_out();
else if(waveform==1) triangle_out();
else if(waveform==2) square_out();
else if(waveform==3) sawtooth_out(); //tian jian
}
void key_int0() interrupt 0
{
uchar keytemp;
uint total_freq; //總頻率
EA=0; TR0=0; //關(guān)總中斷與定時器
delay(5); //延時夠嗎???
if(key==0) //確實有按鍵按下而引發(fā)中斷
{
keytemp=P30xf0; //獲取P3口高四位的值
switch(keytemp)
{
case 0xe0://選擇波形
waveform++;
if(waveform3) waveform=0; //jiang 2 gai wei 3
break;
case 0xd0: //頻率按規(guī)定單位依次增加
wavefreq[waveform]++;
if(wavefreq[waveform]10) wavefreq[waveform]=1; // /*這邊要用“10”,因為它比“=11”可靠
break; // 性更高,使加數(shù)有個上限,不會一直加下去*/
case 0xb0: //頻率按規(guī)定單位依次衰減
wavefreq[waveform]--;
if(wavefreq[waveform]1) wavefreq[waveform]=10; //這邊要用“1”,因為它比“=0”可靠性更高
break;
case 0x70: //TTL輸出
DA_S2=1; //使DAC寄存器關(guān)閉
break;
}
THtemp=waveTH[waveform*10+(wavefreq[waveform]-1)]; //方括號中選取第幾個數(shù)后,并把該值賦給T_temp
TLtemp=waveTL[waveform*10+(wavefreq[waveform]-1)];
total_freq= wavefreq[waveform] * freq_unit[waveform]; //求輸出頻率(個數(shù)*單位)
lcd_hang2[5]=total_freq%10+0x30; //在液晶中顯示個位,(0x30 在液晶顯示中表示數(shù)字0)
total_freq/=10; lcd_hang2[4]=total_freq%10+0x30; //在液晶中顯示時十位
total_freq/=10; lcd_hang2[3]=total_freq%10+0x30; //在液晶中顯示時百位
total_freq/=10; lcd_hang2[2]=total_freq%10+0x30; //在液晶中顯示時千位
disp_lcd(0x80,lcd_hang1[waveform*16]); //在第一行顯示
disp_lcd(0xc0,lcd_hang2); //在第二行顯示
}
wavecount=0; //'抽點'計數(shù)清零
while(!key);
EA=1; TR0=1; //開啟總中斷與定時器
/**************************************/
/* 信號發(fā)生器 (正弦波,方波,三角波) */
/*************************************/
#includereg52.h
#include intrins.h
#define uchar unsigned char
#define uint unsigned int
sbit cs=P2^0; //tlc5615片選端口
sbit clk=P2^1; //tlc5615時鐘線
sbit din=P2^2; //tlc5615傳輸端口
sbit key1=P1^0;
sbit key2=P1^1; //按鍵的單片機接口
uchar keydat;
uchar flag; //波形發(fā)生終止信號的標志位 一旦被置零立馬停止發(fā)信號
uchar flagsqu; //方波高低電平控制為(運用定時器1中斷控制)
uchar m,num;
uchar dat=0xff;
uchar code tosin[141]={ //正弦波的編碼
0x00,0x01,0x02,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
0x09,0x0a,0x0b,0x0d,0x0e,0x10,0x11,0x13,0x15,0x16,
0x18,0x1a,0x1c,0x1e,0x20,0x22,0x25,0x27,0x29,0x2b,
0x2e,0x30,0x33,0x35,0x38,0x3a,0x3d,0x40,0x43,0x45,
0x48,0x4c,0x4e,0x51,0x55,0x57,0x5a,0x5d,0x60,0x63,
0x66,0x69,0x6c,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,
0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7e,
0x7f,0x80,0x7f,0x7e,0x7e,0x7d,0x7c,0x7b,0x7a,0x79,
0x78,0x77,0x76,0x75,0x74,0x73,0x72,0x6f,0x6c,0x69,
0x66,0x63,0x60,0x5d,0x5a,0x57,0x55,0x51,0x4e,0x4c,
0x48,0x45,0x43,0x40,0x3d,0x3a,0x38,0x35,0x33,0x30,
0x2e,0x2b,0x29,0x27,0x25,0x22,0x20,0x1e,0x1c,0x1a,
0x18,0x16,0x15,0x13,0x11,0x10,0x0e,0x0d,0x0b,0x0a,
0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x02,0x01,
0x00};
void delay(uchar z) //延時函數(shù)
{
uchar x,y;
for(x=0;x110;x++)
for(y=z;y0;y--);
}
void prepare() //tlc5615的初始化
{
cs=1;
din=1;
clk=0;
cs=0; //cs的上升沿和下降沿必須在clk為低時進?
}
/* 用中斷來產(chǎn)生方波
void Squtranslator()
{
TR1=1; //啟動定時器1 控制高低電平的持續(xù)時間 占空比
do{
do{
_wave=0;
}while((!flagsqu) flag==1);//如果一旦終止信號的
//產(chǎn)生可以立馬退出循環(huán)
flagsqu=0;
do{
_wave=1;
}while((!flagsqu) flag==1);
flagsqu=0;
}while(flag);
flag=1;
TR1=0;
}
*/
void Squtranslator() //方波函數(shù)
{
uchar j;
uchar dat1=0x7f;
while(flag)
{
do{
prepare();
dat=dat1;
for(j=0;j12;j++)
{
din=(bit)(dat7); //將數(shù)據(jù)的最高位賦給din
clk=1;
dat=dat1; //一位位的傳輸
clk=0;
}
cs=1; //cs的上升沿和下降沿必須在clk為低時進行
delay(200); //使高低電平持續(xù)一段時間
if(dat1==0)
dat1=0x7f; //完成了0和0x7f之間的替換
else
dat1=0;
}while(flag);
}
}
void Tratranslator() //鋸齒波的發(fā)生函數(shù)
{
uchar j;
uchar dat1=0x7f;
while(flag)
{
do{
prepare();
dat=dat1;
for(j=0;j12;j++)
{
din=(bit)(dat7); //將數(shù)據(jù)的最高位賦給din
clk=1;
dat=dat1; //一位位的傳輸
clk=0;
}
cs=1; //cs的上升沿和下降沿必須在clk為低時進行
delay(2); //稍加延時
dat1--;
}while(flag dat1); //一旦有終止信號就可以停止
do{
prepare();
dat=dat1;
for(j=0;j12;j++)
{
din=(bit)(dat7); //將數(shù)據(jù)的最高位賦給din
clk=1;
dat=dat1; //一位位的傳輸
clk=0;
}
cs=1; //cs的上升沿和下降沿必須在clk為低時進行
delay(2); //稍加延時
dat1++;
}while(flag (!(dat1==0x7f)));
}
}
void Sintranslator(uchar wave[],uchar num )//正弦波的轉(zhuǎn)換函數(shù)
{
uchar i,j;
uchar dat1;
do{
for(i=0;inum;i++)
{
prepare();
dat1=wave[i]; //打開片選 開始工作
for(j=0;j12;j++)
{
din=(bit)(dat17); //將數(shù)據(jù)的最高位賦給din
clk=1;
dat1=dat11; //一位位的傳輸
clk=0;
if(flag==0)break;
}
cs=1; //cs的上升沿和下降沿必須在clk為低時進行
delay(1); //稍加延時
if(flag==0)break;
}
}while(flag); //等待控制鍵的暫停
}
void keyscan() //切換功能按鍵返回鍵值函數(shù)
{
uchar i;
for(i=0;i4;i++)
{
if(key1==0)
{
delay(10);
if(key1==0)
{
keydat++;
do{}while(!key1); //松手檢測
if(keydat==4)keydat=1;//加滿回零處理
}
}
}
}
void keycountrl() //切斷輸出控制函數(shù)
{
if(key2==0)
{
delay(10);
if(key2==0)
{
flag=0;
do{}while(!key2); //松手檢測
}
}
}
void main ()
{
uchar temp;
TMOD=0x01; //確定定時器的工作方式
TH0=(65536-50000)/256; //給定時器0賦予初值
TL0=(65536-50000)%256;
EA=1; //開總中斷
ET0=1; //開啟定時器0中斷
TR0=1;
while(1)
{
do{
switch(keydat)
{
case
網(wǎng)站標題:c語言鋸齒波發(fā)生函數(shù) 函數(shù)發(fā)生器鋸齒波
本文鏈接:http://www.rwnh.cn/article18/doohidp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供營銷型網(wǎng)站建設(shè)、網(wǎng)站營銷、標簽優(yōu)化、App開發(fā)、外貿(mào)建站、定制網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)