利用雙通道示波器展示傳輸線行為的方法
2 直接數(shù)字合成
本文引用地址:http://cafeforensic.com/article/248900.htm為獲得穩(wěn)定的顯示,就必須產(chǎn)生準確的頻率。這里的“穩(wěn)定”表示節(jié)點的水平位置或者駐波圖案的最大或最小位置在屏幕上不移動。一種實現(xiàn)辦法,采用具有數(shù)控振蕩器(NCO)2的DDS。NCO采用一個16位計數(shù)器,稱之為相位累加器,來實現(xiàn)。FCLOCK(圖5)為一個固定的時鐘頻率遞增量,F(xiàn)cw為調(diào)制量或頻率控制量。FCLOCK遠遠高于波形頻率。
將相位累加器的高8位的值和正弦查找表(LUT)對應,然后將查找值發(fā)送至DAC。相位累加器中的值可認為對應的是一個圓上的某一個點;調(diào)制量定義為繞圓周的“步長”。調(diào)制量越大,繞圓周旋轉(zhuǎn)的越快,因此輸出的頻率也越高。產(chǎn)生的頻率由下式給出:
FOUT = FCW × FCLOCK/216
輸出頻率與FCW成正比。本例中,F(xiàn)CLOCK為31.25kHz。FCW值采用841、839和837,計算得到三個頻率為:
F1=841×31250/65536= 401.02Hz
F2=839×31250/65536= 400.06Hz
F3=837×31250/65536= 399.11Hz
這里的頻率表示采用保留兩位小數(shù),但實際上(F1 – F2和(F2 – F3)是完全相等的。頻率差精確到9位小數(shù)時為0.953674316Hz。
3 實現(xiàn)
本演示使用Maxim® MAX5715 4通道12位數(shù)/模轉(zhuǎn)換器(DAC)的三個通道來實現(xiàn),由Arduino® Uno板上的Atmel® AVR處理器驅(qū)動。Arduino是一個開放的軟硬件平臺,對于基于AVR系統(tǒng)開發(fā)環(huán)境,非常方便。Maxim DAC通過SPI(串行外設接口)很容易和Arduino相連,AVR硬件支持SPI接口,Arduino軟件庫自帶SPI驅(qū)動。運行Arduino 庫中的SPI程序初始化AVR SPI硬件。也提供現(xiàn)存的SPI數(shù)據(jù)傳輸?shù)某绦?,但速度太慢,未使用?/p>
三個相位累加器采用16的位計數(shù)器,計數(shù)器遞增是通過一個中斷程序來實現(xiàn),中斷程序由處理器中的一個定時器來觸發(fā)。每32µs (1/31.25kHz)中斷一次。利用LUT將兩個相位累加器值(生成F1和F3)轉(zhuǎn)換為正弦值并然后送給DAC的兩個通道。將第三個相位累加器(生成F2)的兩個最高有效位發(fā)送至第三個DAC通道,產(chǎn)生一個4節(jié)拍的示波器觸發(fā)信號。通過改變觸發(fā)電平,可選擇想要駐波的相位去進行開路或短路端接仿真。
Arduino SPI庫中的數(shù)據(jù)傳輸程序太慢,導致中斷程序的運行時間超過了中斷周期。因此,改用直接寫至AVR SPI硬件的代碼。
中斷程序代碼:
//******************************************************************
// Timer2 Interrupt Service at 31372.550 Hz = 32uSec
// this is the timebase REFCLOCK for the DDS generator
// FOUT = (M (REFCLK)) / (2 exp 32)
ISR(TIMER2_OVF_vect) {
// set the SS line low
PORTB &= (0xFF ^ 4);
// send in the address and value via SPI:
SPDR = CODEA;
// update phase accumulators while waiting
phaccu_a += tword_a;
phaccu_b += tword_b;
phaccu_c += tword_c;
while (!(SPSR & _BV(SPIF)))
;
// do the table lookup based on accum 'a' high-order byte
SPDR = pgm_read_byte_near(sine256 + highByte(phaccu_a));
while (!(SPSR & _BV(SPIF)))
;
SPDR = 0;
while (!(SPSR & _BV(SPIF)))
;
// set the SS line high
PORTB |= 4;
// set the sS line low for the second SPI transfer
PORTB &= (0xFF ^ 4);
// do the second SPI transfer
//SPDR = CODEB_LOADALL;
SPDR = CODEB;
while (!(SPSR & _BV(SPIF)))
;
// do table lookup based on accum 'b'
SPDR = pgm_read_byte_near(sine256 + highByte(phaccu_b));
while (!(SPSR & _BV(SPIF)))
;
SPDR = 0;
while (!(SPSR & _BV(SPIF)))
;
評論