超聲波液位可控恒溫水浴系統(tǒng)
超聲波液位可控恒溫水浴系統(tǒng),超聲波,可控,恒溫,水浴,系統(tǒng)
華南理工大學(xué)第九屆
智能設(shè)計(jì)控制大賽
初級(jí)組
超聲波液位可控恒溫水浴系統(tǒng)
默默隊(duì):謝銳勇
陳浩權(quán)
林俊彥
目錄
一、引言
1. 超聲波液位可控恒溫水浴系統(tǒng)的現(xiàn)實(shí)意義
二、系統(tǒng)整體設(shè)計(jì)
2.1 整體設(shè)計(jì)方案
2.2水浴箱外形設(shè)計(jì)
三、硬件設(shè)計(jì)方案
3.1 電源
3.2 AT89S52單片機(jī)
3.3 5位獨(dú)立鍵盤
3.4 12864液晶顯示
3.5 水體溫度采集
3.6 液位高度采集
3.7 溫度、高度調(diào)節(jié)
3.8 PC與單片機(jī)通信
四、軟件
4.1 程序總體設(shè)計(jì)方案
4.2 主程序偽代碼
五、調(diào)試
5.1 遇到的問(wèn)題及解決方案
六、我們的特色
七、主要程序附錄
6.1主程序
6.2 12864液晶顯示程序
6.3獨(dú)立鍵盤掃描程序
6.4溫度、高度控制程序
6.5 Ds18b20讀取溫度程序
6.6 超聲波測(cè)液位程序
6.7 上位機(jī)及下位機(jī)程序
一、 引言
在一個(gè)水浴系統(tǒng)中,控制并保持水體溫度,高度是十分必要的。本系統(tǒng)主要應(yīng)用超聲波測(cè)液位,溫度傳感器測(cè)水體溫度。超聲波液位可控恒溫水浴系統(tǒng)在人們?nèi)粘I钌a(chǎn)中有很廣泛的應(yīng)用。如:游泳池水位、水溫的檢測(cè)及調(diào)控。
二、 系統(tǒng)總體設(shè)計(jì)
本設(shè)計(jì)基于單片機(jī)的超聲波液位可控恒溫水浴系統(tǒng)主要由單片機(jī)模塊、溫度檢測(cè)模塊、超聲波檢測(cè)模塊、LED顯示模塊、12864液晶顯示模塊、獨(dú)立鍵盤模塊、繼電器驅(qū)動(dòng)模塊以及PC通信等組成。
1. 整體設(shè)計(jì)方案
本設(shè)計(jì)采用模塊化思想,以AT89S52為核心,將其他表模塊有機(jī)結(jié)合在一起,形成一個(gè)符合設(shè)計(jì)要就的系統(tǒng)。其系統(tǒng)模塊框圖如下圖:
獨(dú)立鍵盤
上位機(jī)
串口通信模塊
超聲波測(cè)量液位
LED顯示模塊
12864液晶
顯示
DS18b20
采集溫度
AT89S52
單
片
機(jī)
繼電器驅(qū)動(dòng)制冷片和水泵
2. 水浴箱外形設(shè)計(jì)
考慮到水浴系統(tǒng)的實(shí)際應(yīng)用,我們?cè)谠O(shè)計(jì)水箱結(jié)構(gòu)時(shí),將加熱制冷模塊和抽水模塊放在水箱底部,并用一層板將之與上面的水浴隔開,實(shí)現(xiàn)安全設(shè)計(jì)的理念。同時(shí),將兩個(gè)制冷片分別置于水箱兩邊,使水箱更加穩(wěn)定;還增加設(shè)計(jì)了兩個(gè)平臺(tái),可以放置液晶顯示模塊和鍵盤操作模塊,使操作更加便利和人性化。
三、 硬件設(shè)計(jì)方案
3.1 電源
根據(jù)師兄往年參賽的經(jīng)驗(yàn),本設(shè)計(jì)所采用的電源是和制冷片配套買的,規(guī)格12V-10A,電壓和電流相對(duì)比較穩(wěn)定。在系統(tǒng)中為散熱風(fēng)扇、制冷片、水泵等供電。另外,采用9V電池為單片機(jī)及其他一些模塊供電。
3.2 AT89S52單片機(jī)
本模塊主要是采用單片機(jī)最小系統(tǒng)板,外加其他附加電路。
3.3 5位獨(dú)立鍵盤
Enter鍵(確定進(jìn),出設(shè)置程序),
上移鍵 (增大各個(gè)數(shù)值),
下移鍵 (增大各個(gè)數(shù)值),
左移鍵 (左移光標(biāo)),
右移鍵 右移光標(biāo))。
3.4 12864液晶顯示
本模塊是用12864液晶顯示溫度、液位高度以及當(dāng)前溫度曲線和液位高度柱狀圖。
其連接電路如下圖:
關(guān)于12864液晶的具體操做方法可參考郭天祥51單片機(jī)教程164頁(yè)7.4常用12864液晶操作實(shí)例。
3.5 水體溫度采集
1. 溫度采集模塊方案比較
方案1:采用美國(guó)DALLAS公司生產(chǎn)DS18B20數(shù)字溫度傳感器,單線接口方式,與單片機(jī)進(jìn)行通信只需要一個(gè)I/O口,電路簡(jiǎn)單且比較方便。而且可以直接讀出溫度值隨后進(jìn)行相應(yīng)的轉(zhuǎn)換并顯示出來(lái)。
方案2:使用正溫度系數(shù)熱敏電阻PTC或者負(fù)溫度系數(shù)熱敏電阻NTC的感溫特性,在溫度變化時(shí),電阻會(huì)相應(yīng)地變化,從而使輸出電壓或輸出電流相應(yīng)地變化,再用AD模數(shù)轉(zhuǎn)換將電壓采集回來(lái),通過(guò)一定的計(jì)算出當(dāng)前溫度并顯示出來(lái)。
電路如上,信號(hào)的采集要加上放大器、比較器、AD模數(shù)轉(zhuǎn)換等,比較麻煩,而且占用資源比較多。
綜上,比較以上兩種方案,很容易看出,采用方案1,電路比較簡(jiǎn)單,軟件設(shè)計(jì)容易實(shí)現(xiàn),故實(shí)際設(shè)計(jì)中擬采用方案1。
3.6 液位高度采集
由于本系統(tǒng)設(shè)計(jì)要求,所以采用超聲波測(cè)量水面液位。
1. 超聲波傳感器與應(yīng)用電路
3.7 溫度、液位高度調(diào)節(jié)
本設(shè)計(jì)采用繼電器雙向控制制冷片以及散熱風(fēng)扇,水泵,從而實(shí)現(xiàn)制冷片制熱,制冷;水泵正反向抽水。
繼電器雙向控制電路如下圖:
用繼電器來(lái)進(jìn)行控制,三極管放大來(lái)驅(qū)動(dòng)繼電器,
一開始擬采用12V控制電壓的,但由于是單片機(jī)驅(qū)動(dòng),便選擇了SRD-05VC-SL-C,VCC端接單片機(jī)電源端即可。比較方便,而且耐得住最大不超過(guò)10A的電流,滿足要求。
3.8 PC與單片機(jī)通信
1. PC機(jī)與單片機(jī)AT89S52通信的硬件設(shè)計(jì)
通常PC機(jī)和單片機(jī)之間的通信是通過(guò)串行總線RS-232實(shí)現(xiàn)的。因此采用一種以MAX232為核心的通信接口電路。該接口電路適用于由一臺(tái)PC機(jī)與多個(gè)8051單片機(jī)串行通信的設(shè)計(jì),其原理和方法同樣適用于PC機(jī)與其它單片機(jī)之間的串行數(shù)據(jù)通信。其原理框圖見圖1:
圖1 單片機(jī)與PC機(jī)通信原理框圖
該框圖中,起著重要作用的是RS-232C通信接口電路。它是上位機(jī)和下位機(jī)之間信息傳遞的樞紐,一切數(shù)據(jù)的傳輸必需由它完成,上位機(jī)直接利用它的RS-232串行口,為此,采用了RS-232串行通信來(lái)接收或上傳數(shù)據(jù)和指令。但RS-232信號(hào)的電平和單片機(jī)串口信號(hào)的電平不一致,必須進(jìn)行二者之間的電平轉(zhuǎn)換。在此電路中,采用MAX232實(shí)現(xiàn)TTL邏輯電平和RS-232電平之間的相互轉(zhuǎn)換。
MAX232由單一的+5V電源供電,只需配接5個(gè)高精度10μF/50V的鉭電容即可完成電平轉(zhuǎn)換。因此,避免了用1488和1489時(shí)必需兩路電源的麻煩。轉(zhuǎn)換后的串行信號(hào)TXD、RXD直接與PC機(jī)的串行口連接。如此設(shè)計(jì),既可發(fā)揮出PC機(jī)強(qiáng)大的計(jì)算和顯示功能,又可以體現(xiàn)出單片機(jī)靈活的控制功能,有利于對(duì)現(xiàn)場(chǎng)信號(hào)的實(shí)時(shí)采集、處理和監(jiān)控。
2. AT89S52與PC機(jī)之間的通信協(xié)議
在許多場(chǎng)合的測(cè)控系統(tǒng)中,約定PC機(jī)和AT89S52單片機(jī)的通信協(xié)議為:
Number+Command+Length+Data+Check
Number:下位機(jī)的機(jī)號(hào),若設(shè)計(jì)中有3臺(tái)下位機(jī),即Number 取01H,02H,03H,分別代表:#1,#2,#3號(hào)下位機(jī);
Command:本次命令的代碼;Length:本次發(fā)送數(shù)據(jù)段的字節(jié)數(shù);
Data:要發(fā)送的數(shù)據(jù)段;
Check:1字節(jié)的校驗(yàn)碼。
本設(shè)計(jì)只考慮一個(gè)單片機(jī),故可對(duì)上述通信協(xié)議進(jìn)行簡(jiǎn)化。
四、 軟件設(shè)計(jì)
4.1 程序總體設(shè)計(jì)方案
本系統(tǒng)的軟件設(shè)計(jì)方案采用多模塊設(shè)計(jì),既有利于分工,提高效率,又有利于實(shí)現(xiàn)程序的封裝。其整體方案如下:
獨(dú)立鍵盤調(diào)節(jié)模塊程序
串口通信模塊程序
AT89S52
單
片
機(jī)
超聲波測(cè)量液位模塊程序
DS18b20
采集溫度模塊程序
上位機(jī)模塊程序
12864液晶
顯示模塊程序
PID控制繼電器驅(qū)動(dòng)制冷片和水泵模塊程序
LED顯示及蜂鳴器警報(bào)模塊程序
4.2 主程序偽代碼:
初始化
While(1)
If模式鍵沒(méi)按下
{ If溫度采樣完成
{
進(jìn)入溫度PID控制
If 當(dāng)前誤差在死區(qū)內(nèi)
制冷片停
Else
12864溫度刷新
將溫度傳給上位機(jī)
If 當(dāng)前溫度>目標(biāo)溫度
制冷片制冷
Else
制冷片加熱
PID控制制冷片工作占空比
}
If 高度采樣完成
{ 進(jìn)入高度PID控制
If 當(dāng)前誤差在死去內(nèi)
水泵停
Else
12864高度刷新
將高度數(shù)據(jù)傳給上位機(jī)
If 當(dāng)前高度>目標(biāo)高度
水泵出水
Else
水泵進(jìn)水
PID控制水泵工作占空比
}
進(jìn)行鍵盤掃描
}
Else (進(jìn)入設(shè)置模式)
{
鍵盤掃描確定按鍵
根據(jù)相應(yīng)的按鍵進(jìn)行溫度、高度的調(diào)節(jié)
}
五、 調(diào)試
5.1 遇到的問(wèn)題及解決方案
1.由于時(shí)間緊迫,如果水箱交由廠家制作成型,時(shí)間會(huì)很浪費(fèi),所以最終決定自己購(gòu)買塑料板回來(lái),再自己用玻璃膠粘和成型,但由于是自己粘的,所以很長(zhǎng)一段時(shí)間,都存在縫隙漏水問(wèn)題,最后再加上其他膠水,才解決這個(gè)問(wèn)題。
2.由于上位機(jī)采用VB語(yǔ)言編寫,但我們?nèi)硕紱](méi)有VB基礎(chǔ),所以只能從零開始學(xué)習(xí)VB 。
3.上位機(jī)與單片機(jī)之間的串口通信線開始時(shí)連接一直出錯(cuò),后買了一條新的串口線,并從新安裝了一個(gè)驅(qū)動(dòng)軟件,才實(shí)現(xiàn)功能。
4.由于電路模塊很多,如果每次都重新接導(dǎo)線,將會(huì)很麻煩,所以我們采用一個(gè)盒子將多個(gè)電路模塊封裝起來(lái),使整體更美觀。
5.由于制冷片工作功率不怎么高,使得我們起初采集到的溫度數(shù)據(jù)的變化不明顯,通過(guò)不斷修改采樣頻率,使得在既能反應(yīng)溫度變化的前提下,又能減少DS18b20的工作頻率。
6.起初設(shè)計(jì)是想把超聲波放在水箱底部,為此還特地在設(shè)計(jì)水箱底部時(shí),設(shè)計(jì)了超聲波模塊的結(jié)構(gòu),但在實(shí)際調(diào)試過(guò)程中,由于防水薄膜對(duì)超聲波反射產(chǎn)生能大的干擾,所以后改用將超聲波模塊放于水箱上部,并將算法進(jìn)行相應(yīng)的修改即可。
7.在調(diào)試過(guò)程中,發(fā)現(xiàn)制冷片的加熱和制冷速率都有點(diǎn)慢,如果要較大幅度的改變溫度(如:重15度升到45度)時(shí),會(huì)等很久,所以經(jīng)過(guò)討論,改進(jìn)成先將水換成常溫下的水,再進(jìn)行制冷或加熱。
六、 我們的特色
1. 考慮到制冷或加熱所需能量較多,且耗費(fèi)時(shí)間更長(zhǎng),因此我們決定,在滿足一定條件時(shí),直接將容器內(nèi)部的水換成外部常溫下的水,再進(jìn)行相應(yīng)的制冷或加熱。
2. 水的進(jìn)出位置安排在底部,液面上升和下降時(shí)較平穩(wěn),沒(méi)有太大波動(dòng)。
3. 制冷裝置和溫度傳感器均安裝在底部,不占用容器主體位置,使該水浴系統(tǒng)使用范圍更廣。
4. 容器側(cè)面有兩個(gè)突出的平臺(tái),可用于放置液晶顯示屏和操作按鍵,更具一體化,實(shí)用性更強(qiáng)。
七、主要程序附錄
6.1主程序
#ifndef __MAIN_H__
#define __MAIN_H__
/**************宏定義****************/
#define uchar unsigned char
#define uint unsigned int
#define ON 1
#define OFF 0
/*************位定義****************/
sbit pump_F = P2^0; //水泵正向引腳
sbit pump_B = P2^1; //水泵反向引腳
sbit cooler1_F = P2^2; //制冷片1正向引腳
sbit cooler1_B = P2^3; //制冷片1反向引腳
sbit cooler2_F = P2^4; //制冷片2正向引腳
sbit cooler2_B = P2^5; //制冷片2反向引腳
/************枚舉******************/
enum DIRECTION {FORWARD=0, BACKWARD=1};
/************聲明變量**************/
extern bit cooler_flag; //制冷片旗標(biāo) 判斷是否啟動(dòng)制冷片
extern bit pump_flag; //水泵旗標(biāo) 判斷是否啟動(dòng)水泵
extern enum DIRECTION cooler_drc_flag; //制冷片方向旗標(biāo) 判斷制冷片電流方向
extern enum DIRECTION pump_drc_flag; //水泵方向旗標(biāo) 判斷水泵電流方向
extern bit temper_check_flag; //溫度檢測(cè)旗標(biāo) 判斷溫度是否采樣
extern bit height_check_flag; //液位檢測(cè)旗標(biāo) 判斷液位是否采樣
extern int temperature; //測(cè)量得到的當(dāng)前溫度值
#endif
/*************頭文件***************/
#include
#include
#include "main.h"
#include "PID.h"
#include "interrupt.h"
#include "keyboard.h"
#include "12864_bing.h"
#include "DS18B20.h"
#include "Ultrasonic.h"
/************定義變量************/
bit cooler_flag = OFF; //制冷片旗標(biāo) 判斷是否啟動(dòng)制冷片
bit pump_flag = OFF; //水泵旗標(biāo) 判斷是否啟動(dòng)水泵
enum DIRECTION cooler_drc_flag = FORWARD; //制冷片方向旗標(biāo) 判斷制冷片電流方向
enum DIRECTION pump_drc_flag = FORWARD; //水泵方向旗標(biāo) 判斷水泵電流方向
bit temper_check_flag = OFF; //溫度改變旗標(biāo) 判斷溫度是否改變
bit height_check_flag = OFF; //液位改變旗標(biāo) 判斷液位是否改變
int temperature; //測(cè)量得到的當(dāng)前溫度值
/**********聲明函數(shù)**************/
void init(); //初始化函數(shù)
/***********主函數(shù)***************/
void main()
{
init(); //初始化
while(1)
{
//若enter鍵旗標(biāo)表明不是進(jìn)入設(shè)置模式
if (enter_flag == 0)
{
//若溫度檢測(cè)旗標(biāo)表明溫度已經(jīng)采樣
if (temper_check_flag == ON)
{
PID1.error0 = temperature - PID1.target; //計(jì)算當(dāng)前誤差 [當(dāng)前值-目標(biāo)值] (單位:*10度)
if ((PID1.error0 >= TEMPER_DDZ_L) && (PID1.error0 <= TEMPER_DDZ_H)) //若當(dāng)前誤差在死區(qū)范圍內(nèi)
{
temper_check_flag = OFF; //溫度檢測(cè)旗標(biāo)變?yōu)镺FF
cooler_flag = OFF; //制冷片旗標(biāo)變?yōu)镺FF,表明制冷片停止工作
//溫度到達(dá)穩(wěn)定標(biāo)志
}
else //否則,當(dāng)前誤差不在死區(qū)范圍內(nèi)
{
//12864刷屏
//將相應(yīng)數(shù)據(jù)傳輸給上位機(jī)
//判斷誤差大于0還是小于0,從而判斷制冷片制冷還是加熱
if (PID1.error0 > 0) //誤差大于0,當(dāng)前溫度高于目標(biāo)值,制冷片電流方向?yàn)檎?,制?
{
cooler_drc_flag = FORWARD;
}
else //否則,誤差小于0,當(dāng)前溫度低于目標(biāo)值,制冷片電流方向?yàn)榉聪颍訜?
{
cooler_drc_flag = BACKWARD;
}
PID1_control(); //溫度PID控制
pwm_cooler = (uchar)(abs(PID1.output)); //將PID輸出值賦給制冷片pwm高電平時(shí)間,從而控制制冷片功率
}
}
//若液位檢測(cè)旗標(biāo)表明液位已經(jīng)采樣
if (height_check_flag == ON)
{
PID2.error0 = (int)( (distance%100000)/10 ) - PID2.target; //計(jì)算當(dāng)前誤差 [當(dāng)前值-目標(biāo)值]
if ((PID2.error0 >= HEIGHT_DDZ_L) && (PID2.error0 <= HEIGHT_DDZ_H)) //若當(dāng)前誤差在死區(qū)范圍內(nèi)
{
height_check_flag = OFF; //液位改變旗標(biāo)變?yōu)镺FF,當(dāng)前誤差為0
pump_flag = OFF; //水泵旗標(biāo)變?yōu)镺FF,表明水泵停止工作
//液位到達(dá)穩(wěn)定標(biāo)志
}
else //否則,當(dāng)前誤差不在死區(qū)范圍內(nèi)
{
//更新12864上顯示的當(dāng)前液位高度
height_draw = distance_char[1] * 10 + distance_char[2]; //取當(dāng)前高度數(shù)值,單位為cm
DrawHeight(height_draw); //將當(dāng)前高度圖像在12864上畫出
//將相應(yīng)數(shù)據(jù)傳輸給上位機(jī)
if (PID2.error0 > 0) //若誤差大于0,當(dāng)前液位高于目標(biāo)液位,水泵電流方向?yàn)檎?,出?
{
pump_drc_flag = FORWARD;
}
else //否則,誤差小于0,當(dāng)前液位低于目標(biāo)液位,水泵電流方向?yàn)樨?fù)方向,進(jìn)水
{
pump_drc_flag = BACKWARD;
}
PID2_control(); //液位PID控制
pwm_pump = (uchar)(abs(PID2.output)); //將PID輸出值賦給水泵pwm高電平時(shí)間,從而控制水泵功率
}
}
enter_scan(); //掃描鍵盤
}
//否則,則enter鍵旗標(biāo)表明進(jìn)入設(shè)置模式
else
{
key = DEFAULT;
while (key == DEFAULT)
{
key_scan(); //鍵盤掃描
}
DealKey();
}
}
}
/***********初始化函數(shù)**********/
void init()
{
interrupt_init(); //中斷初始化
PID_init(); //PID參數(shù)初始化
Init_12864(); //12864初始化
Init_DS18B20(); //DS18B20初始化
}
6.2 12864液晶顯示程序
#ifndef __12864_BRING_H__
#define __12864_BRING_H__
/***********宏定義***********/
#define uchar unsigned char
#define uint unsigned int
/********* 端口定義*********/
#define LCD_data P0 //數(shù)據(jù)口
sbit LCD_RS=P3^4; //寄存器選擇輸入
sbit LCD_RW=P3^5; //液晶讀/寫控制
sbit LCD_EN=P3^6; //液晶使能控制
//psb接在正極上
/**********變量聲明**********/
extern uchar idata LastTemp; //定義最后一次的溫度,方便畫線
extern uchar idata LastTempData1; //最后一次讀取顯示的內(nèi)容,用于變換目標(biāo)溫度時(shí)恢復(fù)上一個(gè)
extern uchar idata LastTempData2; //最后一次讀取顯示的內(nèi)容,用于變換目標(biāo)溫度時(shí)恢復(fù)上一個(gè)
extern uchar idata LastHeight; //最后一次的高度,用于變化高度時(shí)迅速畫線,減少關(guān)閉畫圖時(shí)間
/*函數(shù)聲明*/
//extern void Delay_ms(uint x) ;
extern void CheckBusy(); //一直等待,直到不忙
extern void WriteCommand(uchar cmd); //寫指令函數(shù)
extern void WriteData(uchar dat); //寫數(shù)據(jù)函數(shù)
extern uchar ReadData(); //返回當(dāng)前地址的數(shù)據(jù)
extern void Location(uchar X,uchar Y); //定位,X=1~4;Y=1~8
extern void Init_12864();
extern void DrawPicture(uchar *img); //整屏畫圖函數(shù),傳遞數(shù)組首地址
extern void DrawPoint(uchar Row ,uchar Column); //寫點(diǎn)函數(shù),參數(shù)是行和列Row=1~64;Column=1~128
extern void DrawTemp(uchar const temp); //畫等溫線函數(shù)(平行于X軸直線)
extern void ChangeTemp(uchar temp); //當(dāng)溫度改變時(shí)調(diào)用,恢復(fù)上次畫線前的樣子,并畫新線
extern void DrawHeight(uchar const h); //畫高度函數(shù)(長(zhǎng)方體),參數(shù)是高度
#endif
#include
#include
#include"12864_bing.h"
#include "delay_ms.h"
#define uchar unsigned char
#define uint unsigned int
uchar idata LastTemp=0;
uchar idata LastTempData1=0;
uchar idata LastTempData2=0;
uchar idata LastHeight=24;
uchar code init_char1[]={"To: 27.6cm 50.0 "};
uchar code init_char2[]={" 27.5cm 56.7cm "};
/*********************************************************/
/* */
/* 讀忙標(biāo)志 */
/* */
/*********************************************************/
void CheckBusy()
{
uchar result;
do
{
LCD_EN=0;
LCD_RS=0;
LCD_RW=1;
LCD_EN=1;
result=LCD_data;
LCD_EN=0;
result=result&0x80;
}while(result==0x80);
}
/*******************************************************************/
/* */
/*寫指令數(shù)據(jù)到LCD */
/*RS=L,RW=L,E=高脈沖,D0-D7=指令碼。 */
/* */
/*******************************************************************/
void WriteCommand(uchar cmd)
{
CheckBusy();
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
LCD_data = cmd;
delay_ms(5);
LCD_EN = 1;
delay_ms(5);
LCD_EN = 0;
}
/*******************************************************************/
/* */
/*寫顯示數(shù)據(jù)到LCD */
/*RS=H,RW=L,E=高脈沖,D0-D7=數(shù)據(jù)。 */
/* */
/*******************************************************************/
void WriteData(uchar dat)
{
CheckBusy();
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
LCD_data = dat;
delay_ms(5);
LCD_EN = 1;
delay_ms(5);
LCD_EN = 0;
}
/*******************************************************************/
/* */
/* 讀數(shù)據(jù) */
/* */
/*******************************************************************/
uchar ReadData()
{
uchar dat;
LCD_data=0xff;
CheckBusy();
LCD_EN=0;
LCD_RW=1;
LCD_RS=1;
LCD_EN=1;
_nop_();
_nop_();
dat=LCD_data;
LCD_EN=0;
return dat;
}
/*********************************************************/
/* */
/* 設(shè)定顯示位置 */
/* */
/*********************************************************/
void Location(uchar X,uchar Y)
{
uchar pos;
if (X==1)
{X=0x80;}
else if (X==2)
{X=0x90;}
else if (X==3)
{X=0x88;}
else if (X==4)
{X=0x98;}
pos = X+Y-1;
WriteCommand(pos); //顯示地址
}
/*******************************************************************/
/* */
/* LCD初始化設(shè)定 */
/* */
/*******************************************************************/
void Init_12864()
{
//LCD_PSB = 1; //并口方式
WriteCommand(0x30); //基本指令操作
delay_ms(5);
WriteCommand(0x0C); //顯示開,關(guān)光標(biāo)
delay_ms(5);
WriteCommand(0x01); //清除LCD的顯示內(nèi)容
delay_ms(5);
}
/*******************************************************************/
/* */
/* 整屏畫圖函數(shù) */
/* */
6.3獨(dú)立鍵盤掃描程序
#ifndef __KEY_SCAN_H__
#define __KEY_SCAN_H__
/**************位定義***************/
sbit key_enter = P2^0; //enter鍵
sbit key_left = P2^1; //左移鍵
sbit key_right = P2^2; //右移鍵
sbit key_up = P2^3; //上移鍵
sbit key_down = P2^4; //下移鍵
/*************枚舉******************/
enum KEY {DEFAULT=0, ENTER=1, LEFT=2, RIGHT=3, UP=4, DOWN=5};
/**************聲明函數(shù)*************/
extern void enter_scan(); //enter鍵掃描函數(shù)
extern void key_scan(); //鍵盤掃描函數(shù)
extern void DealKey(); //鍵盤處理函數(shù)
/**************聲明變量************/
extern bit enter_flag; //鍵盤旗標(biāo) 按下enter鍵時(shí),1表示進(jìn)入設(shè)置,0表示退出設(shè)置
extern struct PID_STRUCT PID1; //溫度
extern struct PID_STRUCT PID2; //高度
extern enum KEY key; //按鍵鍵值
#endif
/*********定義變量***********/
bit enter_flag = 0; //enter鍵旗標(biāo) 按下enter鍵時(shí),1表示進(jìn)入設(shè)置,0表示退出設(shè)置
bit flag_num_location;// 定義修改目標(biāo)溫度位置標(biāo)志位,當(dāng)值為0時(shí)表明正在修改目標(biāo)高度,是1時(shí)正在修改溫度
enum KEY key = DEFAULT; //按鍵鍵值 DEFAULT表明沒(méi)有按鍵按下
/*********掃描enter鍵函數(shù)*******/
void enter_scan()
{
if (key_enter == 0)
{
delay_ms(10); //去抖延時(shí)
if (key_enter == 0)
{
EA = OFF; //關(guān)總中斷
while (key_enter == 0); //等待按鍵釋放
enter_flag = ~enter_flag; //鍵盤旗標(biāo)取反
//若鍵盤旗標(biāo)為1,表明進(jìn)入設(shè)置
if (enter_flag == 1)
{
ET1 = OFF; //關(guān)定時(shí)器1中斷
TR1 = OFF; //停止定時(shí)器1
TH1 = (65536 - 46080) / 256; //重裝初值 11.0592M晶振 50ms
TL1 = (65536 - 46080) % 256;
temper_sample_count = 0; //采樣時(shí)間計(jì)數(shù)歸零
height_sample_count = 0;
cooler_count = 0; //制冷片pwm計(jì)數(shù)歸零
pump_count = 0; //水泵pwm計(jì)數(shù)歸零
cooler1_F = OFF; //繼電器所有引腳撥到停止位置,制冷片、水泵停止工作
cooler2_F = OFF;
cooler1_B = OFF;
cooler2_B = OFF;
pump_F = OFF;
pump_B = OFF;
Location(1,3);
WriteCommand(0x0f);//開光標(biāo)
flag_num_location=0;
}
//否則,鍵盤旗標(biāo)為0,表明退出設(shè)置
}
}
}
/*********掃描鍵盤函數(shù)**********/
void key_scan()
{
//enter鍵被按下
if (key_enter == 0)
{
delay_ms(10); //去抖延時(shí)
if (key_enter == 0)
{
while (key_enter == 0); //等待按鍵釋放
key = ENTER;
}
}
//左移鍵被按下
if (key_left == 0)
{
delay_ms(10); //去抖延時(shí)
if (key_left == 0)
{
while (key_left == 0); //等待按鍵釋放
key = LEFT;
}
}
//右移鍵被按下
if (key_right == 0)
{
delay_ms(10); //去抖延時(shí)
if (key_right == 0)
{
while (key_right == 0); //等待按鍵釋放
key = RIGHT;
}
}
//上移鍵被按下
if (key_up == 0)
{
delay_ms(10); //去抖延時(shí)
if (key_up == 0)
{
while (key_up == 0); //等待按鍵釋放
key = UP;
}
}
//下移鍵被按下
if (key_down == 0)
{
delay_ms(10); //去抖延時(shí)
if (key_down == 0)
{
while (key_down == 0); //等待按鍵釋放
key = DOWN;
}
}
}
void DealKey()
{
uchar temp1,temp2; //用于將目標(biāo)值變成兩個(gè)數(shù)字
if(key==ENTER)
{
//按下enter鍵
enter_flag = 0; //enter鍵旗標(biāo)置0,表明退出設(shè)置模式
EA = ON; //開總中斷
ET1 = ON; //開定時(shí)器1中斷
TR1 = ON; //啟動(dòng)定時(shí)器1
WriteCommand(0x0c);//關(guān)光標(biāo)
}
else if(key==LEFT)
//按下左移鍵
{
Location(1,3);
flag_num_location=0;
}
else if(key==RIGHT)
//按下右移鍵
{
Location(1,7);
flag_num_location=1;
}
else if(key==UP)
//按下上移鍵
{
//-----------------------------------------------------
if(flag_num_location==0) //正在修改高度
{
temp1=PID2.target/100;
temp2=(PID2.target-temp1*100)/10;
if(temp2!=9) //還沒(méi)滿十
{
WriteData(0x30 + temp1);
WriteData(0x30 + temp2 + 1);
PID2.target += 10;
}
//---------------------------------------------
if(temp2==9) //滿十進(jìn)1
{
WriteData(0x30 + temp1 + 1);
WriteData('0');
PID2.target += 10;
}
Location(1,3);
flag_num_location=0; //恢復(fù)光標(biāo)顯示
}
//--------------------------------------------------
else if(flag_num_location==1) //正在修改溫度
{
temp1=PID1.target/100;
temp2=(PID1.target-temp1*100)/10;
if(temp2!=9) //還沒(méi)滿十
{
WriteData(0x30 + temp1);
WriteData(0x30 + temp2 + 1);
PID1.target += 10;
}
//---------------------------------------------
if(temp2==9) //滿十進(jìn)1
{
WriteData(0x30 + temp1 + 1);
WriteData('0');
PID1.target += 10;
}
Location(1,7);
flag_num_location=1; //恢復(fù)光標(biāo)顯示
}
}
else if(key==DOWN)
{
//按下下移鍵
//-----------------------------------------------------
if(flag_num_location==0) //正在修改高度
{
temp1=PID2.target/100;
temp2=(PID2.target-temp1*100)/10;
if(temp2!=0) //還沒(méi)滿十
{
WriteData(0x30 + temp1);
WriteData(0x30 + temp2 - 1);
PID2.target -= 10;
}
//---------------------------------------------
if(temp2==0) //滿十進(jìn)1
{
WriteData(0x30 + temp1 - 1);
WriteData('9');
PID2.target -= 10;
}
Location(1,3);
flag_num_location=0; //恢復(fù)光標(biāo)顯示
}
//--------------------------------------------------
else if(flag_num_location==1) //正在修改溫度
{
temp1=PID1.target/100;
temp2=(PID1.target-temp1*100)/10;
if(temp2!=0) //還沒(méi)滿十
{
WriteData(0x30 + temp1);
WriteData(0x30 + temp2 - 1);
PID1.target -= 10;
}
//---------------------------------------------
if(temp2==0) //滿十進(jìn)1
{
WriteData(0x30 + temp1 - 1);
WriteData('9');
PID1.target -= 10;
}
Location(1,7);
flag_num_location=1; //恢復(fù)光標(biāo)顯示
}
}
}
6.4溫度、高度控制程序
#define TEMPER_SAMPLE 100 //溫度采樣周期 [100*50=5000 ms]
#define TEMPER_P 5 //溫度比例系數(shù) [0.5]
#define TEMPER_I 50 //溫度積分時(shí)間 [5000*50=250 000 ms] (縮小100倍,相當(dāng)于Ki放大100倍)
#define TEMPER_D 600 //溫度微分時(shí)間 [600*50=3000 ms]
#define TEMPER_SprH 100 //溫度積分分離上限(10度) 誤差大于該上限時(shí)采用積分分離
#define TEMPER_SprL -100 //溫度積分分離下限(-10度) 誤差小于該下限時(shí)采用積分分離
#define TEMPER_ErrSumMax 2000 //設(shè)定溫度累積誤差最大值(200度)
#define TEMPER_ErrSumMin -2000 //設(shè)定溫度累積誤差最小值(-200度)
#define HEIGHT_SAMPLE 20 //液位采樣周期 [20*50=1000 ms]
#define HEIGHT_P 4 //液位比例系數(shù) [0.1]
#define HEIGHT_I 10 //液位積分時(shí)間 [1000*50=50 000 ms] (縮小100倍,相當(dāng)于Ki放大100倍)
#define HEIGHT_SprH 50 //液位積分分離上限(5cm) 誤差大于該上限時(shí)采用積分分離
#define HEIGHT_SprL -50 //液位積分分離下限(-5cm) 誤差小于該下限時(shí)采用積分分離
#define HEIGHT_ErrSumMax 300 //液位累積誤差最大值(30cm)
#define HEIGHT_ErrSumMin -300 //液位累積誤差最小值(-30cm)
#define TEMPER_DDZ_H 5 //溫度死區(qū)上限(0.5度)
#de
收藏
編號(hào):4493579
類型:共享資源
大小:7.99MB
格式:ZIP
上傳時(shí)間:2020-01-07
35
積分
- 關(guān) 鍵 詞:
-
超聲波
可控
恒溫
水浴
系統(tǒng)
- 資源描述:
-
超聲波液位可控恒溫水浴系統(tǒng),超聲波,可控,恒溫,水浴,系統(tǒng)
展開閱讀全文
- 溫馨提示:
1: 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
裝配圖網(wǎng)所有資源均是用戶自行上傳分享,僅供網(wǎng)友學(xué)習(xí)交流,未經(jīng)上傳用戶書面授權(quán),請(qǐng)勿作他用。