自適應量程數字電壓表設計總結


1. 任務需求

  • 量程:直流電壓0~20V
  • 三檔:0~200mV,200mV~2V,2V~20V
  • 精度:0.01,顯示穩定,無閃爍
  • 誤差:0.2V擋位≤10%,2V和20V擋≤1%

2. 需求分析

  • 直流電壓表(0~20V):利用數碼管,通過數字方式顯示測定直流電壓值,其范圍為0~20V
  • 自動量程轉換:0~20V直流電壓分為三檔:0~0.2V,0.2V~2V,2V~20V。且能根據0~20V測試電壓的具體值來自動切換量程

3. 設計方案

3.1. 總概述

首先,我們了解到測試電壓為0~20V的直流電壓。現我們使用的ADC0809芯片只能處理0~5V電壓。故,我們先需要將0~20V電壓5分壓至0~4V,即滿足了ADC0809芯片處理范圍。然后STC89C52接收到數字量后,在程序中判斷當前量程是否合適。若是,則將電壓值輸出到數碼管上顯示。否,則反饋調節數據選擇器的輸出口去調節擋位,直到量程合適。總體設計圖如3-1

圖3-1

3.2. 電壓放大部分

這一部分屬於信號預處理部分,實際上電壓表的誤差主要出現在這里。首先,我了解到ADC0809為八位A/D轉換芯片,量化模擬電壓值范圍為0~5V。我們測定電壓范圍為0~20V,故我首先要將其5分壓至0~4V以便滿足其需求。而為了精確測定,我需要將5分壓后較小的兩個量程0~0.2、0.2~2分別放大100倍、10倍。此處,我借助同相比例放大器。三個擋位增益由小到大根據圖3-2分別為1、1+R10/R9、1+R11/R9。同時,為了滿足自動轉換這一需求,我借助74HC4051芯片——八選一數據選擇器。將其數據地址口A、B分別與單片機P1.4、P1.5相連。在單片機內部程序中,根據ADC0809送入數字量判斷當前量程是否合適,若不合適改變數據選擇器的地址輸入,即可完成自動量程轉換這一需求。

圖3-2

3.3. 模數轉換部分

主要元器件為ADC0809與74LS74。這一部分屬於整個電路中最最為關鍵的部分,但是實際上設計與操作來說,並不是特別復雜。因為ADC0809芯片集成度很高,我只需要將其啟動轉換端口,轉換完成標志端口等將其與單片機STC89C52相連接,並且在程序內編寫相關語句就可以完成對ADC0809芯片的控制,即可完成A/D轉換的處理。而74LS74芯片是一個雙D觸發器。由於ADC0809內部並沒有晶振電路,所以,其需要時鍾信號,並且要求范圍在0~640Khz之間。這次我使用的STC89C52芯片晶振頻率為6Mhz,其ALE口輸出為1Mhz,故使用D觸發器進行二分頻可得到500Khz時鍾信號,即完成ADC0809芯片的正常運轉。

 

圖3-3

3.4. 數碼管顯示部分

在位選部分我選擇了P0口,值得注意的一點是:P0口在作為通用I/O使用時,需要接入上拉電阻並且手動先置高電平。並且,我使用了共陰極七段數碼管,所以在位選個個端口要接入非門。在段選部分,我使用P2.0~3,使用了4511譯碼器,即可完成段選數據的輸入。小數點則單獨使用了P2.7口,在單片機程序內判斷是否點亮它。

圖3-4

4. 仿真

2~20V:測試用量5V

 

0.2~2V:測試用量1.5V

 

0~0.2:測試用量0.1V

5. 調試與測試

5.1. 幾個問題

問題一:如何降低同相比例放大器處的誤差?(此處誤差為電壓表誤差最主要之處)

問題二:如何保證數碼管處焊接無錯誤(此處為電路中最難焊接之處)

問題三:如何確保ADC0809芯片處於正常工作狀態

5.2. 問題分析

問題一:由於定值電阻並不是完全准確,所以在同相比例放大器處放大倍數並不是在仿真中那樣完全理想。故會產生較大的誤差。

問題二:數碼管處在段選部分,我們使用單個I/O控制,故此我們需要將每一個數碼管對應的引腳並連。線路並不復雜,但極易出現短路、短路、鏈接錯誤等情況。

問題三:ADC0809正常工作有比較多的需求。首先,需要有0~640kHZ的時鍾信號,其次,單片機內部程序要對其正確的操作。

5.3. 解決方法

問題一:采用電位器,在整個電路焊接好之后,調節電位器來減小誤差。

問題二:編寫測試文件,即單片機程序送出一個固定的數字,若數碼管顯示數字及小數點符合預期要求,即數碼管處連接正確。反之,則有錯誤。

問題三:實際上來說這個問題並不能直接調試,因為假定寫入完整的程序,數碼管是固定的數字,並無法保證是其出錯。我的方法是:寫入完整的程序后,給定1V測試電壓。在預期方案中1V屬於0.2~2V量程,則此刻4051選擇通道2,則此時其數據地址A為高,B為低。若是如此,則ADC0809完成了正常的數據采集操作,因為A之所以為高,B之所以為低是單片機程序作用的結果,而單片機只有接收到了正確的值才會做這個操作。故反推ADC0809是正常工作的。

6. 參考文獻

汪文、陳林. 單片機原理及應用[M]. 湖北:華中科技大學出版社.

7. 附錄1(測量數據)

8. 附錄2(源碼)

  1 #include<reg52.h>
  2 sbit start = P1^0; //啟動A/D轉換
  3 sbit eoc = P1^1;    //轉換結束信號輸出端
  4 sbit oe = P1^2;        //輸出允許
  5 sbit ale = P1^3;    //地址鎖存允許
  6 
  7 //自動擋位選擇輸入
  8 sbit a = P1^4;
  9 sbit b = P1^5;
 10 
 11 sbit point = P2^7;
 12 
 13 
 14 unsigned int W_temp_data[4] = {0x08, 0x04, 0x02, 0x01};//位選數據
 15 unsigned int D_temp_data[8] = {0,0,0,0,0,0,0,0}; //段選數據
 16 
 17 unsigned long int temp_data = 0; //ADC0809輸出數字量
 18 
 19 /*********************
 20  *       軟件延時     *
 21  *********************/
 22 void deley(unsigned int x)
 23 {
 24     unsigned int i,j;
 25     for(i=0; i<x; i++)
 26     {
 27         for(j=0; j<100; j++)
 28         {
 29             ;
 30         }
 31     }
 32 }
 33 
 34 /*********************
 35  *       顯示函數        *
 36  *********************/
 37 void display(unsigned int x)
 38 {
 39     unsigned int i, j;
 40     for(j = 0; temp_data ; j ++)
 41     //將數字量每一位取出放入D_temp_data數組中
 42     {
 43         D_temp_data[j] = temp_data % 10;
 44         temp_data = temp_data / 10;
 45     }
 46     for(i = 0; i < 4; i ++)
 47     {
 48     
 49         //前導零消除
 50         if(x == 0 && i == 3 && D_temp_data[i] == 0)
 51         {
 52             break;
 53         }
 54         if(x == 2)
 55         {
 56             if(D_temp_data[i] == 0 && i == 2 && D_temp_data[3] == 0)
 57             {
 58                 break;
 59             }
 60             if(D_temp_data[i] == 0 && i == 3)
 61             {
 62                 break;
 63             }
 64         }
 65         P0 = W_temp_data[i];
 66         P2 = D_temp_data[i];
 67         //小數點顯示
 68         if(x == 0)
 69         {
 70             if(i == 2)
 71             {
 72                 point = 1;
 73             }
 74         }
 75         else if(x == 1)
 76         {
 77             if(i == 3)
 78             {
 79                 point = 1;
 80             }
 81         }
 82         else if(x == 2)
 83         {
 84             if(i == 1)
 85             {
 86                 point = 1;
 87             }
 88         }
 89         deley(1);
 90     }
 91 }
 92 
 93 /*********************
 94  *       擋位選擇       *
 95  *    x: 0 *1擋        *
 96  *       1 *10擋        *
 97  *       2 *100擋        *
 98  *********************/
 99 void choose(unsigned int x)
100 {
101     switch(x)
102     {
103         case 0:
104             a = 0;
105             b = 0;
106             break;
107         case 1:
108             a = 1;
109             b = 0;
110             break;
111         case 2:
112             a = 0;
113             b = 1;
114             break;
115         default:
116             ;
117     }
118 }
119 
120 void main()
121 {
122     unsigned int x = 0; //量程控制
123     while(1)
124     {
125         ale = 1;
126         deley(1);
127         ale = 0;
128         choose(x);
129         start = 1;
130         deley(1);
131         start = 0; //下降沿啟動A/D轉換
132         while(eoc == 0)
133         //轉換結束
134         {
135             ;
136         }
137         oe = 1; //輸出允許
138         temp_data = P3;
139         oe = 0; //輸出阻塞
140         if(x == 0 && temp_data < 21)
141         //量程過高,切換至0.2-2V
142         {
143             x = 1;
144             continue;
145         }
146         if(x == 1 && temp_data < 21)
147         {
148         //量程過高,切換至0-0.2V
149             x = 2;
150             continue;
151         }
152         if(x ==1 && temp_data > 204)
153         //量程過低,切換至2-20V
154         {
155             x = 0;
156             continue;
157         }
158         if(x == 2 && temp_data > 204)
159         //量程過低,切換至0.2-2V
160         {
161             x = 1;
162             continue;
163         }
164         temp_data = temp_data * 100 * 5 /51;
165         display(x);
166     }
167 }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM