題目:基于51單片機數字頻率計的設計 系 部: 專 業: 學 號: 學生姓名: 指導教師姓名: 指導教師職稱:
XXXXXXXXXX學院(論文) 摘 要 本文提出設計數字頻率計的方案,重點介紹以單片機AT89C51為控制核心,實現頻率測量的數字頻率設計。測頻的基本原理是采用在低頻段直接測頻法,在低頻段直接測頻法的設計思路,硬件部分由單片機和數計顯示電路組成;軟件部分由信號頻率測量模塊和數據顯示模塊等模塊實現。應用單片機的控制功能和數學運算能力,實現計數功能和頻率的換算。設計的頻率計范圍能夠達到1HZ~1MHZ,滿足所要求的頻率范圍,測量精度較高。
目錄 前 言 第一章 總體設計方案 1.1 總設計框圖 1.2 硬件設計分析 1.2.1 電源的設計 (4):LCD1602的指令說明及時序 (5): LCD1602的RAM地址映射及標準字庫表 第二章 軟件設計與分析 2.1 軟件設計的組成 2.2 各部分軟件分析 2.2.1 定時器0中斷子函數 2.2.2 定時器1中斷子函數 2.2.3 主函數 2.3 總源程序 第三章 軟件介紹 3.1 PROTEUS簡介 3.2 PROTEL 99 SE簡介 3.2.1 電路工程設計部分 3.2.2 電路仿真與PLD部分 3.3 Protel 99 SE的功能特性 3.4 Protel99SE快捷鍵大全 3.6仿真圖 3.7原理圖 第四章 減小誤差措施及擴展方面 4.1減小誤差措施 4.2擴展方面 (1)預處理電路部分 (2)增加電源部分 4.3 功能上的完善 4.3.1 增加鍵盤控制 4.3.2 實現自動量程轉換 4.3.3 液晶顯示器(LCD)進行數據的顯示 總結 致謝詞 參考文獻
前 言頻率是電子技術領域的一個基本參數,同時也是一個非常重要的參數,因此,頻率測量已成為電子測量領域最基本最重要的測量之一。 隨著科學技術的不斷發展提高,人們對科技產品的要求也相應的提高,數字化的電子產品越來越受到歡迎。頻率計作為比較常用和實用的電子測量儀器,廣泛應用于科研機構、學校、家庭等場合,因此它的重要性和普遍性勿庸質疑。數字頻率計具有體積小、攜帶方便;功能完善、測量精度高等優點,因此在以后的時間里,必將有著更加廣闊的發展空間和應用價值。比如:將數字頻率計稍作改進,就可制成既可測頻率,又能測周期、占空比、脈寬等功能的多用途數字測量儀器。將數字頻率計和其他電子測量儀器結合起來,制成各種智能儀器儀表,應用于航空航天等科研場所,對各種頻率參數進行計量;應用在高端電子產品上,對其中的頻率參數進行測量;應用在機械器件上,對機器振動產生的噪聲頻率進行監控;等等。研究數字頻率計的設計和開發,有助于頻率計功能的不斷改進、性價比的提高和實用性的加強。以前的頻率計大多采用TTL數字電路設計而成,其電路復雜、耗電多、體積大、成本高。隨后大規模專用IC(集成電路)出現,如ICM7216,ICM7226頻率計專用IC,使得頻率計開發設計變得簡單,但由于價格較高,因此利用IC設計數字頻率計的較少。現在,單片機技術發展非常迅速,采用單片機來實現數字頻率計的開發設計,實現頻率的測量,不但測量準確,精度高,而且誤差也很小。我們將介紹一種簡單、實用的基于單片機的數字頻率計的設計和制作。 第一章 總體設計方案以AT89C51單片機為核心,起著控制作用。系統包括LCD1602液晶顯示電路、復位電路、時鐘電路。設計思路分為四個模塊:復位電路、晶振電路模塊、AT89C51、LCD1602液晶顯示電路。 1.1 總設計框圖
圖1-1-1 總設計框圖 1.2 硬件設計分析1.2.1 電源的設計(1):系統電源使用直流5伏。
(2):單片機最小系統 單片機選用型號為AT89C51。 AT89C51是一個低電壓,高性能CMOS 8位單片機,片內含4k bytes的可反復擦寫的Flash只讀程序存儲器和128bytes的隨機存取數據存儲器(RAM),器件采用ATMEL公司的高密度、非易失性存儲技術生產,兼容標準MCS-51指令系統,內置功能強大的微型計算機的AT89C51提供了高性價比的解決方案。 如圖1-2-3所示為AT89C51單片機基本構造,其基本性能介紹如下: 圖1-2-3 AT89C51單片機 AT89C51本身內含40個引腳,32個外部雙向輸入/輸出(I/O)端口,同時內含2個外中端口,3個16位可編程定時計數器,2個全雙工串行通信口,AT89C51可以按照常規方法進行編程,但不可以在線編程。其將通用的微處理器和Flash存儲器結合在一起,特別是可反復擦寫的Flash存儲器可有效地降低開發成本。 AT89C51的主要特性如下表所示: 表1-2-1 AT89C51主要功能描述 AT89C51為40腳雙列直插封裝的8位通用微處理器,采用工業標準的C51內核,在內部功能及管腳排布上與通用的8xc51相同,其主要用于會聚調整時的功能控制。功能包括對會聚主IC內部寄存器、數據RAM及外部接口等功能部件的初始化,會聚調整控制,會聚測試圖控制,紅外遙控信號IR的接收解碼及與主板CPU通信等。主要管腳有:XTAL1(19腳)和XTAL2(18腳)為振蕩器輸入輸出端口,外接12MHz 晶振。RST/Vpd(9腳)為復位輸入端口,外接電阻電容組成的復位電路。VCC(40腳)和VSS(20腳)為供電端口,分別接+5V電源的正負端。P0~P3 為可編程通用I/O腳,其功能用途由軟件定義,在本設計中,P0端口(32~39腳)被定義為N1功能控制端口,分別與N1的相應功能管腳相連接,13腳定義為IR輸入端,10腳和11腳定義為I2C總線控制端口,分別連接N1的SDAS(18腳)和SCLS(19腳)端口,12腳、27腳及28腳定義為握手信號功能端口,連接主板CPU的相應功能端,用于當前制式的檢測及會聚調整狀態進入的控制功能。 P0口:P0口是一組8位漏極開路型雙向I/O 口,也即地址/數據總線復用口。作為輸出口用時,每位能吸收電流的方式驅動8個TTL邏輯門電路,對端口P0寫“1”時,可作為高阻抗輸入端用。在訪問外部數據存儲器或程序存儲器時,這組口線分時轉換地址(低8位)和數據總線復用,在訪問期間激活內部上拉電阻。在Flash 編程時,P0口接收指令字節,而在程序校驗時,輸出指令字節,校驗時,要求外接上拉電阻。 P1口:P1是一個帶內部上拉電阻的8位雙向I/O口,P1的輸出緩沖級可驅動(吸收或輸出電流)4個TTL邏輯門電路。對端口寫“1”,通過內部的上拉電阻把端口拉到高電平,此時可作輸入口。作輸入口使用時,因為內部存在上拉電阻,某個引腳被外部信號拉低時會輸出一個電流(IIL)。與AT89C51不同之處是,P1.0和P1.1還可分別作為定時/計數器2 的外部計數輸入(P1.0/T2)和輸入(P1.1/T2EX)。Flash編程和程序校驗期間,P1接收低8位地址。 P2口:P2是一個帶有內部上拉電阻的8 位雙向I/O口,P2的輸出緩沖級可驅動(吸收或輸出電流)4個TTL邏輯門電路。對端口P2寫“1”,通過內部的上拉電阻把端口拉到高電平,此時可作輸入口,作輸入口使用時,因為內部存在上拉電阻,某個引腳被外部信號拉低時會輸出一個電流(IIL)。在訪問外部程序存儲器或16位地址的外部數據存儲器(例如執行MOVX @DPTR指令)時,P2口送出高8位地址數據。在訪問8位地址的外部數據存儲器(如執行MOVX @RI指令)時,P2口輸出P2鎖存器的內容。Flash編程或校驗時,P2亦接收高位地址和一些控制信號。 P3口:P3口是一組帶有內部上拉電阻的8位雙向I/O口。P3口輸出緩沖級可驅動(吸收或輸出電流)4個TTL邏輯門電路。對P3口寫入“1”時,它們被內部上拉電阻拉高并可作為輸入端口。此時,被外部拉低的P3口將用上拉電阻輸出電流(IIL)。P3口除了作為一般的I/O口線外,更重要的用途是它的第二功能P3口還接收一些用于Flash 閃速存儲器編程和程序校驗的控制信號。 RST:復位輸入。當振蕩器工作時,RST引腳出現兩個機器周期以上高電平將使單片機復位。 ALE/PROG:當訪問外部程序存儲器或數據存儲器時,ALE(地址鎖存允許)輸出脈沖用于鎖存地址的低8位字節。一般情況下,ALE仍以時鐘振蕩頻率的1/6輸出固定的脈沖信號,因此它可對外輸出時鐘或用于定時目的。要注意的是:每當訪問外部數據存儲器時將跳過一個AL脈沖。對Flash存儲器編程期間,該引腳還用于輸入編程脈沖(PROG)。如有必要,可通過對特殊功能寄存器(SFR)區中的8EH單元的D0位置位,可禁止ALE操作。該位置位后,只有一條 MOVX 和MOVC指令才能將ALE激活。此外,該引腳會被微弱拉高,單片機執行外部程序時,應設置ALE禁止位無效。 PSEN:程序儲存允許(PSEN)輸出是外部程序存儲器的讀選通信號,當AT89C51由外部程序存儲器取指令(或數據)時,每個機器周期兩次PSEN有效,即輸出兩個脈沖。在此期間,當訪問外部數據存儲器,將跳過兩次PSEN信號。 EA/VPP:外部訪問允許。欲使CPU僅訪問外部程序存儲器(地址為0000H—FFFFH),EA端必須保持低電平(接地)。需注意的是:如果加密位LB1被編程,復位時內部會鎖存EA端狀態。如EA端為高電平(接Vcc端),CPU則執行內部程序存儲器中的指令。Flash存儲器編程時,該引腳加上+12V的編程允許電源Vpp,當然這必須是該器件是使用12V編程電壓Vpp。 XTAL1:振蕩器反相放大器的及內部時鐘發生器的輸入端。 XTAL2:振蕩器反相放大器的輸出端。 單片機最小原理圖如圖1-2-4所示。 圖1-2-4 單片機最小系統 單片機最小系統說明: 時鐘信號的產生:在MCS-51芯片內部有一個高增益反相放大器,其輸入端為芯片引腳XTAL1,其輸出端為引腳XTAL2。而在芯片的外部,XTAL1和XTAL2之間跨接晶體振蕩器和微調電容,從而構成一個穩定的自激振蕩器,這就是單片機的時鐘振蕩電路。 時鐘電路產生的振蕩脈沖經過觸發器進行二分頻之后,才成為單片機的時鐘脈沖信號。 一般地,電容C1和C2取30pF左右,晶體的振蕩頻率范圍是1.2-12MHz。如果晶體振蕩頻率高,則系統的時鐘頻率也高,單片機的運行速度也就快。 單片機復位使CPU和系統中的其他功能部件都處在一個確定的初始狀態下,并從這個狀態開始工作。單片機復位條件:必須使9腳加上持續兩個機器周期(即24個振蕩周期)的高電平。 (3):顯示系統 LCD1602分為帶背光和不帶背光兩種,基控制器大部分為HD44780,帶背光的比不帶背光的厚,是否帶背光在應用中并無差別,兩者尺寸差別如下圖1-2-5所示:
LCD1602的主要技術參數: 1、顯示容量:16×2個字符 2、芯片工作電壓:4.5—5.5V 3、工作電流:2.0mA(5.0V) 4、模塊最佳工作電壓:5.0V 5、字符尺寸:2.95×4.35(W×H)mm 引腳功能說明 LCD1602采用標準的14腳(無背光)或16腳(帶背光)接口,各引腳接口說明如圖1-2-6所示:
編號 | 符號 | 引腳說明 | 編號 | 符號 | 引腳說明 | 1 | VSS | 電源地 | 9 | D2 | 數據 | 2 | VDD | 電源正極 | 10 | D3 | 數據 | 3 | VL | 液晶顯示偏壓 | 11 | D4 | 數據 | 4 | RS | 數據/命令選擇 | 12 | D5 | 數據 | 5 | R/W | 讀/寫選擇 | 13 | D6 | 數據 | 6 | E | 使能信號 | 14 | D7 | 數據 | 7 | D0 | 數據 | 15 | BLA | 背光源正極 | 8 | D1 | 數據 | 16 | BLK | 背光源負極 |
圖1-2-1:引腳接口說明表 第1腳:VSS為地電源。 第2腳:VDD接5V正電源。 第3腳:VL為液晶顯示器對比度調整端,接正電源時對比度最弱,接地時對比度最高,對比度過高時會產生“鬼影”,使用時可以通過一個10K的電位器調整對比度。 第4腳:RS為寄存器選擇,高電平時選擇數據寄存器、低電平時選擇指令寄存器。 第5腳:R/W為讀寫信號線,高電平時進行讀操作,低電平時進行寫操作。當RS和R/W共同為低電平時可以寫入指令或者顯示地址,當RS為低電平R/W為高電平時可以讀忙信號,當RS為高電平R/W為低電平時可以寫入數據。 第6腳:E端為使能端,當E端由高電平跳變成低電平時,液晶模塊執行命令。 第7~14腳:D0~D7為8位雙向數據線。 第15腳:背光源正極。 第16腳:背光源負極。 (4):LCD1602的指令說明及時序1602液晶模塊內部的控制器共有11條控制指令,如圖1-2-7所示:
序號 | 指令 | RS | R/W | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | 1 | 清顯示 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 2 | 光標返回 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | * | 3 | 置輸入模式 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | I/D | S | 4 | 顯示開/關控制 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | D | C | B | 5 | 光標或字符移位 | 0 | 0 | 0 | 0 | 0 | 1 | S/C | R/L | * | * | 6 | 置功能 | 0 | 0 | 0 | 0 | 1 | DL | N | F | * | * | 7 | 置字符發生存貯器地址 | 0 | 0 | 0 | 1 | 字符發生存貯器地址 | 8 | 置數據存貯器地址 | 0 | 0 | 1 | 顯示數據存貯器地址 | 9 | 讀忙標志或地址 | 0 | 1 | BF | 計數器地址 | 10 | 寫數到CGRAM或DDRAM) | 1 | 0 | 要寫的數據內容 | 11 | 從CGRAM或DDRAM讀數 | 1 | 1 | 讀出的數據內容 |
1602液晶模塊的讀寫操作、屏幕和光標的操作都是通過指令編程來實現的。(說明:1為高電平、0為低電平) 指令1:清顯示,指令碼01H,光標復位到地址00H位置。 指令2:光標復位,光標返回到地址00H。 指令3:光標和顯示模式設置I/D:光標移動方向,高電平右移,低電平左移S:屏幕上所有文字是否左移或者右移。高電平表示有效,低電平則無效。 指令4:顯示開關控制。D:控制整體顯示的開與關,高電平表示開顯示,低電平表示關顯示C:控制光標的開與關,高電平表示有光標,低電平表示無光標B:控制光標是否閃爍,高電平閃爍,低電平不閃爍。 指令5:光標或顯示移位S/C:高電平時移動顯示的文字,低電平時移動光標。 指令6:功能設置命令DL:高電平時為4位總線,低電平時為8位總線 N:低電平時為單行顯示,高電平時雙行顯示F: 低電平時顯示5x7的點陣字符,高電平時顯示5x10的點陣字符。 指令7:字符發生器RAM地址設置。 指令8:DDRAM地址設置。 指令9:讀忙信號和光標地址BF:為忙標志位,高電平表示忙,此時模塊不能接收命令或者數據,如果為低電平表示不忙。 指令10:寫數據。 指令11:讀數據。 (5): LCD1602的RAM地址映射及標準字庫表 液晶顯示模塊是一個慢顯示器件,所以在執行每條指令之前一定要確認模塊的忙標志為低電平,表示不忙,否則此指令失效。要顯示字符時要先輸入顯示字符地址,也就是告訴模塊在哪里顯示字符,圖2-2-6是1602的內部顯示地址。
例如第二行第一個字符的地址是40H,那么是否直接寫入40H就可以將光標定位在第二行第一個字符的位置呢?這樣不行,因為寫入顯示地址時要求最高位D7恒定為高電平1所以實際寫入的數據應該是01000000B(40H)+10000000B(80H)=11000000B(C0H)。 在對液晶模塊的初始化中要先設置其顯示模式,在液晶模塊顯示字符時光標是自動右移的,無需人工干預。每次輸入指令前都要判斷液晶模塊是否處于忙的狀態。 1602液晶模塊內部的字符發生存儲器(CGROM)已經存儲了160個不同的點陣字符圖形,這些字符有:阿拉伯數字、英文字母的大小寫、常用的符號、和日文假名等,每一個字符都有一個固定的代碼,比如大寫的英文字母“A”的代碼是01000001B(41H),顯示時模塊把地址41H中的點陣字符圖形顯示出來,我們就能看到字母“A”。 
圖1-2-9 液晶顯示電路
3.6仿真圖
 3.7原理圖
3.8元件清單
第四章 減小誤差措施及擴展方面4.1減小誤差措施(1)選用頻率較高和穩定性好晶振。如選24KHZ的晶振可使測量范圍擴大,穩定性好的晶振可以減小誤差。 (2)測量頻率低的信號時,可適當調整程序,延長門限時間,減少原理上±1的相對誤差。 (3)測量頻率高的信號時,可先對信號進行分頻,在進行測量。 4.2擴展方面(1)預處理電路部分 在實際工作中,如若兩級NPN放大管仍不能使放大作用明顯,則可以再級聯一個NPN放大管;或者采用放大能力更強的三極管或CMOS管代替。后一種思路雖然在價格上有所增加,但卻減少了電路的復雜程度,并且在電路板一旦出現問題時,能盡最大可能的減少元器件的更換和連接線路的修改,非常方便和實用。 (2)增加電源部分 在上面數字頻率計的設計工程中,使用的是外部干電池電源對單片機和其他電路供電,操作起來很方便,但有一個缺點是外部提供的電源準確度不是很高。比如,單片機需要提供5V的標準電壓,我們使用的干電池,由于使用時間過久或型號不同而使得提供的電壓達不到5V或高于5V,這樣使得電路不能在正常的狀態下工作或損壞元器件。因此在原理圖中,我們可以加入電源部分,采用元件7805或7809和整流電路對外來電壓進行整流、限壓,提供標準的5V電壓給電路,這樣就增加了硬件電路的穩定性和測試的準確性。 4.3 功能上的完善4.3.1 增加鍵盤控制通過按鍵實現數字頻率計的測頻率,周期,占空比,脈寬等各項功能。按不同的鍵起到不同的作用,也就是完成不同的功能。還可以根據按鍵數的多少來選擇不同的鍵盤。所以我們可以從實際操作中知道鍵盤的擴展是非常方便的。 4.3.2 實現自動量程轉換在測量頻率時,軟件編程也可以實現頻率測量量程的自動轉換。頻率計每個工作循環開始時使用計數方法實現頻率測量,測量完后判斷測量結果是否具有2位有效數字,如果成立,將結果送去顯示,本工作循環結束;否則將計數閘門寬度依次擴大10倍,繼續進行測量判斷,直到計數閘門寬度達到1s,這時對應的頻率測量范圍為100Hz~999Hz。如果測量結果仍不具有2位有效數字,頻率計則使用定時方法實現頻率測量。 4.3.3 液晶顯示器(LCD)進行數據的顯示LED顯示管只能顯示0~9和一些簡單的英文字母,頻率計的功能就受到極大的限制,而LCD顯示管能夠解決LED的不足,增強顯示功能。LCD具有體積小、低耗電量、無輻射危險,平面直角顯示以及影像穩定不閃爍等優勢,因此廣泛應用于各種儀表設備中去。LCD顯示器主要有字符型和點陣型兩種。 總結系統的分析與設計過程也是對學習的總結過程,更是進一步學習和探索的過程。在這過程中,我對利用可編程控制器進行控制系統的設計與開發有了深刻的的認識,對機械手的工作原理有了進一步的掌握,對控制系統的分析與設計有了切身的認識和體會,并在學習和實踐過程中增長了知識,豐富了經驗。控制系統的開發設計是一項復雜的系統工程,必須嚴格按照系統分析、系統設計、系統實施、系統運行與調試的過程來進行。系統的分析與設計是一項很辛苦的工作,同時也是一個充滿樂趣的過程。在設計過程中,要邊學習,邊實踐,遇到新的問題就不斷探索和努力,即可使問題得到解決。 同時,在本次設計中,也深刻體會到理論和實踐相集合的重要性。雖然之前收集了大量的資料但在實際應用中卻有很大差異,出現了許多意想不到的問題。但經過長時間的摸索最終還是設計出達到要求的系統。由于時間緊迫,有些設計工作還有待完善,在以后的工作中我會繼續努力,不斷提高自己的技術水平,以適應未來的激烈競爭形勢。 致謝詞畢業,意味著一個人一個階段學習生涯的結束。在大學里,畢業論文是宣告這一事實的標準。從大一到現在三年的學習三年的磨練,在此刻沉淀成一篇畢業論文。 通過這次畢業設計,使我得到了一次用專業知識、專業技能分析和解決問題的全面系統的鍛煉。我學到了很多書本上學不到的實踐知識,尤其對電子硬件、電路設計有了更深刻的理解,了解了設計一個產品從方案的選擇到最終產品的一系列的設計階段,了解了產品的調試技術。使我真正體會到理論和實踐相結合的重要性。 在此有無數感謝。 首先,感謝我的父母。是他們教會我做人做事的道理,他們的諄諄教導是.我前進的強大動力和堅實后盾。 感謝大學三年里教育過我的老師, 那些曾經的歲月,曾經的年華,我們一起走過的路。 感謝我的同學。無論是教室里的如切如磋,餐桌旁的高談闊論。還是寢室里的歡聲笑語,都留下了我們最美好的回憶。這是我最寶貴的財富之一。 當然,這里更要感謝的是xxx老師,他是我這次畢業設計的指導老師。衷心的感謝他在這段時間對我的幫助和對我的教導。任老師的言傳身教我將謹記遵循,他淵博的學識和嚴謹的治學態度將是我收益終生。 最后感謝各位評委和答辯老師在百忙之中抽出時間來親自檢閱我的畢業設計。 - 2.2 各部分軟件分析
- 2.2.1 定時器0中斷子函數
- void t0() interrupt 1 using 1
- {
-
- }
- 2.2.2 定時器1中斷子函數
- void t1() interrupt 3 using 3//定時器T1中斷服務程序
- {
- if(num==3999)
- {
- GATE=0;
- TR0=0;
- TR1=0;
- aaa=TH0*256+TL0;
- bbb=P1;
- d=c/100.0;
- c=0;
- e=f;
- f=1;
- CLR=1;
- CLR=0;
- TH0=0x00;
- TL0=0x00;
- TH1=0x06;
- TL1=0x06;
- num=0;
- GATE=1;
- TR0=1;
- TR1=1;
- }
- else
- num++;
- }
- 2.2.3 主函數
- void main()//主函數
- {
- unsigned long a=0;
- bit b=0;
- uchar tab[10];
- uint temp=0;
- LCD_init();
- init();
- LCD_sfj1(0,0);
- LCD_print("Welcome to use ");
- LCD_sfj1(0,1);
- LCD_print("Please Wating...");
- delay3();
- LCD_write(0,0x01);
- while(1)
- {
- if(K1==0)
- {
- delay2(10);
- if(K1==0)
- {
- while(K1==0);
- b=~b;
- LCD_write(0,0x01);
- }
- }
- temp=fenjie(0);
- if(temp>c)
- c=temp;
- if(temp>c>>3&&temp<c>>1)
- f=0;
- if(b==0)
- {
- a=(aaa*256)+bbb;
- if(a==0)
- {
- LCD_sfj1(0,0);
- LCD_print("F= 0000000000 Hz");
- LCD_sfj1(0,1);
- LCD_print("F= 0000000000 Hz");
- }
- else
- {
- LCD_sfj1(0,0);
- LCD_print("F= Hz");
- sprintf(tab,"%ld",a);
- LCD_sfj1(2,0);LCD_print(tab);
- LCD_sfj1(0,1);
- LCD_print("P= ms");
- sprintf(tab,"%0.6f",1000.0/a);
- LCD_sfj1(2,1);
- LCD_print(tab);
- }
- }
- else
- {
- sprintf(tab,"%bd",e);
- LCD_sfj1(0,0);
- LCD_print(tab);
- sprintf(tab,"Upp=%0.3fV",d);
- LCD_sfj1(0,1);
- LCD_print(tab);
- }
- }
- }
- 2.3 總源程序
- #include<reg51.h>
- #include<stdio.h>
- #include<intrins.h>
- typedef unsigned char uchar;
- typedef unsigned int uint;
- sbit RS=P2^5;
- sbit RW=P2^6;
- sbit E=P2^7;
- sbit CLK=P2^0;
- sbit DO=P2^1;
- sbit DI=P2^1;
- sbit CS=P2^2;
- sbit CLR=P3^0;
- sbit GATE=P3^1;
- sbit K1=P3^7;
- uint num=0;
- uint c=0;
- float d=0;
- uchar e=1,f=1;
- unsigned long int aaa=0,bbb=0;
- uchar LCD_wait()//LCD1602內部等待函數
- {
- RS=0;
- RW=1;
- _nop_();
- E=1;
- _nop_();
- E=0;
- return P0;
- }
- void LCD_write(bit aa,uchar bb)//向LCD寫入命令或數據
- {
- E=0;
- RS=aa;
- RW=0;
- _nop_();
- P0=bb;
- _nop_();//注意順序
- E=1;
- _nop_();//注意順序
- E=0;
- _nop_();
- LCD_wait();//LCD1602內部等待函數
- }
- void LCD_display(uchar temp)
- {
- LCD_write(0,0x08|temp);
- }
- void LCD_input(uchar cc)
- {
- LCD_write(0,0x04|cc);
- }
- void LCD_init()//初始化LCD
- {
- E=0;
- LCD_write(0,0x38);//8位數據端口,2行顯示,5*7點陣
- LCD_write(0,0x38);
- LCD_display(0x04|0x00);//開啟顯示, 無光標
- LCD_write(0,0x01);//清屏
- LCD_input(0x02|0x00);//AC遞增,畫面不動
- }
- void LCD_sfj1(uchar x,uchar y)
- {
- if(y==0)
- LCD_write(0,0x80|x);
- if(y==1)
- LCD_write(0,0x80|(x-0x40));
- }
- void LCD_print(uchar *p)
- {
- while(*p!='\0')
- {
- LCD_write(1,*p);
- p++;
- }
- }
- void delay1(uchar x)//ms延時子函數
- {
- uchar i;
- for(i=0;i<x;i++); //延時,脈沖一位持續的時間
- }
- uchar start(bit temp) //把模擬電壓值轉換成8位二進制數并返回,dat為通道選擇。
- {
- uchar i,aa=0;
- CS=0;
- DO=0;//片選,DO為高阻態
- delay1(10);
- CLK=0;
- delay1(2);
- DI=1;
- CLK=1;
- delay1(2);//第一個脈沖,起始位
- CLK=0;
- delay1(2);
- DI=1;
- CLK=1;
- delay1(2);//第二個脈沖,DI=1表示雙通道單極性輸入
- CLK=0;
- delay1(2);
- DI=temp; /*******************************/
- CLK=1;
- delay1(2);//第三個脈沖,DI=1表示選擇通道1(CH2)
- DI=0;
- DO=1;//DI轉為高阻態,DO脫離高阻態為輸出數據作準備
- CLK=1;
- delay1(2);
- CLK=0;
- delay1(2);//經實驗,這里加一個脈沖AD便能正確讀出數據,
- //不加的話讀出的數據少一位(最低位d0讀不出)
- for(i=0;i<8;i++)
- {
- CLK=1;
- delay1(2);
- CLK=0;
- delay1(2);
- aa=(aa<<1)|DO;//在每個脈沖的下降沿DO輸出一位數據,最終ch為8位二進制數
- }
- CS=1;//取消片選,一個轉換周期結束
- return(aa);//把轉換結果返回
- }
- uint fenjie(bit cc)
- {
- uchar dd;
- uint ee;
- dd=start(cc);
- ee=(uint)dd*100/51; //51是由5/255的倒數得來的,5是5V,255是8位AD。
- return(ee);
- }
- void delay2(uint z)//按鍵消抖
- {
- uint x;
- uchar y;
- for(x=0;x<z;x++)
- for(y=0;y<110;y++);
- }
- void delay3()//1s延時子函數
- {
- uchar h,i,j,k;
- for(h=5;h>0;h--)
- for(i=4;i>0;i--)
- for(j=116;j>0;j--)
- for(k=214;k>0;k--);
- }
- //定時計數初始化
- void init()
- {
- TMOD=0x25; // T0計數,T1定時
- TH0=0x00;
- TL0=0x00;
- TH1=0x06;
- TL1=0x06;
- CLR=1;
- CLR=0;
- GATE=0;
- GATE=1;
- ET0=1;
- ET1=1;
- EA=1;
- TR0=1;
- TR1=1;
- }
- void main()//主函數
- {
- unsigned long a=0;
- bit b=0;
- uchar tab[10];
- uint temp=0;
- LCD_init();
- init();
- LCD_sfj1(0,0);
- LCD_print("Welcome to use ");
- LCD_sfj1(0,1);
- LCD_print("Please Wating...");
- delay3();
- LCD_write(0,0x01);
- while(1)
- {
- if(K1==0)
- {
- delay2(10);
- if(K1==0)
- {
- while(K1==0);
- b=~b;
- LCD_write(0,0x01);
- }
- }
- temp=fenjie(0);
- if(temp>c)
- c=temp;
- if(temp>c>>3&&temp<c>>1)
- f=0;
- if(b==0)
- {
- a=(aaa*256)+bbb;
- if(a==0)
- {
- LCD_sfj1(0,0);
- LCD_print("F= 0000000000 Hz");
- LCD_sfj1(0,1);
- LCD_print("F= 0000000000 Hz");
- }
- else
- {
- LCD_sfj1(0,0);
- LCD_print("F= Hz");
- sprintf(tab,"%ld",a);
- LCD_sfj1(2,0);LCD_print(tab);
- LCD_sfj1(0,1);
- LCD_print("P= ms");
- sprintf(tab,"%0.6f",1000.0/a);
- LCD_sfj1(2,1);
- LCD_print(tab);
- }
- }
- else
- {
- sprintf(tab,"%bd",e);
- LCD_sfj1(0,0);
- LCD_print(tab);
- sprintf(tab,"Upp=%0.3fV",d);
- LCD_sfj1(0,1);
- LCD_print(tab);
- }
- }
- }
- void t0() interrupt 1 using 1
- {
-
- }
- void t1() interrupt 3 using 3//定時器T1中斷服務程序
- {
- if(num==3999)
- {
- GATE=0;
- TR0=0;
- TR1=0;
- aaa=TH0*256+TL0;
- bbb=P1;
- d=c/100.0;
- c=0;
- e=f;
- f=1;
- CLR=1;
- CLR=0;
- TH0=0x00;
- TL0=0x00;
- TH1=0x06;
- TL1=0x06;
- num=0;
- GATE=1;
- TR0=1;
- TR1=1;
- }
- else
- num++;
- }
復制代碼
完整的Word格式文檔51黑下載地址:
http://www.zg4o1577.cn/bbs/dpj-115872-1.html
|