|
基于AT89S52單片機的毫歐表設(shè)計是采用伏安法測量電阻。采用TLC5615數(shù)模轉(zhuǎn)換芯片和LM358運算放大器及三極管TIP41構(gòu)成的壓控恒流源提拱恒定的電流。測量電阻時可選擇的電流分別為1mA,10mA,100mA。測量電阻的量程分別為40.00Ω、4000mΩ、400.0mΩ。測量的電壓信號通過LM358運算放器放大100倍后經(jīng)過TLC1549模數(shù)芯片傳入單片機進行計算處理并在數(shù)碼管上輸出電阻值! 關(guān)鍵字:毫歐表 壓控恒流源 目 錄: 一.總體方案設(shè)計:. 4 二.方案選擇:. 5 2.1.1 方案一 比較法測電阻:. 5 2.1.2 方案二 替代法測電阻:. 5 2.1.3 方案三 直流電橋測電阻. 5 2.1.4 方案四 伏安法測電阻. 6 2.2 壓控恒流源方案:. 6 2.2.1 方案一. 6 2.2.2 方案二. 6 2.2.3 方案三. 6 三.單元模塊設(shè)計:. 7 3.1 數(shù)控恒流源. 7 3.2 電壓放大模塊設(shè)計. 8 3.3 AD轉(zhuǎn)換與單片機處理. 9 3.4 DA轉(zhuǎn)換. 9 3.5 按鍵的輸入及數(shù)碼管的顯示輸出. 9 四.軟件設(shè)計. 11 4.1 主程序流程圖. 11 5.1 系統(tǒng)實現(xiàn)的功能,. 12 5.2 測量電阻方法:. 12 5.3 實際測試結(jié)果. 13 5.4 對測理結(jié)果的分析:. 15 六.設(shè)計總結(jié). 16 七.參考文獻. 17 八.附:. 18 8.1 電路仿真原理圖. 18 9.2 程序: 19
一.總體方案設(shè)計: 采用伏安法測電阻,通以恒定的電流,測量電阻上的電壓。因為U=R×I 由于電阻為毫歐,如果電流為毫安的話,則所得的電壓值很小,難以通過ADC識別出來。可以采用大電流的方法和把電壓信號放大的方法來使ADC芯片識別出來并由通過單片機計算得出電阻值。采用大電流的話,由于很多小電阻無法承受較大的電流,通過電阻的電流較大時,產(chǎn)生的熱量也多,會帶來較大的誤差。所以采用把電壓信號放大的方法,把微小的電壓信號放大后經(jīng)過AD轉(zhuǎn)換,把信號送入單片機,然后由單片機計算并顯示出電阻值。
|
| 測量范圍 | 測量電流 | 最大輸出電壓 | 電壓放大100倍 |
| 40.00Ω | 1mA | 40mV | 4V |
| 4000mΩ | 10 mA | 40mV | 4V |
| 400.0mΩ | 100 mA | 40mV | 4V |
上圖為測試電阻的范圍及測量時的電流: 下載本文所涉及到的protel格式電路圖:相關(guān)的ic資料,相關(guān)源程序!
二.方案選擇: 2.1電阻測量方案 2.1.1 方案一 比較法測電阻:
| | | |
| |
| | |
|
在乙圖中,K1閉合,K2斷開測得U1;K1斷開,K2閉合測得U2,使用條件:在乙圖中應(yīng)保證AB間電壓恒定。上圖中的比較法測量電阻值的阻值非常小時,電阻R0難以選取。并且要用電壓表測量兩處電阻的電壓。其中的導(dǎo)體接觸間的電阻也會對測量結(jié)果造成一定的誤差,并且對電壓表的要求高。沒有采用此方案。 2.1.2 方案二 替代法測電阻: 步驟:①K1打開,K2接1,調(diào)節(jié)R1為最大,電阻箱R0為最大。②閉合K1。調(diào)節(jié)R1使、指針指在2/3處,讀數(shù)。③K2接2,保持R1不動,調(diào)節(jié)R-0,使、讀數(shù)不變。④RX=電阻箱讀數(shù)。條件:被測量的部份電路電流或電壓不變。上圖但不適合于測量小電阻。因為電阻箱的阻值一般都較大。測量的電阻精度低。 2.1.3 方案三 直流電橋測電阻 直流電橋又分直流單電橋和直流雙電橋。采用上面的兩種方法時要用很多操作需要手動操作,并且對元件選取要求高,是通過數(shù)字電位器來改變需要的電阻參數(shù),雖然可以達到數(shù)控的目的,但數(shù)字電位器的每一級步進電阻比較大,調(diào)節(jié)困難,需要采用數(shù)控電阻,用單片機處理計算雜復(fù)并且測量時操作不方便。 2.1.4 方案 四 伏安法測電阻 采用伏安法測量電阻時,恒流源電路產(chǎn)生恒定的電流源通過被測電阻Rx,只需要測量出Rx上的電壓大小,然后用Rx=U / I 即可算出電阻的阻值大小。方便單片機進行處理。實際操作起來相對也比較簡單。方案四,操作簡單,計算方便。精度比方案一和方案二高,但操作和計算比方安三更簡單和方案。所以采用方案四伏安法測電阻。 2.2 壓控恒流源方案: 2.2.1 方案一 I=U/(R1+R2),若R1>>R2,則電流I約為I=U/R1; 可以采用一個恒定的電壓,然后除以一個大電阻,測試時由時所測的電阻很小,基本上可以看作電流是恒定的。但這種方案測量的電阻阻值越大,電流變化較大,電流精度不高。 2.2.2 方案二 采用恒流二極管或者恒流三極管,精度比較高,但這種電路能實現(xiàn)的恒流范圍很小,只能達到十幾毫安,不能達到題目的要求。 2.2.3 方案三 壓控恒流源,通過改變恒流源的外圍電壓,利用電壓的大小來控制輸出電流的大小。電壓控制電路采用數(shù)控的方式,利用單片機送出數(shù)字量,經(jīng)過D/A轉(zhuǎn)換轉(zhuǎn)變成模擬信號,再送到運算放大器和大功率三極管進行放大輸出電流。該方案通過軟件方法實現(xiàn)輸出電流穩(wěn)定,易于功能的實現(xiàn),便于操作,故選擇此方案。原理圖如下面的數(shù)控恒流源中的原理圖。 三.單元模塊設(shè)計: 3.1 數(shù)控恒流源 數(shù)控恒流源為電阻測量提供恒定的電流。單片機由測量所需的電流而控制輸出恒定電流的大小。 實際電路中采用的三極管為TIP41,三極管本身在這里不具備控制電流大小的作用,但是起到驅(qū)動和擴流的作用。前面是一個電壓跟隨,后面一個負(fù)反饋。 R9上的電壓為輸入的電壓Vin。 理論計算 I1=VR1/R1=(Vi-V+)/R1 ; I2=VR2/R2=(V+-Va)/R2 ; 因為I+=0,得I1 = I2 所以Va=(V+-Vi)R2/R1+V+; I3=VR3/R3=V-/R1 ;I4=VR4/R4=(VO-V-)/R4 ; 因為I-=0,得I3 = I4 所以VO= V- (R3/R4+1); 從而可得R5上電壓為UR5=VO - Va =(R4/R3)×V- - (R2/R1)×V+ +(V--V+) + (R2/R1)×Vi ,若R2=R1,R3=R4,且 V-=V+ 則UR5=Vi(輸入電壓) 假設(shè)I5=IL 可得 VA/RL=VI/R5 ,由上式的Va=(V+-V-)R2/R1+V+;及R2=R1;可得。ǎ睼+ - V-)/RL= Vi / R5 即(2V+/V-)-1= RL/ R5; 當(dāng)V+<Vi 和RL<R5,R3+R4>>R5, R3+R4>>RL,時可滿足RL上電流恒定。 3.2 電壓放大模塊設(shè)計 需要把測量到的直流電壓信號放大100倍后,即可傳給AD芯片再由單片機處量。原理圖如下 通過調(diào)節(jié)R2與R1的比值即可以改變電壓放大倍數(shù)。 上圖為LM358的PDF里提供的電路原理圖,實際電路中采用的電阻R2=1MΩ,R1由3296電位器構(gòu)成,阻值調(diào)成10K。 上圖是采用的單個運算放大一百倍。也可以采用兩個運算,每個放大十倍。 實際電路制作過程中,上面兩種方法都進行測試,發(fā)現(xiàn)采用單個運算放大一百倍效果相對要好。所以實際電路中是采用的單個運算放大100倍的方法。 3.3 AD轉(zhuǎn)換與單片機處理 電阻測量所取得的電壓信號放大100倍后,通過AD-IN傳入ADC轉(zhuǎn)換芯片。再由單片機計算,用所得的電壓除以測量時恒定的電流可得電阻的阻值大小,但此時的電阻阻值還不是實際所測得的電阻阻值,因為電壓是放大一百倍后所得的。所以結(jié)果應(yīng)縮小100倍即可得到真實的電阻阻值大小。 3.4 DA轉(zhuǎn)換 由單片機控制DAC5615芯片分別產(chǎn)生40mV、400mV、4000mV的電壓即可獲得需要測量的電流分別為1mA (40mV/40Ω)、10mA (400mV/40Ω)、100mA (4000mV/40Ω)。實際電路中只需要選擇好相應(yīng)的電阻測量范圍即可。不需要手機選擇測試電流,電流將由單片機控制電壓控制電流源電路輸出所需要的電流。 3.5 按鍵的輸入及數(shù)碼管的顯示輸出 采用了串行接口8位LED數(shù)碼管及64鍵鍵盤智能控制芯片HD7279芯片來處理按鍵的輸入及8位數(shù)碼管的輸出顯示。本電路只采用了4×4的按鍵及8位數(shù)碼管顯示輸出。
四.軟件設(shè)計 4.1 主程序流程圖
| 開始 |
| 初始化 |
| 延時等待 |
| 是否有按鍵 |
| 按鍵識別 |
| 調(diào)用相應(yīng)的程序 |
| YES |
| NO |
| YES |
| NO |
| 延時等待 |
| 按鍵說明1: 1mA 電流測量電阻2: 10mA 電流測量電阻3: 100mA電流測量電阻4: 顯示測量電壓值5: 備用(清除顯示)6: 備用(清除顯示)7: 暫停時鐘進入調(diào)整8: 調(diào)整時鐘的數(shù)值9: 啟動并顯示時鐘0: 自動調(diào)零(測量值減去導(dǎo)線電值)上: 產(chǎn)生正弦波下: 產(chǎn)生方波左: 產(chǎn)生三角波右: 皮生距齒波Enter:備用(清除顯示)Esc: 備用(清除顯示) |
|
| |
五.系統(tǒng)功能,指標(biāo)參數(shù) 5.1 系統(tǒng)實現(xiàn)的功能, (1) 電阻的測量,測量電阻范量為0.1mΩ-40Ω。(理論值可達到0.1mΩ) (2) 產(chǎn)生方波,正弦波,方波,鋸齒波。 (3) 時鐘的顯示功能。并可調(diào)整時間。 (4) 測量0-4V間的直流電壓值。 (5) 壓控恒流源 輸入0-4V的電壓,產(chǎn)生恒定的電流為0-100mA。 5.2 測量電阻方法: 用小鱷魚夾接好電阻,選估計被測電阻的范圍,再按下按鍵來選擇測試的電流。其中,在100mA電流(按鍵3)中設(shè)了自動調(diào)零技術(shù)?梢赃x用把測試導(dǎo)線直接短接后,選按下數(shù)字鍵3,再按一下自動調(diào)零按鍵(數(shù)字0)即可。測量出的電阻顯示的是,測量值減去導(dǎo)線間的電阻值。 注意:1必須在測試之前,確定被測電阻可以安全流過最大測試電流!尤其在使用 0.4Ω (100mA)檔時! 2調(diào)零時,先把兩根測試導(dǎo)線短接。按下要用的量程鍵(數(shù)字鍵3)之后,再按下調(diào)零鍵(數(shù)字鍵0)。此時,數(shù)碼管會顯示出當(dāng)前導(dǎo)線間的電阻值一秒鐘并保存。再按下量程鍵(數(shù)字鍵3)即可進行測量。 5.3 實際測試結(jié)果 被測電阻全部為四色壞的碳膜電阻。0.24Ω、2Ω、2.2Ω、3.9Ω 由于測試時電阻有限,所以下面測試中部分電阻阻值是采用以上電阻串聯(lián)或并聯(lián)起來作為一個被測電阻。三個量程測試的數(shù)據(jù)分別如下: 1mA電流的量程,測得電阻阻值如下表
| 量程 | 電阻標(biāo)稱值Ω | 測量電阻值Ω | 絕對誤差 | 相對誤差 % |
| 1mA 40Ω | 1 | 0.99 | 0.01 | 1.00 |
| 1mA 40Ω | 2 | 2.11 | 0.11 | 5.50 |
| 1mA 40Ω | 2.2 | 2.06 | 0.14 | 6.36 |
| 1mA 40Ω | 3.9 | 3.88 | 0.02 | 0.51 |
| 1mA 40Ω | 4 | 4.04 | 0.04 | 1.00 |
| 1mA 40Ω | 6 | 6.28 | 0.28 | 4.67 |
| 1mA 40Ω | 8 | 8.45 | 0.45 | 5.62 |
| 1mA 40Ω | 10 | 10.56 | 0.56 | 5.60 |
| 1mA 40Ω | 12 | 12.88 | 0.88 | 7.33 |
| 1mA 40Ω | 14 | 13.94 | 0.06 | 0.43 |
| 1mA 40Ω | 16 | 16.34 | 0.34 | 2.13 |
| 1mA 40Ω | 18 | 18.82 | 0.82 | 4.56 |
| 1mA 40Ω | 20 | 20.74 | 0.74 | 3.70 |
| 1mA 40Ω | 22 | 22.78 | 0.78 | 3.55 |
| 平均 | | | | 3.71 |
10mA電流的量程,測得電阻阻值如下表 | 量程 | 電阻標(biāo)稱值Ω | 測量電阻值Ω | 絕對誤差 | 相對誤差 % |
| 10mA 4Ω | 0.12 | 0.12 | 0 | 0.00 |
| 10mA 4Ω | 0.24 | 0.24 | 0 | 0.00 |
| 10mA 4Ω | 0.48 | 0.508 | 0.028 | 5.83 |
| 10mA 4Ω | 0.72 | 0.768 | 0.048 | 6.67 |
| 10mA 4Ω | 1 | 1.024 | 0.024 | 2.40 |
| 10mA 4Ω | 2 | 2.052 | 0.052 | 2.60 |
| 10mA 4Ω | 2.2 | 2.216 | 0.016 | 0.73 |
| 10mA 4Ω | 3.9 | 3.928 | 0.028 | 0.72 |
| 10mA 4Ω | 4 | 4.048 | 0.048 | 1.20 |
| 平均 | | | | 2.24 |
100mA電流的量程,測得電阻阻值如下表 | 量程 | 電阻標(biāo)稱值mΩ | 測量電阻值mΩ | 絕對誤差 | 相對誤差 % |
| 100mA 0.4Ω | 60 | 61.4 | 1.4 | 2.33 |
| 100mA 0.4Ω | 80 | 83.5 | 3.5 | 4.38 |
| 100mA 0.4Ω | 120 | 125.4 | 5.4 | 4.50 |
| 100mA 0.4Ω | 240 | 255.8 | 15.8 | 6.58 |
| 平均 | | | | 4.45 |
5.4 對測理結(jié)果的分析: 1 在采用1mA電流測試時,當(dāng)被測電阻小于2Ω時,所得的測試結(jié)果平均比電阻標(biāo)稱值要小0.23Ω。當(dāng)被測的電阻大于14歐時,所得的測試結(jié)果平均比電阻標(biāo)稱值要大1.38Ω。在編程中對上面問題進行了軟件修正。 2 分析原因,當(dāng)測量電流為1mA,電阻小于2歐時,產(chǎn)生的電壓也小于2mV。由于LM358器件原因,而使得輸出結(jié)果小0.23Ω。被測電阻大于14歐時,所得結(jié)果偏大的原因,估計由時測試時的14Ω,16Ω,18Ω,20Ω,22Ω的電阻都是由一單獨阻值為2Ω的碳膜電阻串聯(lián)而成的。在兩電阻間的接觸處沒有用電烙鐵等工具焊接起來,而且直接用把電阻引腳綁定在一起。每個電阻連結(jié)處的電阻給測量結(jié)果帶來的較大的偏差。 3 測試結(jié)果表明,所測得的電阻在一定程度上與電阻本身標(biāo)稱值相同,當(dāng)工作電流太小,或在比較大的電流范圍時誤差有所增加。引起這些誤差的因素是多方面的,主要由測量儀器的系統(tǒng)誤差以及電阻采用的是四環(huán)的碳膜電阻受溫度影響較大,電流源工作在大電流時受溫度影響所致。 4 本系統(tǒng)如果采如精度更高,溫度特性更好的電阻和導(dǎo)線,可提高測量的精度。
六.設(shè)計總結(jié) 在制作毫歐表的過程中,我深切的體會到電路理論與實際相結(jié)合的重要。以及用電腦軟件仿真與電路理論及電路實際的不同。自己制作過程是先實際再理論最后再實際的過程。自己最初制作的毫歐表是采用的是穩(wěn)定的電壓除以大電阻的恒流源方案。測量的結(jié)果不是很穩(wěn)定。而且每次換量程時還需要手動改變電流,操作繁瑣。后面打算單片機通過控制繼電器來改變電流開關(guān)。需要占用較多的單片機資源。而且成本增加。后面發(fā)現(xiàn)了壓控恒流源方案來恒定電流,接著花了很長時間查資料學(xué)習(xí)及實驗采用的壓控恒流源的方法來提拱恒定的電流。在整個制作過程中,主要是離不開上學(xué)期電子培訓(xùn)課上老師所教的知識及提供的條件,讓自己學(xué)到了更多的知識。其次是網(wǎng)上電子愛好者及電子類的論壇給了自己很大的幫助,在整個制作過程中所遇到的問題大部分是通過網(wǎng)絡(luò)上雖互不認(rèn)識但都愛好電子的電子愛好者給予的解答。 用途:測量直流類 mΩ~數(shù)十 Ω 的小電阻,主要用于電動機,揚聲器,繼電器等線圈的直流電阻,由于它們的直流電阻數(shù)值不大,普通萬用表實際很難測量到準(zhǔn)確讀數(shù).使用毫歐表可以解決大部分這種測量.
七.參考文獻 [1]:周塵.單片機C語言輕松入門.北京航空航一大學(xué)出版社.2006 [2]:康華光,陳大欽編.電子技術(shù)基本.高等教育出版社.2004 [3]:周潤景.張麗娜.基于PROTEUSR的電路及單片機系統(tǒng)設(shè)計與仿真.2006 [4]: http://www.jldz08.cn/0606/2711houb.htm 杰龍電子 單片機毫歐表 [5]: http://www.ednchina.com/blog/user_default.aspx?u=asyun&page=3
八.附: 8.1 電路仿真原理圖 在proteus電路仿真軟件中的仿真的壓控恒流源電路原理圖如下: 在Multisim 9電路仿真軟件中的仿真的壓控恒流源電路原理圖如下: 9.2 程序: #include <reg51.h> #include<intrins.h> /********函數(shù)聲明********/ void write7279(unsigned char, unsigned char);//寫入到HD7279 unsigned char read7279(unsigned char); //從HD7279讀出 void send_byte(unsigned char); //發(fā)送一個字節(jié) unsigned char receive_byte(void); //接收一個字節(jié) void delay10ms(unsigned char time); //延時程序 void short_delay(void); //短延時 unsigned int adc1549(void); //ADC TLC1549的驅(qū)動程序 void DaConv(unsigned int DaDat); //DAC TLC5615的驅(qū)動程序 unsigned int lubo(void); //濾波程序 void zhenxianbo(void); //正弦波 void sanjiaobo(void); //三角波 void juchibo(void); //鋸齒波 void fangbo(void); //方波 void displaytime(); //顯示時鐘 void adc(void); //顯示測量出的電壓值 void resistance1mA(); //1mA 計算電阻值 void resistance10mA(); //10mA 計算電阻值 void resistance100mA(); //100mA 計算電阻值 void ABC(); // 計算導(dǎo)線間的電阻值 void overflow(unsigned char d3,unsigned char d2,unsigned char d1,unsigned char d0); // 溢出顯示1 //**************** HD7279A指令 ************ #define CMD_RESET 0xa4 #define CMD_TEST 0xbf #define DECODE0 0x80 #define DECODE1 0xc8 #define CMD_READ 0x15 #define UNDECODE 0x90 #define RTL_CYCLE 0xa3 #define RTR_CYCLE 0xa2 #define RTL_UNCYL 0xa1 #define RTR_UNCYL 0xa0 #define ACTCTL 0x98 #define SEGON 0xe0 #define SEGOFF 0xc0 #define BLINKCTL 0x88 //**************** 鍵盤按鍵代碼 ************ #define one 0x3a #define two 0x39 #define three 0x38 #define four 0x32 #define five 0x31 #define six 0x30 #define seven 0x2a #define eight 0x29 #define nine 0x28 #define Esc 0x22 #define zero 0x21 #define Enter 0x20 #define up 0x3f #define left 0x37 #define right 0x2f #define down 0x27 #define uint unsigned int #define uchar unsigned char //************* 變量及I/O口定義 ****************** unsigned char key_number,hour=0,minute=0,second=0; unsigned int tmr; unsigned int u1=0,u=0,res=0,DaDate; sbit cs=P0^3; // HD7279 sbit clk=P0^2; // HD7279 sbit dat=P0^0; // HD7279 sbit key=P0^1; // HD7279 sbit ad_clk = P2^2; //ADC1549 sbit ad_cs= P2^0; //ad sbit ad_dout= P2^1; //ad sbit DIN=P2^3; //DAC5615 sbit DaCS=P2^4; //da sbit DaSCLK=P2^5; //da /***************正弦波數(shù)值表******************/ void da5615(unsigned int); void fangbo(void); void juchibo(void); void sanjiaobo(void); void zhenxianbo(void); void set_time (void); code unsigned char TAB[]={ 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,0XEF,0XF1,0XF2,0XF3,0XF4,0XF5, 0XF6,0XF7,0XF8,0XF9,0XFA,0XFB,0XFC,0XFD,0XFE,0XFE,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF, 0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFE,0XFE,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,0XC9,0XC5,0Xc2,0XBF,0XBC,0XBA,0XB7,0XB4,0XB1, 0XAE,0XAB,0XA8,0XA5,0XA2,0X9F,0X9C,0X99,0X96,0X93,0X90,0X8D,0X89,0X86,0X83,0X80, 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, 0X00,0X00,0X00,0X01,0X00,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}; main() { unsigned char a,*p; while(1) { for (tmr=0;tmr<0x2000;tmr++); //上電延時 send_byte(CMD_RESET); //復(fù)位HD7279A cs=1; delay10ms(10); key_number=0xff; TMOD=0x01; //定時器0 工作方式1 TH0=0xdc; //定時時間=(65536-56320)*(1/11.0592)*12=10ms (fosc=11.0592) TL0=0x00; ET0=1; TR0=1; if (!key) //如果有鍵按下 { key_number=read7279(CMD_READ); //讀出鍵碼 tmr=key_number; switch(tmr) { case one: do{ resistance1mA(); delay10ms(100);//1mA 電流時測得 電阻值 DaConv(11); }while(key);break; case twdo{ resistance10mA(); delay10ms(100);//10mA 電流時測得 電阻值 DaConv(100); }while(key);break; case three:do{ resistance100mA();delay10ms(100);//100mA 電流時測得 電阻值 DaConv(1000); }while(key);break; case zer ABC();delay10ms(100); //計算導(dǎo)線間的電阻值 break; case four:do{ adc();delay10ms(100); //顯示電壓值 DaConv(1000); }while(key);break; case seven: EA=0; //關(guān)總中斷 時鐘暫停,進入調(diào)整 a++; if(a==1) { write7279(BLINKCTL,0x3f); // 此時調(diào)整 時 第6、7兩位設(shè)為閃爍顯示 p=&hour; } if(a==2) { write7279(BLINKCTL,0xe7); // 此時調(diào)整 分 第3、4兩位設(shè)為閃爍顯示 p=&minute; } if(a==3) { write7279(BLINKCTL,0xfc); // 此時調(diào)整 秒 第0、1兩位設(shè)為閃爍顯示 p=&second; } if(a>3){a=0; write7279(BLINKCTL,0xff); //清除閃爍設(shè)置 } displaytime(); //顯示時鐘 DaConv(0); delay10ms(100); break; case eight: *p=*p+1; if(second>59||minute>59){*p=0;} //當(dāng) 分 或 秒 顯示為59時變?yōu)? if(hour>23){*p=0;} //當(dāng) 時 顯示為23時變?yōu)? displaytime(); //顯示時鐘 delay10ms(100); DaConv(0);;break; case nine: do{ EA=1; //開總中斷 displaytime(); //顯示時鐘 delay10ms(100); DaConv(0); }while(key);break; case up:do{ zhenxianbo(); //正弦波 }while(key);break; case left:do{ sanjiaobo(); //三角波 }while(key);break; case right:do{ juchibo(); //鋸齒波 }while(key);break; case down:do{ fangbo(); //方波 }while(key);break; } } } } /************* 定時器0中斷 ************/ void timer0() interrupt 1 //定時器0中斷 { static Count=0; //靜態(tài)變量計數(shù)器 TH0=0xdc; TL0=0x00; Count++; if(Count>=100){ Count=0; second=second+1; } //判斷時間是否到 1s 了? if(second>=60){ second=0; minute+=1; } if(minute>=60){ minute=0; hour+=1; } if( hour>=23 && minute>=59 && second>=59){ second=0; minute=0; hour=0;} } /************* 顯示時鐘 ************/ void displaytime() //顯示時鐘 { write7279(DECODE0+1,second/10); //顯示 秒的 十位 write7279(DECODE0+0,second%10); //顯示 秒的 個位 write7279(DECODE0+2,10); write7279(DECODE0+4,minute/10); //顯示 分的 十位 write7279(DECODE0+3,minute%10); //顯示 分的 個位 write7279(DECODE0+5,10); write7279(DECODE0+7,hour/10); //顯示 時的 十位 write7279(DECODE0+6,hour%10); //顯示 時的 個位 } /************* ADC數(shù)碼管顯示轉(zhuǎn)換后的電壓值數(shù)值************/ void adc(void) { unsigned char d0,d1,d2,d3; unsigned int a; u1=lubo(); a=u1<<2; /* a=u1*4; */ d3=a/1000; d3=d3|0x80; //顯示小數(shù)點 d2=a/100%10; d1=a/10%10; d0=a%10; write7279(DECODE0+3,d3); write7279(DECODE0+2,d2); write7279(DECODE0+1,d1); write7279(DECODE0+0,d0); } /************* 1mA 計算電阻值************/ void resistance1mA() { unsigned char d0,d1,d2,d3; unsigned int a; u1=lubo(); a=u1*40; if(a>200&&a<2000){a=a+230;} //修正電阻值 當(dāng)電阻值小于2歐姆時,顯示結(jié)果為測量值加0.23歐 if(a>14000&&a<40770){a=a-1380;} //修正電阻值 當(dāng)電阻值大于14歐姆時,顯示結(jié)果為測量值減去1.38歐 d3=a/10000; d2=a/1000%10; d2=d2|0x80; //顯示小數(shù)點 d1=a/100%10; d0=a/10%10; overflow(d3,d2,d1,d0); } /************* 10mA 計算電阻值************/ void resistance10mA() { unsigned char d0,d1,d2,d3; unsigned int a; u1=lubo(); a=u1<<2; /* a=u1*4; */ d3=a/1000; d2=a/100%10; d1=a/10%10; d0=a%10; overflow(d3,d2,d1,d0); } /************* 100mA 計算電阻值************/ void resistance100mA() { unsigned char d0,d1,d2,d3; unsigned int a; u1=lubo(); a=u1<<2; /* a=u1*4; */ if(a!=4092){ a=a-res; d3=a/1000; d2=a/100%10; d1=a/10%10; d1=d1|0x80; //顯示小數(shù)點 d0=a%10; write7279(DECODE0+7,d3); // 第八位數(shù)碼管 write7279(DECODE0+6,d2); // 第七位數(shù)碼管 write7279(DECODE0+5,d1); // 第六位數(shù)碼管 write7279(DECODE0+4,d0); // 第五位數(shù)碼管 } else{ write7279(DECODE0+7,1); // 超出范轉(zhuǎn)顯示1 write7279(DECODE0+6,0x0f); // 第七位數(shù)碼管 空 write7279(DECODE0+5,0x0f); // 第六位數(shù)碼管 空 write7279(DECODE0+4,0x0f); // 第五位數(shù)碼管 空 } } /************* 溢出顯示1************/ void overflow(unsigned char d3,unsigned char d2,unsigned char d1,unsigned char d0) { if(d3==4 && d1==9) // 超出范轉(zhuǎn)顯示1 { write7279(DECODE0+7,1); // 超出范轉(zhuǎn)顯示1 write7279(DECODE0+6,0x0f); // 第七位數(shù)碼管 空 write7279(DECODE0+5,0x0f); // 第六位數(shù)碼管 空 write7279(DECODE0+4,0x0f); // 第五位數(shù)碼管 空 } else { write7279(DECODE0+7,d3); // 第八位數(shù)碼管 write7279(DECODE0+6,d2); // 第七位數(shù)碼管 write7279(DECODE0+5,d1); // 第六位數(shù)碼管 write7279(DECODE0+4,d0); // 第五位數(shù)碼管 } } /************* 計算導(dǎo)線間的電阻值************/ void ABC() { unsigned int a; unsigned char d0,d1,d2,d3; a=lubo(); a=a<<2; /*a=a*4;*/ d3=a/1000; d2=a/100%10; d1=a/10%10; d0=a%10; if(a>=3000){ res=0; write7279(DECODE0+3,d3); // 第八位數(shù)碼管 write7279(DECODE0+2,d2); // 第七位數(shù)碼管 write7279(DECODE0+1,d1); // 第六位數(shù)碼管 write7279(DECODE0+0,d0); // 第五位數(shù)碼管 } else{ res=a; write7279(DECODE0+3,d3); // 第八位數(shù)碼管 write7279(DECODE0+2,d2); // 第七位數(shù)碼管 write7279(DECODE0+1,d1); // 第六位數(shù)碼管 write7279(DECODE0+0,d0); // 第五位數(shù)碼管 } delay10ms(100); } //*************A/DC1549轉(zhuǎn)換子程序************** unsigned int adc1549(void) { uchar i; ad_cs=0; ad_clk=0; ad_dout=1; u=0; for(i=0;i<10;i++) /*read data */ { ad_clk=0; short_delay(); u=u*2; if (ad_dout==1) { u ++ ; } ad_clk =1 ; //上升沿接受數(shù)據(jù) short_delay(); } ad_dout=1; ad_cs=1; return u; /*return ad data */ short_delay(); } //*************濾波程序************************* unsigned int lubo(void) //濾波程序 { unsigned char i; unsigned int a[10],sum=0,value; for(i=0;i<10;i++) //取值 { a[i]=adc1549(); short_delay(); } for(i=0;i<10;i++) //求和 { sum=sum+a[i]; } value=sum/10; //計算平均值 return value; } //**************TLC5615轉(zhuǎn)換子程序******************* void DaConv(uint DaDat) //TLC5615的驅(qū)動程序,命令:DAConv { uchar i=0; DaCS=1; _nop_(); _nop_(); DIN=0; DaSCLK=0; DaCS=0; _nop_(); _nop_(); for(i=0;i<12;i++) { DaDat=_irol_(DaDat,1); if((DaDat&0x0400)!=0) DIN=1; else DIN=0; DaSCLK=1; _nop_(); _nop_(); DaSCLK=0; _nop_(); _nop_(); } DaCS=1; DIN=0; DaSCLK=0; } void send_byte( unsigned char out_byte)//發(fā)送一個命令字 { unsigned char i; clk=0; cs=0; short_delay(); for (i=0;i<8;i++) { clk=0; if (out_byte&0x80) {dat=1;} else {dat=0;} clk=1; short_delay(); out_byte=out_byte*2; } dat=1; } unsigned char receive_byte(void) //接收一個命令字 { unsigned char i, in_byte; cs=0; clk=0; dat=1; //設(shè)為輸入狀態(tài) short_delay(); for (i=0;i<8;i++) { clk=0; in_byte=in_byte*2; clk=1; if (dat==1) { in_byte=in_byte|0x01;} } dat=1; //cs=1; return (in_byte); } void write7279(unsigned char cmd, unsigned char dta) { send_byte (cmd); send_byte (dta); cs=1;} unsigned char read7279(unsigned char command) { send_byte(command); cs=1; return(receive_byte()); } void short_delay(void) //短延時 { unsigned char i; for (i=0;i<8;i++);} // ********************* n*10ms 延時********************** void delay10ms(unsigned char time) { unsigned char i; unsigned int j; for(i=0;i<time;i++) { for(j=0;j<0x390;j++); } } /***********方波***********/ void fangbo(void) {uint j; delay10ms(100); while(key) {for(j=0;j<2;j++) {if(j<1) DaConv(0x0fff); else DaConv(0x0000); } } } /*********鋸齒波**********/ void juchibo(void) {uint i,j; i=0; j=0; delay10ms(100); while(key) { if(i<500) {i=i+30; //周期 j=j+3; //幅值 DaConv(j*40);} else {i=0; j=0;} } } /*************三角波***************/ void sanjiaobo(void) {uint i,j,k; i=0; j=0; delay10ms(100); while(key) {for(i=0;i<1;i++) //周期 {if(j<200) {k=200; j=j+10; DaConv(j*10);} else { if(k<1) j=0; else {DaConv(k*10); k=k-10;} } } } } /**************正弦波*******************/ void zhenxianbo(void) {uint i; delay10ms(100); while(key) { for(i=0;i<253;i++) DaConv(TAB[i]*6); } }