水位AD檢測
摘要 1
1、概述 2
2、系統主要器件選擇介紹 3
2.1 方案論證 3
2.2系統介紹 5
2.3 STC89c52單片機 5
2.4 壓力傳感器 9
2.5 ADC0832 9
2.6 1602液晶 12
3、系統電路設計 15
3.1 最小系統電路設計 15
3.2 1602顯示電路設計 15
3.3 電磁繼電器電路設計如下:圖11 15
3.4 壓力傳感器采集電路設計如下;圖12 16
3.5 蜂鳴器電路設計如下;圖13 16
4、 系統程序設計 17
4.1系統程序程圖設計如下;圖13 17
4.2壓力傳感器采集顯示程序流程圖設計 17
4.3按鍵程序流程圖設計 18
5、結論 19
致 謝 19
附錄1 20
附錄2 22
附錄3:源程序 23
摘要
該系統以STC89c52單片機為控制核心設計的水位檢測裝置,該系統主要有單片機最小系統、按鍵模塊、1602液晶顯示模塊、壓力傳感器模塊、電磁繼電器驅動模塊和ADC0832組成。STC89c52系列單片機內部自帶資源豐富、運算速度較快,適用于強干擾和要求速度較高的場合。以電磁繼電器開環控制和壓力傳感器閉環實現對該系統的控制,達到系統的穩定可靠
1、概述
液位檢測在許多控制領域已較為普遍,各種類型的液位檢測傳感器較多,按原理分有浮子式、壓力式、超聲波式、吹氣式等。各種方式都根據其需要設計完成,其結構、量程和精度適用于各自不同的場合,大多結構較為復雜,制造成本偏高;市面上也有現成的液位計,有投入式、浮球式、彈簧式等,多數成品價格偏高。以上液位計多數輸出為模擬量電流或電壓,有些為機械指針讀數,不能用于遠程監視;普遍適用于靜止液面,在波動液面易引起讀數的波動;也有用電容法測液位的系統,此法是一種簡單易行的方案。本文利用壓力傳感器測液體壓力的原理,結合單片機設計出一種智能液位監控器。
本設計是在學完有關單片機系統和傳感器相關課程的基礎上,為了能更好的掌握這些課程的內容,把理論應用于實際而提出來的。旨在發揮我們的設計,創新意識。通過本課程設計可以掌握和鞏固傳感器的基本設計方法,工業水位的測量方法,單片機的基本應用,顯示電路的連接等知識。進一步加強對課堂理論知識的理解與綜合應用能力,從而提高我們解決問題的能力和創造發明能力。
如今傳感器的應用是非常的廣泛,并且已經融入到我們的生活、工作、科研等領域中。在進行設計中首先對壓力傳感器輸出的電壓和對應的液體高度進行整理和多次測量得出一個比較與實際高度符合的函數。通過壓力傳感器測出液體壓力,利用ADC0832芯片對壓力傳感器的輸出電壓進行采集并將模擬電壓信號轉換成數字電平信號0,1。
液位監控器的應用雖然非常廣泛,但是現在高精度的液位監控器的價格非常貴,實現民用還有一定的難度。所以我們的設計應更加創新利用更小的成本設計生產出更好的傳感器。
2、系統主要器件選擇介紹
2.1 方案論證
(1)主控器件的比較與選擇
方案一:采用ARM7作為主控器件,雖然速度很快,資源很多,但價格 比較高,資源浪費,缺乏市場競爭力。
方案二:采用SST89C52作為主控器件,雖然該款單片機較便宜,運行 速度較慢,但是運行速度相對而言足夠系統臀形并有富余,也可以對單片機 操作,來完成系統的功能設置,且電機的控制可以增加簡單的外圍電路設計。 單片機就顯現出來它的優勢——控制簡單、方便、快捷。這樣一來,單片機 就可以充分發揮其資源、有較為強大的控制功能及可位尋址操作功能。
綜上所述,為簡化外圍電路設計,提高市場競爭力,我們選擇方案二。
(2)壓力傳感器的比較與選擇
根據壓力的大小可以呈線性的改變輸出的電壓,通過對電壓的采集處理比較,輸出相應的高度值。
方案一:采用橋式壓力傳感器
橋式壓力傳感器是通過應變片的應力變形,當有應力變形時,傳感器會輸出電壓,隨著中立重力的加大輸出電壓會出現線性變化。但是由于橋式壓力傳感器,應力變形很小,輸出的電壓變化幅度小、電壓值小,所以通AD簡單的外圍電路組成的采集模塊一起使用,是電路簡化,操作方便,易于固定、控制,稱量值精度高。
方案二:采用分立元件搭建一個壓力傳感模塊
采用壓敏電阻和外圍電路搭建一個壓力傳感器,通過放大電路對敏電阻的電 壓放大,有普通的AD采集。該方案容易受到外界干擾,有時甚至檢測不到, 還要用到AD采樣和電壓比較器來處理,這樣加大了電路設計的難度。這樣 的靈敏度不夠,誤差大,功耗大,增加了開發成本。
比較以上兩種方案,方案一占有很大的優勢。這樣不但能準確完成測量, 而且能避免電路的復雜性,因此擬選擇方案一。
(3)AD器件的比較與選擇
方案一:采用12位AD芯片
采用12位AD芯片,分辨率比較高,成本高,但系統用不到那么高的分辨率,資源浪費,缺乏市場競爭力。
方案二:采用8位AD芯片
采用8位AD芯片,分半路256,在0-5v電壓模數轉換時,變量變化1,才有19.53mv的變化,足夠系統的需求。
綜上所述,我們選擇方案二。
(4)水泵驅動電路的比較與選擇
方案一:采用主控器件89C51單片機的定時器1定時中斷,改變IO口的高低電平產生模擬的pwm信號。由于定時器0的根據系統的需要定時產生實時時鐘,用另一個定時器,避免產生干擾。通過簡單地測試,微控制器不斷地進出中斷,占用CPU太多時間,液晶顯示部分、數據處理部分工作效率不高。
方案二:通過驅動繼電器驅動水泵
繼電器可低壓控制高壓,或小電流控制大電流,單片機驅動繼電器很簡單,方便,繼電器另外一端開關反映也很靈敏,使用壽命較長,電流過大的時候不影響、單片機工作。
綜上所述,根據系統的需求,我們選擇方案二。
(5)顯示器件的比較與選擇
顯示模塊現在的技術已經很成熟,是集成LED一些成型的模塊。
方案一:采用1602液晶顯示,1602液晶只能顯示二行,每行16個字符,并且不利于顯示漢字(1個漢字占用2個字節),根據系統的要求,能很好地滿足系統的需要。
方案三:采用12864液晶顯示,12864屏幕大,顯示控制相對復雜,相對功耗大、成本高。
綜上所述,我們選擇方案一。
2.2系統介紹
根據設計內容要求,經仔細分析計算,充分考慮各種因素,制定整體制作方案。整體方案以AT89C51為控制核心,對各傳感器采集數據進行綜合分析,作出相應的處理,保證精確穩定、快速的完成設計任務。系統方框圖如圖1所示。
2.3 STC89c52單片機
STC89C52RC是宏晶科技推出的新一代超強抗干擾、高速、 低功耗的單片機,基于 Intel 標準的 8052,指令代碼完全兼容傳統的 8051 系列單片機,12 時鐘/機器周期和 6 時鐘/機器周期可任意選擇。
主要特性
� 增強型 6 時鐘/機器周期,12 時鐘/機器周期 8051CPU。
� 工作電壓:5.5V - 3.4V(5V 單片機) / 3.8V - 2.0V(3V 單片機) 。
� 工作頻率范圍:0 – 40 MHz,相當于普通的 8051 的 0 ~80 Mhz,實際工作頻率可達到 48MHz。
� 用戶應用程序空間 4K、8K、13K、16K、20K、32K、64K 字節。
� 片上集成 1280 字節、512 字節 RAM。
� 通用 I/O(32/36 個) ,復位后為:P1、P2、P3、P4(PDIP-40 封裝是沒有引出 P4 口的)是準雙向口、弱上拉(普通 8051 傳統 I/O 口) ,P0 口是開漏輸出,作為總線拓展用時,不用加上拉電阻,作為 I/O 口用時,需要加上拉電阻
� 共 3 個 16 位定時器、計數器,其中定時器 0 還可以當成 2 個 8 位定時器使用
� 外部中斷 4 路,下降沿中斷或低電平觸發中斷,Power Down 模式可由外部中斷低電平觸發中斷方式喚醒
� P0
P0 口是一個 8 位漏極開路的雙向 I/O 口。 作
為輸出口,每位能驅動 8 個 TTL 邏輯電平。對 P0
端口寫“1”時,引腳用作高阻抗輸入。
當訪問外部程序和數據存儲器時,P0 口也被
作為低 8 位地址/數據復用。 在這種模式下, P0 具
有內部上拉電阻。
� P1
P1 口是一個具有內部上拉電阻的 8 位雙向
I/O 口, P1 輸出緩沖器能驅動 4 個 TTL 邏輯電
平。 對 P1 端口寫“1”時, 內部上拉電阻把端口拉高,
此時可以作為輸入 口使用。作為輸入使用時,被
外部拉低的引腳由于內部電阻的原因,將輸出電流(IIL) 。
此外,P1.0 和 P1.2 分別作定時器/計數器 2 的外部計數輸入(P1.0/T2)和時器/計數器 2 的觸發輸入
(P1.1/T2EX) 。
引腳號第二功能:
P1.0 T2(定時器/計數器 T2 的外部計數輸入) ,時鐘輸出。
P1.1 T2EX(定時器/計數器 T2 的捕捉/重載觸發信號和方向控制) 。
� P2
P2 口是一個具有內部上拉電阻的 8 位雙向 I/O 口, P2 輸出緩沖器能驅動 4 個 TTL 邏輯電平。 對
P2 端口寫“1”時,內部上拉電阻把端口拉高,此時可以作為輸入口使用。作為輸入使用時,被外部拉低
的引腳由于內部電阻的原因,將輸出電流(IIL) 。在訪問外部程序存儲器或用 16 位地址讀取外部數據存
儲器(例如執行 MOVX @DPTR)時,P2 口送出高八位地址。在這種應用中,P2 口使用很強的內部上拉發
送 1。在使用 8 位地址(如 MOVX @RI)訪問外部數據存儲器時,P2 口輸出 P2 鎖存器的內容。在 flash
編程和校驗時,P2 口也接收高 8 位地址字節和一些控制信號。
� P3
P3 口是一個具有內部上拉電阻的 8 位雙向 I/O 口, p2 輸出緩沖器能驅動 4 個 TTL 邏輯電平。 對
P3 端口寫“1”時,內部上拉電阻把端口拉高,此時可以作為輸入口使用。作為輸入使用時,被外部拉低
的引腳由于內部電阻的原因,將輸出電流(IIL) 。
端口引腳第二功能如表 2-4-1。
表 2-4-1
引腳 第二功能
P3.0 RXD(串行輸入口)
P3.1 TXD(串行輸出口)
P3.2 INT0(外中斷 0)
P3.3 INT1(外中斷 1)
P3.4 T0(定時/計數器 0)
P3.5 T1(定時/計數器 1)
P3.6 WR(外部數據存儲器寫選通)
P3.7 RD(外部數據存儲器讀選通)
� 其他引腳
RST——復位輸入。當振蕩器工作時,RST 引腳出現兩個機器周期以上高電平將使單片機復位。
ALE/PROG——當訪問外部程序存儲器或數據存儲器時,ALE(地址鎖存允許)輸出脈沖用于鎖存地址的低 8 位字節。一般情況下, ALE 仍以時鐘振蕩頻率的 1/6 輸出固定的脈沖信號, 因此它可對外輸出時鐘或用于定時目的。要注意的是:每當訪問外部數據存儲器時將跳過一個 ALE 脈沖。對 FLASH 存儲器編程期間,該引腳還用于輸入編程脈沖(PROG) 。如有必要,可通過對特殊功能寄存器(SFR)區中的 8EH 單元的 D0 位置位,可禁止 ALE 操作。該位置位后,只有一條 MOVX 和 MOVC 指令才能將 ALE 激活。此外,該引腳會被微弱拉高,單片機執行外部程序時,應設置 ALE 禁止位無效。
PSEN——程序儲存允許(PSEN)輸出是外部程序存儲器的讀選通信號,當 AT89C52 由外部程序存儲器取指令(或數據)時,每個機器周期兩次 PSEN 有效,即輸出兩個脈沖,在此期間,當訪問外部數據存儲器,將跳過兩次 PSEN 信號。EA/VPP——外部訪問允許,欲使 CPU 僅訪問外部程序存儲器(地址為 0000H-FFFFH) ,EA端必須保持低電平(接地) 。需注意的是:如果加密位 LB1 被編程,復位時內部會鎖存EA端狀態。如EA端為高電平(接 Vcc 端) ,CPU 則執行內部程序存儲器的指令。
2.4 壓力傳感器
壓力傳感器是通過應變片的應力變形,當有應力變形時,傳感器會輸出電壓,隨著中立重力的加大輸出電壓會出現線性變化。但是由于橋式稱重壓力傳感器,應力變形很小,輸出的電壓變化幅度小、電壓值小,所以通過8位AD芯片ADC0832和簡單的外圍電路組成的采集模塊一起使用,是電路簡化,操作方便,易于固定、控制,稱量值精度高。我們選用D3B壓力傳感器。
D3B壓力傳感器工作電壓:4.2v—6.2v;壓力范圍:0-----1000mm水柱,0----0.1Kg/c㎡;電壓輸出:0.23v---4.9v;線性度0.2%;外型:30×30×20mm
I接 5V O接IO口 G接GND
2.5 ADC0832
ADC0832 為 8 位分辨率 A/D 轉換芯片,其最高分辨可達 256 級,可以適應一般的模擬量轉換要求。其內部電源輸入與參考電壓的復用,使得芯片的模擬電壓輸入在 0~5V 之間。芯片轉換時間僅為 32μS,據有雙數據輸出可作為數據校驗,以減少數據誤差,轉換速度快且穩定性能強。獨立的芯片使能輸入,使多器件掛接和處理器控制變的更加方便。通過 DI 數據輸入端,可以輕易的實現通道功能的選擇。 正常情況下 ADC0832 與單片機的接口應為 4 條數據線,分別是 CS、CLK、DO、DI。但由于 DO 端與 DI 端在通信時并未同時有效并與單片機的接口是雙向的,所以電路設計時可以將 DO 和 DI 并聯在一根數據線上使用。
當 ADC0832 未工作時其 CS 輸入端應為高電平,此時芯片禁用,CLK 和 DO/DI 的電平可任意。當要進行 A/D 轉換時,須先將 CS 使能端置于低電平并且保持低電平直到轉換完全結束。此時芯片開始轉換工作,同時由處理器向芯片時鐘輸入端 CLK 輸入時鐘脈沖,DO/DI 端則使用 DI 端輸入通道功能選擇的數據信號。在第 1 個時鐘脈沖的下沉之前 DI 端必須是高電平,表示啟始信號。在第 2、3個脈沖下沉之前 DI 端應輸入 2 位數據用于選擇通道功能,其功能項見表一。與單片機接口電路圖如下:圖2
圖2
如表 1 所示,當此 2 位數據為“1”、“0”時,只對 CH0 進行單通道轉換。當 2 位數據為“1”、“1”時,只對 CH1 進行單通道轉換。當 2 位數據為“0”、“0”時,將 CH0 作為正輸入端 IN+,CH1作為負輸入端 IN-進行輸入。當 2 位數據為“0”、“1”時,將 CH0 作為負輸入端 IN-,CH1 作為正輸入端 IN+進行輸入。
到第 3 個脈沖的下沉之后 DI 端的輸入電平就失去輸入作用,此后 DO/DI 端則開始利用數據輸出 DO 進行轉換數據的讀取。從第 4 個脈沖下沉開始由 DO 端輸出轉換數據最高位 DATA7,隨后每一個脈沖下沉 DO 端輸出下一位數據。直到第 11 個脈沖時發出最低位數據 DATA0,一個字節的數據輸出完成。也正是從此位開始輸出下一個相反字節的數據,即從第 11 個字節的下沉輸出 DATD0。隨后出 8 位數據,到第 19 個脈沖時數據輸出完成,也標志著一次 A/D 轉換的結束。最后將 CS 置高電平禁用芯片,直接將轉換后的數據進行處理就可以了。更詳細的時序說明請見表 2。
2.6 1602液晶
液晶顯示模塊是一個慢顯示器件,所以在執行每條指令之前一定要確認模塊的忙標志為低電平,表示不忙,否則此指令失效。要顯示字符時要先輸入顯示字符地址,也就是告訴模塊在哪里顯示字符,圖3是1602的內部顯示地址。
圖3液晶內部顯示地址
例如第二行第一個字符的地址是40H,那么是否直接寫入40H就可以將光標定位在第二行第一個字符的位置呢?這樣不行,因為寫入顯示地址時要求最高位D7恒定為高電平1所以實際寫入的數據應該是01000000B(40H)+10000000B(80H)=11000000B(C0H)。
在對液晶模塊的初始化中要先設置其顯示模式,在液晶模塊顯示字符時光標是自動右移的,無需人工干預。每次輸入指令前都要判斷液晶模塊是否處于忙的狀態。
1602液晶模塊內部的字符發生存儲器(CGROM)已經存儲了160個不同的點陣字符圖形,如圖10-58所示,這些字符有:阿拉伯數字、英文字母的大小寫、常用的符號、和日文假名等,每一個字符都有一個固定的代碼,比如大寫的英文字母“A”的代碼是01000001B(41H),顯示時模塊把地址41H中的點陣字符圖形顯示出來,我們就能看到字母“A”。
圖4 字符代碼與圖形對應圖
初始化過程如下:圖5
延時15mS
寫指令38H(不檢測忙信號)
延時5mS
寫指令38H(不檢測忙信號)
延時5mS
寫指令38H(不檢測忙信號)
以后每次寫指令、讀/寫數據操作均需要檢測忙信號
寫指令38H:顯示模式設置
寫指令08H:顯示關閉
寫指令01H:顯示清屏
寫指令06H:顯示光標移動設置
寫指令0CH:顯示開及光標設置
圖5:初始化活成(復位過程)
基本操作時序如下:
圖6;讀寫指令
讀操作時許如下:圖7
圖7;讀操作時序圖
寫操作時序如下:圖8
圖8;寫操作時序圖
3、系統電路設計
3.1 最小系統電路設計
最小系統由單片機,P0口上啦排阻,外部時鐘振蕩電路,復位電路組成。如下;圖9
圖9;單片機最小系統電路圖
3.2 1602顯示電路設計
根據1602的數據手冊,1602與單片機的接法如下:圖10
圖10;單片機與1602連接原理圖
3.3 電磁繼電器電路設計如下:圖11
圖11;單片機驅動繼電器原理圖
3.4 壓力傳感器采集電路設計如下;圖12
圖12;壓力傳感器采集原理圖
3.5 蜂鳴器電路設計如下;圖13
圖13;蜂鳴器驅動原理圖
4、系統程序設計
4.1系統程序程圖設計如下;圖13
圖13:主程序流程圖
4.2壓力傳感器采集顯示程序流程圖設計
4.3按鍵程序流程圖設計
5 .1系統功能及指標參數
5.1.1 系統功能
本次設計的智能液位傳感器主要能實現以下功能:
1、壓力傳感器采用的測量液體的壓強的方式來實現測量液面高度;
2、設計的單片機系統能控制ADC對壓力傳感器的輸出電壓信號進行采集并轉換;
3、測量范圍能基本達到設計的要求在0-1米的范圍內誤差較。
4、能在上位機上直觀的顯示出測量的液面高度;
5.2.1 AD部分調試參數
在調通AD后我們對AD的數據采集功能進行了測試,測試數據如下圖5.1:
序號 高度(CM) AD值
1 0 2
2 2 7
3 3 9
4 4 11
5 5 14
6 6 16
7 7 19
8 8 21
9 9 24
10 10 26
11 11 28
12 12 31
13 13 33
14 14 36
15 15 38
16 16 40
17 17 43
18 18 45
19 19 48
20 20 51
21 30 74
22 40 98
23 50 122
24 60 146
25 70 170
26 80 194
27 90 218
28 100 242
圖 5.1 AD的采集數據與給定的輸入數據
這幾組數據都是在室內測得的,都是在室溫接近30度的情況測得。我們對所測得的數據進行了處理,一共測了28組數據(給定的高度讀取ADC0832輸出的AD值),說明AD的線性度還是比較高的。
總結出來公式:水位高度=(AD值-2)/2.4
5.2.3 調試總結
通過調試我們發現調試時最費時間的是考慮很多因素,調試過程要將整個系統組合起來看工作是否正常,能否達到基本的要求。
我們設計的只能液位傳感器能基本滿足設計的基本要求,通過壓力傳感器測量液位的壓強方式,ADC0832對壓力傳感器的輸出的模擬電壓進行采集和轉換送入單片機然后通過液晶屏幕顯示液面的高度。量范圍在0-1米內時誤差能基本滿足要求。誤差主要就是來至壓力傳感器的輸出與ADC0832的輸入有一定的差距。
6、結論
本次設計的智能液位傳感器達到了預期的基本要求,主要特色之一就是直接利用壓力傳感器測液體的壓力的方式實現了測液面的高度,這種方式實現起來比較容易;其二就是將測量系統與PC機相結合起來這樣對數據的讀數比較直觀,并且能精確到厘米。不過此設計也有很多不足之處,測量時要在容器的底部開口才能讀出壓力,還可以加入報警系統,當測量超出范圍時,系統自動報警。還有就是還可以加上一定的數據存儲能力,這樣要對以前的數據進行研究的地方非常有幫助。
致 謝
通過這一階段的努力,我的畢業設計終于完成了,這意味著我的大學生活即將結束。在大學階段,我在學習上和思想上都受益匪淺,這除了自身的努力外,與各位老師、同學和朋友的關心、支持和鼓勵是分不開的。
在本論文的完成過程中,我的指導老師傾注了大量的心血,從選題到開題報告,從寫作提綱到一遍又一遍地指出每稿中的具體問題,嚴格把關,循循善誘,在此我衷心感謝。同時我還要感謝在我學習期間給我極大關心和支持的各位老師以及關心我的同學和朋友。
寫作畢業論文是一次在系統學習的過程,畢業論文的完成,同樣也意味著新的學習生活的開始,我將銘記我曾是一名工大學子,在今后的工作中把工大的優良傳統發揚光大。
感謝各位專家的批評指導。
附錄1
參考文獻
[1] 趙國強,智能臺燈,科學啟蒙,2007, 第Z1期
[2]趙繼文,傳感器與應用電路設計,北京,北京科學出版社,2002.3,6
[3]黃繼昌,電子元器件應用手冊,北京,北京人民郵電出版社, 2004年,5
[4]趙輝,Protel99電子線路CAD,北京,北京郵電大學出版社,2007
[5]畢淑娥,電工與電子技術基礎,哈爾濱,哈爾濱工業大學出版社,2008.6
[6]李全利,單片機原理及應用,北京,清華大學出版社,2006.2
[7]黃長藝,機械工程測試技術基礎,北京:機械工業出版社,2009.3,68-124
[8]金發慶,傳感器技術與應用,北京 : 機械工業出版社, 2004.8,281-290
[9]王港元,電子技能基礎,成都,成都科技大學出版社,1999
[10]熱釋電紅外傳感器,http://baike.baidu.com/view/1788636.htm
[11]光敏電阻,http://baike.baidu.com/view/55997.htm
[12]夏路易,單片機在控制系統中的應用,北京,北京希望電子出版社,2006
[13]李朝青,單片機原理及接口技術,北京,北京航空航天大學出版社,2004
[15] AT89C51 DATA SHEEP Philips Semiconductors 1999.dec
[16]Yang. Y., Yi. J., Woo, Y.Y., and Kim. B.: ‘Optimum design for linearityand efficiency of microwave Doherty amplifier using a new loadmatching technique’, Microw. J., 2001, 44, (12), pp. 20–36
附錄2
系統原理圖
附錄3:源程序
#include<reg52.h> //頭文件
#include<intrins.h>
#include"eeprom52.h" //STC89C52 EEPROM 程序文件
#define uchar unsigned char //宏定義
#define uint unsigned int
#define LCD1602_dat P0 //LCD1602數據口宏定義
sbit LCD1602_rs=P2^5; //LCD1602控制數據IO口
sbit LCD1602_rw=P2^6;
sbit LCD1602_e=P2^7;
sbit beep=P1^4; //蜂鳴器 IO
sbit led_1=P1^6; //LED指示燈 IO
sbit led_2=P1^7;
sbit key_1=P3^0; //系統控制按鍵IO口
sbit key_2=P3^1;
sbit key_3=P3^2;
sbit alarm_1=P2^0; //控制繼電器IO口
sbit ADC0832_CS=P1^2; //ADC0832 控制IO口 使能口
sbit ADC0832_CLK=P1^1; //時鐘IO口
sbit ADC0832_DIO=P1^0; //數據輸入輸出IO口
uint sum; //10次AD值的綜合變量
uchar RH,RH_H=12,RH_L=8,state,ms,cs; //當前水位, 水位上限,下限, 設置項變量,50ms變量 ,cs 為計次數變量 ,
bit beep1,zt,s1; //報警標志位, 工作模式標志位, 閃爍標志位
unsigned int A_D() //ADC0832 讀值程序
{
unsigned char i;
unsigned char dat;
ADC0832_CS=1; //一個轉換周期開始
ADC0832_CLK=0; //為第一個脈沖作準備
ADC0832_CS=0; //CS置0,片選有效
ADC0832_DIO=1; //DIO置1,規定的起始信號
ADC0832_CLK=1; //第一個脈沖
ADC0832_CLK=0; //第一個脈沖的下降沿,此前DIO必須是高電平
ADC0832_DIO=1; //DIO置1, 通道選擇信號
ADC0832_CLK=1; //第二個脈沖,第2、3個脈沖下沉之前,DI必須跟別輸入兩位數據用于選擇通道,這里選通道RH0
ADC0832_CLK=0; //第二個脈沖下降沿
ADC0832_DIO=0; //DI置0,選擇通道0
ADC0832_CLK=1; //第三個脈沖
ADC0832_CLK=0; //第三個脈沖下降沿
ADC0832_DIO=1; //第三個脈沖下沉之后,輸入端DIO失去作用,應置1
ADC0832_CLK=1; //第四個脈沖
for(i=0;i<8;i++) //高位在前
{
ADC0832_CLK=1; //第四個脈沖
ADC0832_CLK=0;
dat<<=1; //將下面儲存的低位數據向右移
dat|=(unsigned char)ADC0832_DIO; //將輸出數據DIO通過或運算儲存在dat最低位
}
ADC0832_CS=1; //片選無效
return dat; //將讀書的數據返回
}
/********************************************************************
* 名稱 : delay()
* 功能 : 小延時。
* 輸入 : 無
* 輸出 : 無
***********************************************************************/
void delay(uint T) //延時函數
{
while(T--);
}
/********************************************************************
* 名稱 : LCD1602_write(uchar order,dat)
* 功能 : 1602寫如數據函數
* 輸入 : 輸入的命令值
* 輸出 : 無
***********************************************************************/
void LCD1602_write(uchar order,dat) //1602 一個字節 處理
{
LCD1602_e=0;
LCD1602_rs=order;
LCD1602_dat=dat;
LCD1602_rw=0;
LCD1602_e=1;
delay(1);
LCD1602_e=0;
}
/********************************************************************
* 名稱 : LCD1602_writebye(uchar *prointer)
* 功能 : 1602寫入數據函數 指針式
* 輸入 : 輸入的命令值
* 輸出 : 無
***********************************************************************/
void LCD1602_writebyte(uchar *prointer) //1602 字符串 處理
{
while(*prointer!='\0')
{
LCD1602_write(1,*prointer);
prointer++;
}
}
/********************************************************************
* 名稱 : LCD1602_cls()
* 功能 : 初始化1602液晶
* 輸入 : 無
* 輸出 : 無
***********************************************************************/
void LCD1602_cls() //1602 初始化
{
LCD1602_write(0,0x01); //1602 清屏 指令
delay(1500);
LCD1602_write(0,0x38); // 功能設置 8位、5*7點陣
delay(1500);
LCD1602_write(0,0x0c); //設置 光標 不顯示開關、不顯示光標、字符不閃爍
LCD1602_write(0,0x06);
LCD1602_write(0,0xd0);
delay(1500);
}
/********************************************************************
* 名稱 : show()
* 功能 : LCD1602液晶顯示程序
* 輸入 : 無
* 輸出 : 無
***********************************************************************/
void show()
{
if(state==0) //當前水位及工作模式顯示
{
LCD1602_write(0,0x80);
LCD1602_writebyte("Water level:"); //當前水位
if(RH>9)LCD1602_write(1,0x30+RH/10%10);
else LCD1602_writebyte(" ");
LCD1602_write(1,0x30+RH%10);
LCD1602_writebyte("cm");
LCD1602_write(0,0xC0);
LCD1602_writebyte("State:"); //工作模式
if(zt==0)
{
LCD1602_writebyte("Manul ");
}else
{
LCD1602_writebyte(" Aoto ");
}
}else //水位上下限設置界面
{
LCD1602_write(0,0x80);
LCD1602_writebyte("Water_H:"); //水位上限
if(state==1&&s1==1) //通過閃爍標志為 達到閃爍的效果
{
LCD1602_writebyte(" ");
}else
{
if(RH_H>9)LCD1602_write(1,0x30+RH_H/10%10);
else LCD1602_writebyte(" ");
LCD1602_write(1,0x30+RH_H%10);
}
LCD1602_writebyte("cm ");
LCD1602_write(0,0xC0);
LCD1602_writebyte("Water_L:"); //水位下限
if(state==2&&s1==1) //通過閃爍標志為 達到閃爍的效果
{
LCD1602_writebyte(" ");
}else
{
if(RH_L>9)LCD1602_write(1,0x30+RH_L/10%10);
else LCD1602_writebyte(" ");
LCD1602_write(1,0x30+RH_L%10);
}
LCD1602_writebyte("cm ");
}
}
/********************************************************************
* 名稱 : key()
* 功能 : 按鍵控制程序 實現系統各個控制功能
* 輸入 : 無
* 輸出 : 無
***********************************************************************/
void key()
{
if(!key_1) //設置按鍵 設置 功能:切換顯示及設置的選項
{
delay(888); //按鍵去抖
if(!key_1) //再次判斷按鍵
{
while(!key_1) show(); //按鍵判斷是否釋放
state=(state+1)%3; //執行按鍵功能 切換設置項
}
}
if(!key_2) //切換設置項值的大小 及非設置模式下切換系統工作模式按鍵
{
delay(888); //按鍵去抖
if(!key_2) //再次判斷按鍵
{
while(!key_2)show(); //按鍵判斷是否釋放
if(state==1) //執行按鍵功能 切換設置項
{
if(RH_H<100)RH_H++; //設置上限值
SectorErase(0x2000); //保存上限值 保存到單片機中EEPROM
byte_write(0x2000,RH_H);
}else if(state==2)
{
if(RH_L<RH_H-1)RH_L++; //設置下限值
SectorErase(0x2200); //保存下限值 保存到單片機中EEPROM
byte_write(0x2200,RH_L);
}else
{
zt=!zt; //切換系統的工作模式 自動 手動
}
}
}
if(!key_3) //切換設置項值的大小 及手動模式下切換系統工作狀態‘開關’
{
delay(888); //按鍵去抖
if(!key_3) //再次判斷按鍵
{
while(!key_3)show(); //按鍵判斷是否釋放
if(state==1) //執行按鍵功能 切換設置項
{
if(RH_H>RH_L+1)RH_H--;
SectorErase(0x2000); //保存上限值 保存到單片機中EEPROM
byte_write(0x2000,RH_H);
}else if(state==2)
{
if(RH_L>0)RH_L--;
SectorErase(0x2200); //保存下限值 保存到單片機中EEPROM
byte_write(0x2200,RH_L);
}else
{
if(zt==0)
{
alarm_1=!alarm_1; //手動模式切換系統的工作狀態
}
}
}
}
}
/********************************************************************
* 名稱 : proc()
* 功能 : 系統處理程序部分
* 輸入 : 無
* 輸出 : 無
***********************************************************************/
void proc()
{
if(zt==1) //zt==1 為自動模式 如果系統在自動模式下
{
if(RH>=RH_H) //如果當前水位值達到水位上限值則
{
alarm_1=1; //關閉繼電器
led_1=0; //顯示對應的指示燈
}else //否則
{
led_1=1; //顯示對應的指示燈
}
if(RH<=RH_L) //如果當前水位值低于水位下限值則
{
alarm_1=0; //開啟繼電器
led_2=0; //顯示對應的指示燈
}else //否則
{
led_2=1; //顯示對應的指示燈
}
if(RH>=RH_H|RH<=RH_L) //蜂鳴器處理部分 如果當前水位超出水位上下限 則
{
beep1=1; //開始報警
}else //否則
{
beep1=0; //停止報警
}
}else
{
beep1=0; //手動模式關閉指示燈及蜂鳴器
led_1=led_2=1;
}
}
void main()
{
float Ad_dat=0;
alarm_1=1; //繼電器狀態初始化
TMOD=0x01; //定時器配置初始化
TH0=0x3c; //16位定時 定時50ms
TL0=0xb0;
ET0=1;
TR0=1; //開啟總中斷 及打開定時器0
EA=1;
LCD1602_cls(); //LCD1602 初始化
RH_H=byte_read(0x2000); //讀取EEPROM中的水位上下限的值
RH_L=byte_read(0x2200);
if((RH_H>99)||(RH_L>99)||(RH_L>=RH_H)) {RH_H=14; RH_L=7;} //如果超出水位上下限設置的范圍,則重新賦值
while(1)
{
if(cs<10) // 濾 //數字濾波器 是ADC0832讀出的值變化幅度小
{
cs++;
sum+=A_D(); // 波 //讀取10次 AD值
}
else // 算
{
cs=0; // 法
Ad_dat=(uchar)(sum/10); //求出當前水位值
//ad_dat1=255-ad_dat1;
if(Ad_dat>2)
{
Ad_dat=(float)((Ad_dat-2)/2.4); //計算水位
RH=(uchar)(Ad_dat);
}
else
RH=0;
sum=0;
}
show(); //調用子程序
key();
proc();
}
}
void UART_1() interrupt 1 //定時器0 中斷
{
TH0=0x3c; //重新賦值
TL0=0xb0;
ms++; //50ms計數
if(ms%5==0) //250ms 計時
{
s1=!s1; //改變閃爍標志為的值
}
if(ms%10==0) //500ms定時
{
if(beep1==1) //蜂鳴器報警處理
{
beep=!beep;
}else
{
beep=1;
}
}
if(ms>19)
{
ms=0;
}
}
|