c51做的電壓表,可切換量程,數據發送到上位機
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
下面是多量程電壓表的設計文檔:
1.設計目的 1.1鞏固和加深對微處理器原理和接口技術知識的理解; 1.2培養根據課題需要選學參考書籍、查閱手冊和文獻資料的能力; 1.3學會方案論證的比較方法,拓寬知識,初步掌握工程設計的基本方法; 1.4掌握常用儀器、儀表的正確使用方法,學會軟、硬件的設計和調試方法; 1.5能按設計的要求編寫設計文檔,能正確反映設計和實驗成果,能用計算機繪制電路圖和流程圖。 2.設計要求 2.1 使用ADC0832進行模數轉換; 2.2 通過串口讀取測量到的電壓值; 2.3 數碼管顯示測量到的電壓值; 2.4 可測多個量程的電壓。 3. 硬件設計 3.1 設計思想 該系統的硬件設計思路如下:首先,通過ADC0832對外部電壓進行模數轉換,然后通過時鐘線、數據線和控制使能線與單片機相連。而后,單片機通過八根數據線與四個控制線與四位數碼管進行連接,用于顯示測量到的電壓。另外,單片機通過TX給外部發送數據,PC端可以通過USB-TTL模塊直接接收到電壓值。最后,關于多量程設計,量程方面我采用了電阻分壓方式,這樣就可以實現大量程的測量,量程選擇方面我使用了開關與繼電器實現。 3.2主要元器件介紹 3.2.1 ADC0832 ADC0832 是美國國家半導體公司生產的一種8位分辨率、雙通道A/D轉換芯片。芯片引腳圖如圖1所示。其引腳分別為CS(片選使能)、CH0(模擬輸入通道0)、CH0(模擬輸入通道1)、GND(供電及參考電壓低電位)、DI(數據信號輸入)、DO(數據信號輸出)、CLK(時鐘信號輸入)以及VCC/VREF(電源及參考電壓輸入)其時序邏輯圖如圖2所示。由圖2可知一般情況下ADC0832與單片機連接應使用四根控制信號線,分別為CS、DO、DI和CLK。但由圖2可知DO與DI其中一個作用時,另一個則不作用,因此在進行硬件電路設計時可以將DO和DI連接在同一個I/O口上。 ADC0832為8位分辨率A/D轉換芯片,其最高分辨可達256級,可以適應一般的模擬量(低精度)轉換要求。 
圖1 
圖2 3.3.2 STC89C52RC STC89C52RC 單片機是宏晶科技推出的超強抗干擾、高速、低功耗單片機,指令代碼完全兼容傳統8051單片機。其最高頻率時鐘為80 MHz, Flash 存儲器為8KB, RAM為512 bit,E2PROM為2KB,可反復擦寫編程。工作溫度為-40℃~+85℃, 內置看門狗電路,內部電源供電系統、時鐘電路和復位電路都經過特殊處理。“6 時鐘/機器周期”和“12 時鐘/機器周期”可在ISP編程時反復設置。其DPIP封裝引腳圖如圖3所示。實物圖如圖4所示。 
圖3 圖4 3.2.3 四位共陽極數碼管 圖5所示即為該系統所采用的共陽極數碼管。該數碼管共有12個引腳,其中8個為數據引腳,4個為控制引腳。數據引腳作用為向數碼管輸入要顯示的數據,控制引腳作用為分別控制四個數碼的亮和滅。圖6所示及為其內部電路圖。 
圖5 
圖6 3.3 原理圖及功能電路介紹 整體原理圖如圖7所示。該電路可以分為三個部分,分別為:模數轉換部分、顯示部分和數據處理部分。 
圖7 3.3.1 顯示部分 
圖8 圖8所示即為顯示部分電路圖。該部分實現的功能是顯示測量到的樹值。數碼管的八個的數據引腳引出接到單片機的P0上,用于接受顯示數據。四個控制引腳分別接在四個PNP管的集電極上,然后PNP管的基極連接單片機的四個I/O口,發射極接VCC。這里控制引腳不直接接單片機上的原因是:單片機I/O無法提供大電流,不能作為共陽極數碼管的控制信號,因此需要接三極管方大電流。 3.2.2模數轉換部分 
圖9 圖9所示即為模數轉換部分電路圖。該部分的主要作用是測量電壓值并以數字量傳輸到單片機中。該部分可以分為兩個子部分,分別為測量部分和量程控制部分。測量部分由ADC0832組成,它通過三根線將CS、CLK、DO與DI與單片機相連。另外,其CH0接到量程控制部分讀取電壓。量程控制部分主要由繼電器、開關和電阻組成。開關連接一個I/O口和繼電器。繼電器選擇接入CH0的信號,當為導通時,量程為0~5V,外部無其他電路,當為不導通時,量程為0~50V,外部接一個電阻分壓電路。 3.2.3 數據處理部分 中央數據處理部分由89C52RC構成。該部分將上述兩部分整合并控制。MCU的P0口接數碼管的數據線;P1.0~P1.3接數碼管控制部分(三極管的基極);P1.4接量程控制部分的開關,作用是讀取當前量程選擇情況;P2.0~P2.2分別接ADC0832的CS、CLK和DO/DI;TX接外部通信設備,接受當前的電壓測量值。 4. 軟件設計 4.1 設計思想 單片機啟動后,先初始化串口,并定義緩存變量,然后進行while死循環。在死循環中,先調用AD轉換函數讀一次“電壓值”,但這時得到的并不是真正的電壓值,所以需要進行精度修正,將范圍0~255的范圍修正為0~500。再判斷當前量程選擇情況,根據它來判斷顯示與串口數據的小數點位置,最后將數據顯示并通過串口發送。 4.2軟件流程圖 
圖10
5. 調試運行 5.1 小量程測量結果 圖11為小量程電壓的仿真測量結果。左下方電壓表為ADC0832輸入的電壓,為4.32V。而圖中數碼管讀到的值為4.33V,串口發送的數據也為4.33V。因此,可以得出結論,在小量程的仿真測試中,電壓測量誤差非常小,可忽略不計。 
圖11 5.1大量程測量結果 圖12為大量程電壓的仿真測量結果。左下方第一個電壓表為ADC0832輸入的電壓,為4.52V,第二個電壓表為所測激勵源的電壓,為45.2。而圖中數碼管讀到的值為45.2V,串口發送的數據也為45.2V。因此,可以得出結論,在大量程的仿真測試中,電壓測量誤差幾乎沒有。 
圖12 6.設計心得體會 通過此次設計,讓我們對所學的51單片機更加熟悉了解,對理論學習時沒有掌握牢固的一些知識以及一些在學習中存在的漏洞進行學習并加以彌補。在學習上光有理論知識那只是“紙上談兵”,還需實際動手去實踐。真正把所學的用到日常生活中,理論聯系實際,做出實物模型。這次單片機設計,我設計的是多量程電壓表設計,通過這次設計我感覺到要想做成功,必須花時間多做準備,查閱大量資料,每個過程都很繁瑣,都要認真地分析每一步每一個模塊要實現大的功能,然后分步進行編寫調試,最后整合成在一起。另外,通過本次設計,我也學會了熟練使用proteus進行仿真設計。 在這次設計,我們知道了基于單片機的系統設計,需要從兩個方面入手:一是軟件的實現即程序的編寫,二是硬件電路的實現。因此在這次的單片機設計中,我不僅鞏固了我所學的單片機知識,而且也提高了我的硬件設計水平和動手能力,使得我的實踐能力進一步增強。 參考書目: [1] 肖金球. 單片機原理與接口技術.[M].北京:清華大學出版社,2004.12 [2] 郭天祥. 新概念51單片機C語言教程: 入門、提高、開發、拓展全攻略[M]. 電子工業出版社, 2009. [3] 康華光. 電子技術基礎. 模擬部分[M]. 高等教育出版社, 1999.
單片機源程序如下: - /***************** 多量程電壓表*********************/
- /******** 作者:孫瑋 學號:14200106214**************/
- /*系統主要實現功能:通過ADC0832將讀取到的模擬量轉化*/
- /*為數字量,并通過單片機進行讀取然后顯示在數碼管上**/
- /*并且可以通過串行口讀取到所測量的電壓值。此外,該**/
- /*電路通過電阻分壓可以實現多個量程的測量************/
- #include <reg52.h> //52系列單片機頭文件定義
- #include <stdio.h> //C語言頭文件定義
- //***************************
- //*******引腳定義************
- //***************************
- //ADC0832控制口定義
- sbit CS =P2^0; //CS:片選使能信號輸出端
- sbit CLK=P2^1; //CLK:時鐘信號輸出端
- sbit DIO=P2^2; //DI/DO信號輸出端(由于D0與D1在通信時不會同時有效,所以共用一個IO口)
- //數碼管控制引腳定義(數據引腳共8個,使用P0)
- sbit S_1=P1^0; //第一個數碼管陽極控制端
- sbit S_2=P1^1; //第二個數碼管陽極控制端
- sbit S_3=P1^2; //第三個數碼管陽極控制端
- sbit S_4=P1^3; //第四個數碼管陽極控制端
- //量程與繼電器控制引腳定義
- sbit KEY=P1^4; //用于量程的選擇以及繼電器的控制
- //***************************
- //*******常量定義************
- //***************************
- unsigned int table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
- //0~9在共陽數碼管中所對應的十六進制值
- //***************************
- //*******延時1000us**********
- //***************************
- void delay_1000us() //簡單延時函數,約延時1000us
- {
- unsigned char i=1000;
- while(i--);
- }
- //***************************
- //*******ADC0832讀取程序*****
- //***************************
- unsigned int ADC0832() //此處編程參考ADC0832英文手冊
- {
- unsigned int i,buff; //緩存數據定義
- //一個讀取周期開始
- CS=1; //CS置一,轉換開始
- CLK=0; //為第一個時鐘信號做準備
- CS=0; //芯片使能
- DIO=1; //給發送DI發送起始電平
- CLK=1; //第一個時鐘開始
- CLK=0; //第一個時鐘結束
- DIO=1; //給DI發送高電平,選擇單通道模式
- CLK=1; //第二個時鐘開始
- CLK=0; //第二個時鐘結束
- DIO=0; //給DI發送低電平,選擇通道0
- CLK=1; //第三個時鐘開始
- CLK=0; //第三個時鐘結束
- DIO=1; //DO置一,準備讀取數據
- for(i=0;i<8;i++) //讀取八位數據,由高到低讀取
- {
- CLK=1; //時鐘信號拉高
- CLK=0; //下降沿有效,進行讀取數據
- buff<<=1; //將下面儲存的低位數據向右移
- buff|=DIO; //將輸出數據DIO通過或運算儲存在buff最低位
- }
- CS=1; //測量完畢,將CS拉高,片選無效
- return buff;
- }
- //***************************
- //*******串口初始化程序******
- //***************************
- void UartInit(void) //串行口初始化
- {
- SCON=0x50; //8位數據,可變波特率
- TMOD=0x20; //設定定時器1為16位自動重裝方式
- TL1=0xFD; //設定定時初值
- TH1=0xFD; //設定定時初值
- ET1=0; //禁止定時器1中斷
- TR1=1; //啟動定時器1
- }
- //***************************
- //*******主程序**************
- //***************************
- void main()
- {
- unsigned int buff,ge,shi,bai; //緩存數據定義
- UartInit(); //串口初始化
- while(1) //死循環
- { //主函數程序開始
- buff=ADC0832()*100; //讀取AD的值,并進行修正
- buff=buff/51; //精度修正,轉換為000~500范圍
- bai=buff/100; //保存buff的百位
- shi=(buff%100)/10; //保存buff的十位
- ge=buff%10; //保存buff的個位
- //數碼管顯示程序
- if(KEY==1) //如果KEY為1,量程設為0~5V
- {
- S_1=0; //選通第一位數碼管,顯示第一位數
- P0=table[0]; //P0口輸出8位數據
- delay_1000us(); //短暫延時
- P0=0xff; //數碼管消隱
- S_1=1; //關閉第一位數碼管
- S_2=0; //選通第二位數碼管,顯示第二位數
- P0=table[bai]&0x7f; //P0口輸出8位數據,因為量程為為0~5V,所以第一位后顯示小數點
- delay_1000us(); //短暫延時
- P0=0xff; //數碼管消隱
- S_2=1; //關閉第二位數碼管
- S_3=0; //選通第三位數碼管,顯示第三位數
- P0=table[shi]; //P0口輸出8位數據
- delay_1000us(); //短暫延時
- P0=0xff; //數碼管消隱
- S_3=1; //關閉第三位數碼管
- S_4=0; //選通第四位數碼管,顯示第四位數
- P0=table[ge]; //P0口輸出8位數據
- delay_1000us(); //短暫延時
- P0=0xff; //數碼管消隱
- S_4=1; //關閉第四位數碼管
- //串口發送程序
- TI=1; //TI置一,開始發送數據
- printf("%d.%d%d\n",bai,shi,ge);
- //將buff/100后發出
- while(!TI); //直到數據發送完畢
- TI=0; //數據發送完畢后,TI置〇
- }
- else //如果KEY為1,量程設為0~50V
- {
- S_1=0; //選通第一位數碼管,顯示第一位數
- P0=table[0]; //P0口輸出8位數據
- delay_1000us(); //短暫延時
- P0=0xff; //數碼管消隱
- S_1=1; //關閉第一位數碼管
- S_2=0; //選通第二位數碼管,顯示第二位數
- P0=table[bai]; //P0口輸出8位數據
- delay_1000us(); //短暫延時
- P0=0xff; //數碼管消隱
- S_2=1; //關閉第二位數碼管
- S_3=0; //選通第三位數碼管,顯示第三位數
- P0=table[shi]&0x7f; //P0口輸出8位數據,因為量程為為0~50V,所以第二位后顯示小數點
- delay_1000us(); //短暫延時
- P0=0xff; //數碼管消隱
- S_3=1; //關閉第三位數碼管
- S_4=0; //選通第四位數碼管,顯示第四位數
- P0=table[ge]; //P0口輸出8位數據
- delay_1000us(); //短暫延時
- P0=0xff; //數碼管消隱
- S_4=1; //關閉第四位數碼管
- //串口發送程序
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
資料51hei附件下載:
仿真程序文檔.7z
(1.18 MB, 下載次數: 196)
2022-5-8 19:12 上傳
點擊文件名下載附件
|