所有資料51hei提供下載:
ff.rar
(7.29 MB, 下載次數: 95)
2018-5-5 14:32 上傳
點擊文件名下載附件
fujian

內容摘要摘要:本系統利用單片機AT89C52采用程序設計方法來測試溫度,還可以通過兩個按鍵設置溫度報警上限,當測試溫度超過設定的溫度上限時,蜂鳴器器就會報警且綠燈關閉,紅燈點亮;當溫度低于上限時蜂鳴器關閉且紅燈關閉,綠燈點亮。并通過液晶屏LCD12864顯示其測試溫度以及設置的上限溫度。
1系統設計2 1.1設計任務 2 1.2基本功能 2 1.3擴展功能 2 2系統方案論證2 2.1主控模塊 2 2.2顯示模塊 3 3 DS18B20的理論分析與計算3 4電路與程序設計6 4.1系統總體框圖 6 4.2總體電路 6 4.3程序的設計 總結 附錄1 附錄2
1系統設計
1.1設計任務設計一數字溫度測量系統,能自動實現實際溫度的測量與顯示。 1.2基本功能(1)測溫范圍-30℃~+120℃。 (2)測量誤差在±0.5℃之內。 (3)能正常顯示測量的溫度。 (4)能正常顯示測量的溫度的變換曲線圖。 1.3擴展功能(1)增加溫控功能,并可修改設置溫控的上下限。 (2)增加溫控報警功能。 2系統方案論證 本系統主要由主控模塊、顯示模塊、按鍵模塊、蜂鳴器模塊、LED模塊、傳感器模塊組成,下面分別論證這幾個模塊的選擇。 2.1主控模塊方案:AT89C52單片機是一種高性能8位單片微型計算機。內核本身具有豐富的指令集,足夠實現本次作品的全部基本功能和部分拓展功能,相比Atmega16我們對AT89C52更為熟悉,且芯片價格較低,性價比高。
2.2顯示模塊方案:采用LCD12864顯示。LCD12864屏幕顯示細膩直觀,且可以顯示中文,但是相對昂貴。 
3 DS18B20的理論分析與計算DS18B20 通過編程,可以實現最高 12 位的溫度存儲值,在寄存器中,以補碼的格式存儲,如圖1所示。 圖1 DS18B20 溫度數據格式 寄存器一共 2 個字節,LSB 是低字節,MSB 是高字節,其中 MSb 是字節的高位,LSb 是字節的低位。大家可以看出來,二進制數字,每一位代表的溫度的含義,都表示出來了。其中 S表示的是符號位,低 11 位都是 2 的冪,用來表示最終的溫度。DS18B20 的溫度測量范圍是從-55 度到+125 度,而溫度數據的表現形式,有正負溫度,寄存器中每個數字如同卡尺的刻度一樣分布,如圖 2所示。 圖2 DS18B20 溫度值 二進制數字最低位變化 1,代表溫度變化 0.0625 度的映射關系。當 0 度的時候,那就是0x0000,當溫度 125 度的時候,對應十六進制是 0x07D0,當溫度是零下 55 度的時候,對應的數字是 0xFC90。反過來說,當數字是 0x0001 的時候,那溫度就是 0.0625 度了。 DS18B20 簡單介紹: DALLAS 最新單線數字溫度傳感器DS18B20是一種新型的“一線器件”,其體積更小、更適用于多種場合、且適用電壓更寬、更經濟。DALLAS 半導體公司的數字化溫度傳感器DS18B20是世界上第一片支持“一線總線”接口的溫度傳感器。溫度測量范圍為-55~+125 攝氏度,可編程為9位~12 位轉換精度,測溫分辨率可達0.0625攝氏度,分辨率設定參數以及用戶設定的報警溫度存儲在EEPROM 中,掉電后依然保存。被測溫度用符號擴展的16位數字量方式串行輸出;其工作電源既可以在遠端引入,也可以采用寄生電源方式產生;多個DS18B20可以并聯到3 根或2 根線上,CPU只需一根端口線就能與諸多DS18B20 通信,占用微處理器的端口較少,可節省大量的引線和邏輯電路。因此用它來組成一個測溫系統,具有線路簡單,在一根通信線,可以掛很多這樣的數字溫度計,十分方便。 DS18B20 的性能特點如下: ●獨特的單線接口方式,DS18B20在與微處理器連接時僅需要一條口線即可實現微處理器與DS18B20的雙向通訊 ●DS18B20支持多點組網功能,多個DS18B20可以并聯在唯一的三線上,實現組網多點測溫 ●DS18B20在使用中不需要任何外圍元件,全部傳感元件及轉換電路集成在形如一只三極管的集成電路內 ●適應電壓范圍更寬,電壓范圍:3.0~5.5V,在寄生電源方式下可由數據線供電 ●測溫范圍-55℃~+125℃,精度為±0.5℃ ●零待機功耗 ●測量結果直接輸出數字信號,以“一線總線”穿行傳送給CPU,同時可傳送CRC校驗位,具有極強的抗干擾糾錯能力 ●負電壓特性,電源極性接反時,溫度計不會因發熱而燒毀,但不能正常工作 以上特點使DS18B20非常適用與多點、遠距離溫度檢測系統。 DS18B20內部結構主要由四部分組成:64位光刻ROM、溫度傳感器、非揮發的溫度報警觸發器TH和TL、配置寄存器。DS18B20的管腳排列、各種封裝形式如圖 4.2 所示,DQ 為數據輸入/輸出引腳。開漏單總線接口引腳。當被用著在寄生電源下,也可以向器件提供電源;GND為地信號;VDD為可選擇的VDD引腳。當工作于寄生電源時,此引腳必須接地。 外部封裝形式 傳感器電路圖 4電路與程序設計4.1系統總體框圖系統總體框圖如圖3所示 圖3 系統總體框圖 4.2總體電路總體電路圖見附錄2。 4.3程序的設計4.3.1程序功能描述(1)能夠測試-30℃~+120℃的溫度。 (2)按下S1能增加溫度報警上限,按下S2能減少溫度報警上限。 4.3.2試驗程序實驗程序見附錄1。
總結本系統以單片機STC89C52芯片為核心部件,利用LCD12864、獨立按鍵、DS18B20并配合C語言算法實現了簡易數字溫度計設計,完成此次設計題目中的全部基本功能和部分拓展功能。在系統設計過程中,力求硬件線路簡單,充分發揮軟件編程方便靈活的特點,來滿足系統設計要求。 在本次設計的過程中,遇到了許多突發事件和困難,設計制作曾一度止步不前,但通過仔細分析和調整后解決了一個又一個的問題。在整個過程中我們深刻的體會到團隊精神的重要性,并提高了自己解決問題的能力。在課程設計的整個過程中,我遇到了許多意想不到的困難,如自己設計電路,進行軟件編譯等等。不僅如此,很多從未遇見過的問題和現象困擾著我,比如在調試的過程中,時常出現問題,但每次經過仔細反復查找,終于可以將這些問題針對性的找到并進行合理的改正,確保其正常實現對應的功能,在自己處理難題的過程中,真正學到了很多新的知識。
單片機源程序如下:
- #include<reg51.h>
- #include<stdlib.h>
- #include<stdio.h>//頭文件
- #define uchar unsigned char
- #define uint unsigned int
- sbit DQ=P2^2;//ds18b20與單片機連接口
- sbit PWM=P1^0;//控制信號的輸出
- sbit TTT=P2^3;//控制信號的輸出
- unsigned char code str[]={"my name is lhh "};
- unsigned char code str_[]={"MADE IN NUPT... "};
- unsigned char code str1[]={"temper:"};
- unsigned char code str2[]={" "};
- unsigned char code nul[]={" "};
- unsigned char code str3[]={"target: "};
- unsigned char str4[6];//設定溫度的存儲
- uchar data disdata[5];
- uchar a[4]={0,0,0,0},j,i,k,num=0; //定義變量
- sbit js=P3^2; //紅外接收端
- uchar zhb_flag=0;//保證一次解碼,只執行一次代碼
- uint tvalue;//溫度值
- uchar tflag;//溫度正負標志
- uint count=0;//按鍵次數初始化為0
- uint number=4;//暫時規定輸入的溫度為xx.x的形式
- uchar j,key;
- uint time_flag=0;
- bit enterflag=0; // 確認鍵按下與否標志
- uint new_t; //轉化后的十進制實時溫度
- uint target=0; //轉化后的十進制的目標溫度---有鍵盤輸入
- //------------定義接口-------------//
- sbit RS=P3^5 ;
- sbit RW=P3^6;
- sbit E=P3^4;
- sbit PSB= P3^7; //H=并口; L="串口";
- #define Lcd_Bus P0
- // P0 接 LCM
- #define uchar unsigned char
- #define FIRST_ADDR 0
- //定義字符/漢字顯示起始位置
- /*------------------檢查忙位-----------------------------*/
- void chk_busy()
- {
- RS=0 ;
- RW=1 ;
- E=1 ;
- Lcd_Bus=0xff ;
- while((Lcd_Bus&0x80)==0x80);
- E=0 ;
- }
- /*------------------延時子程序-----------------------------*/
- void lcd_delay(unsigned int t)
- {
- unsigned int i,j ;
- for(i=0;i<t;i++)
- for(j=0;j<10;j++);
- }
- /*------------------寫命令到LCD------------------------------*/
- void write_com(unsigned char cmdcode)
- {
- chk_busy();
- RS=0 ;
- RW=0 ;
- E=1 ;
- Lcd_Bus=cmdcode ;
- lcd_delay(5);
- //------------------在數據寫入的時候加入適當的延時
- E=0 ;
- lcd_delay(5);
- }
- /*-------------------寫數據到LCD----------------------------*/
- void write_data(unsigned char Dispdata)
- {
- chk_busy();
- RS=1 ;
- RW=0 ;
- E=1 ;
- Lcd_Bus=Dispdata ;
- lcd_delay(5);
- //------------------在數據寫入的時候加入適當的延時
- E=0 ;
- lcd_delay(5);
- }
- /*------------------初始化LCD屏--------------------------*/
- void lcdreset()
- {
- PSB = 1;
- lcd_delay(2000);
- write_com(0x30);
- lcd_delay(10);
- //選擇基本指令集
- write_com(0x30);
- //選擇8bit數據流
- lcd_delay(5);
- write_com(0x0c);
- //開顯示(無游標、不反白)
- lcd_delay(10);
- write_com(0x01);
- //清除顯示,并且設定地址指針為00H
- lcd_delay(500);
- write_com(0x06);
- //指定在資料的讀取及寫入時,設定游標的移動方向及指定顯示的移位
- lcd_delay(0);
- }
- /*------------------顯示字符串--------------------------*/
- void hzkdis(unsigned char code*s)
- {
- while(*s>0)
- {
- write_data(*s);
- s++;
- lcd_delay(50);
- }
- }
- /*------------------首屏顯示--------------------------*/
- void ceshi()
- {
- write_com(0x01);
- //清除顯示,并且設定地址指針為00H
- lcd_delay(5);
- write_com(0x80);
- //第一行(如果是地址是:80H,即LCD的第一行的第一個位置顯示)
- hzkdis("通信1503");
- write_com(0x90);
- //第二行(如果是地址是:90H,即LCD的第二行的第一個位置顯示)
- hzkdis(str);
- write_com(0x88);
- //第三行(如果是地址是:88H,即LCD的第二行的第一個位置顯示)
- hzkdis("李浩浩常凡");
- write_com(0x98);
- //第四行(如果是地址是:98H,即LCD的第二行的第一個位置顯示)
- hzkdis("1513024090");
- }
- //------------------清整個GDRAM空間----------------------------
- void clrgdram()
- {
- unsigned char x,y ;
- for(y=0;y<64;y++)
- for(x=0;x<16;x++)
- {
- write_com(0x34);
- write_com(y+0x80);
- //行地址
- write_com(x+0x80);
- //列地址
- write_com(0x30);
- write_data(0x00);
- write_data(0x00);
- }
- }
- //------------------------------------------------------------
- void clrscreen()
- {
- write_com(0x01);
- lcd_delay(10);
- }
- unsigned char ReadByte(void)
- {
- unsigned char byReturnValue ;
- chk_busy();
- Lcd_Bus=0xff ;
- RS=1 ;
- RW=1 ;
- E=0 ;
- E=1 ;
- byReturnValue=Lcd_Bus ;
- E=0 ;
- return byReturnValue ;
- }
- /*增加畫點子程序
- 函數功能:在坐標為(x,y)點畫一個點
- 參數意義
- X:12864屏幕的橫坐標,范圍是0到128(從左到右)
- Y:12864的縱坐標,范圍是0到64(從上到下)
- Color:為1的時候表示為黑點
- */
- void DrawPoint(unsigned char X,unsigned char Y,unsigned char Color)
- {
- unsigned char Row,Tier,Tier_bit ;
- unsigned char ReadOldH,ReadOldL ;
- write_com(0x34);
- write_com(0x36);
- Tier=X>>4 ;
- Tier_bit=X&0x0f ;
- if(Y<32)
- {
- Row=Y ;
- }
- else
- {
- Row=Y-32 ;
- Tier+=8 ;
- }
- write_com(Row+0x80);
- write_com(Tier+0x80);
- ReadByte();
- ReadOldH=ReadByte();
- ReadOldL=ReadByte();
- write_com(Row+0x80);
- write_com(Tier+0x80);
- if(Tier_bit<8)
- {
- switch(Color)
- {
- case 0 :
- ReadOldH&=(~(0x01<<(7-Tier_bit)));
- break ;
- case 1 :
- ReadOldH|=(0x01<<(7-Tier_bit));
- break ;
- case 2 :
- ReadOldH^=(0x01<<(7-Tier_bit));
- break ;
- default :
- break ;
- }
- write_data(ReadOldH);
- write_data(ReadOldL);
- }
- else
- {
- switch(Color)
- {
- case 0 :
- ReadOldL&=(~(0x01<<(15-Tier_bit)));
- break ;
- case 1 :
- ReadOldL|=(0x01<<(15-Tier_bit));
- break ;
- case 2 :
- ReadOldL^=(0x01<<(15-Tier_bit));
- break ;
- default :
- break ;
- }
- write_data(ReadOldH);
- write_data(ReadOldL);
- }
- write_com(0x30);
- }
- void send_to_pc(void)
- {
- uint pc_flag=0;
- SCON=0x50;//串口方式1,允許接收
- TMOD=0x20;//定時器1,定時方式2
- TCON=0x40;//設定時器1開始計數
- TH1=0xE8;//11.0592MHz, 1200波特率
- TL1=0xE8;
- TI=1;
- TR1=1;
- while(1)
- {
- if(pc_flag==1)
- {
- TMOD=1;
- }
- else
- {
- printf("Now temperture is ");
- printf(disdata);
- printf("*0.1 C");
- pc_flag++;
- }
- }
- }
- void delay_18B20(unsigned int i)//延時1微秒
- {
- while(i--);
- }
- void ds1820rst()/*ds1820復位*/
- {
- unsigned char x=0;
- DQ = 1; //DQ復位
- delay_18B20(4); //延時
- DQ = 0; //DQ拉低
- delay_18B20(100); //精確延時大于480us
- DQ = 1; //拉高
- delay_18B20(40);
- }
- uchar ds1820rd()/*讀數據*/
- {
- unsigned char i=0;
- unsigned char dat = 0;
- for (i=8;i>0;i--)
- {
- DQ = 0; //給脈沖信號
- dat>>=1;
- DQ = 1; //給脈沖信號
- if(DQ)
- dat|=0x80;
- delay_18B20(10);
- }
- return(dat);
- }
- void ds1820wr(uchar wdata)/*寫數據*/
- {
- unsigned char i=0;
- for (i=8; i>0; i--)
- {
- DQ = 0;
- DQ = wdata&0x01;
- delay_18B20(10);
- DQ = 1;
- wdata>>=1;
- }
- }
- read_temp1()/*讀取溫度值并轉換*/
- {
- ds1820rst();
- ds1820wr(0xcc);//*跳過讀序列號*/
- ds1820wr(0x44);//*啟動溫度轉換*/
- ds1820rst();
- }
- read_temp2()
- {
- uchar a,b;
- ds1820wr(0xcc);//*跳過讀序列號*/
- ds1820wr(0xbe);//*讀取溫度*/
- a=ds1820rd();
- b=ds1820rd();
- tvalue=b;
- tvalue<<=8;
- tvalue=tvalue|a;
- if(tvalue<0x0fff)
- tflag=0;
- else
- {
- tvalue=~tvalue+1;
- tflag=1;
- }
- tvalue=tvalue*(0.625);//溫度值擴大10倍,精確到1位小數
- return(tvalue);
- }
- /*******************************************************************/
- void ds1820disp1()//溫度值顯示
- {
- uchar flagdat;
- if (tvalue>4200)
- {
- TTT=0;
- }
- disdata[0]=tvalue/1000+0x30;//百位數
- disdata[1]=tvalue%1000/100+0x30;//十位數
- disdata[2]=tvalue%100/10+0x30;//個位數
- disdata[3]=tvalue%10+0x30;//小數位
- if(tflag==0)
- flagdat=0x20;//正溫度不顯示符號
- else
- flagdat=0x2d;//負溫度顯示負號:-
- if(disdata[0]==0x30)
- {
- disdata[0]=0x20;//如果百位為0,不顯示
- if(disdata[1]==0x30)
- {
- disdata[1]=0x20;//如果百位為0,十位為0也不顯示
- }
- }
- }
- void ds1820disp2()
- {
- lcd_delay(5);
- write_com(0x80);
- hzkdis("溫度為:");
- lcd_delay(50);
- write_com(0x84);
- write_data(disdata[1]);
- write_com(0x85);
- write_data(disdata[2]);
- write_com(0x86);
- write_data(0x2e);
- write_com(0x87);
- write_data(disdata[3]);
- if(disdata[1]>=3+0x30||(disdata[2]>=8+0x30))
- { write_com(0x98);
- hzkdis("sos"); }
- else
- { write_com(0x98);
- hzkdis(" "); }
- lcd_delay(50);
- new_t=disdata[1]*10+disdata[2];
- }
- void delay(uint us) //delay time
- {
- while(us--);
- }
- void HW_key(void)
- {
- if(zhb_flag==1)
- {
- if((a[2]+a[3])==0xff) //判斷接收到數據是否正確
- {
- switch(a[2]) //將接受到的數據與所建表一一對應
- {
- case 0x00:
- {
- num=0;
- if (count<number)
- {
- str4[count]='0';
- count++;
- }break;//數字鍵0
- }
- case 0x01:
- {
- num=1;
- if (count<number)
- {
- str4[count]='1';
- count++;
- }break;//數字鍵1
- }
- case 0x02:
- {
- num=2;
- if (count<number)
- {
- str4[count]='2';
- count++;
- }break;//數字鍵2
- }
- case 0x03:
- {
- num=3;
- if (count<number)
- {
- str4[count]='3';
- count++;
- }break;//數字鍵3
- }
- case 0x04:
- {
- num=4;
- if (count<number)
- {
- str4[count]='4';
- count++;
- }break;//數字鍵4
- }
- case 0x05:
- {
- num=5;
- if (count<number)
- {
- str4[count]='5';
- count++;
- }break;//數字鍵5
- }
- case 0x06:
- {
- num=6;
- if (count<number)
- {
- str4[count]='6';
- count++;
- }break;//數字鍵6
- }
- case 0x07:
- {
- num=7;
- if (count<number)
- {
- str4[count]='7';
- count++;
- }break;//數字鍵7
- }
- case 0x08:
- {
- num=8;
- if (count<number)
- {
- str4[count]='8';
- count++;
- }break;//數字鍵8
- }
- case 0x09:
- {
- num=9;
- if (count<number)
- {
- str4[count]='9';
- count++;
- }break;//數字鍵9
- }
- case 0x0a:
- {
- num=10;
- if (count<number)
- {
- str4[count]='.';
- count++;
- }break;//鍵"--/-"
- }
- case 0x0b:
- {
- num=11;
- break;//鍵LG
- }
- case 0x0f:
- {
- num=12; break;//AV鍵
- }
- case 0x10:
- {
- num=13;
- send_to_pc();break;//靜音鍵
- }
- case 0x15:
- {
- num=14;
- break;//開關鍵
- }
- case 0x16:
- {
- num=15;break;//選臺鍵
- }
- case 0x17:
- {
- /* num=16; count = 0;//清零
- for (j=0;j<number;j++)
- {
- str4[j]=' ';
- }
- str4[j]='/0';
- PWM=1;
- time_flag=0;
- wr_com(0xcd);
- display(nul);
- target=0;
- enterflag = 0;break;//睡眠鍵*/
- }
- default:break;
- }
- if (enterflag==1) // 如果按下確認鍵
- {
- // enterflag = 0; // 標志位置回0
- /* wr_com(0xcd);
- wr_dat(0xdf);
- wr_dat(0x43);
- target=str4[0]*10+str4[1];
- time_flag=1;*/
- }
- /* wr_com(0xc0);
- display(str3);
- wr_com(0xc8);
- display(str4);
- zhb_flag=0;*/
- }
- }
- }
- /*void pitu_wave(void)
- {
- uchar i,a;
- uchar colour=1;
- for(i=0;i<128;i+=2)
- {
- a=64-new_t;
- DrawPoint(i,a,colour);
- }
- }*/
- /********************主程序***********************************/
- void main()
- {
- uchar wave=0;
- uchar i=0,a;
- uchar colour=1;
- RW=0 ;
- lcdreset();
- ceshi();
- clrgdram();
- delay(2000);
- clrscreen();
- EA=1; //初始化
- ET0=1; //開計數中斷0
- EX0=1; //開外部中斷0
- TMOD=1; //設置工作方式
- IT0=1; //啟動計時器
- while(1)
- {
- read_temp1();//讀取溫度
- read_temp2();//讀取溫度
- ds1820disp1();//顯示
- ds1820disp2();//顯示
- wave++;
- if(wave>=10)
- {
- a=64-new_t;
- if(i>=128)
- {
- i=0;
- clrgdram();
- delay(2000);
- clrscreen();
- }
- DrawPoint(i++,a,colour);
- wave=0;
- }
- HW_key();
- }
- }
- void zhb(void) interrupt 0 // 外部中斷子程序(譯碼過程)
- {
- zhb_flag=1;
- TH0=0; //計數器清零
- TL0=0;
- TR0=1; //啟動計數器
- while(!js) //等待低電平結束
- {
- delay(5);
- if(TH0>45) //判斷低電平是否高于11.52ms如果高于則跳出等待和中斷
- return;
- }
- TR0=0;
- if(TH0<30) //判斷低電平是否低于7.68ms如果低于跳出中斷
- return;
- TH0=0;
- TR0=1;
- while(js) //等待高電平結束
- {
- delay(5);
- if(TH0>28) //判斷高電平是否高于7.168ms如果高于則跳出等待和中斷
- return;
- }
- //至此為起始信號檢測
- TR0=0;
- TH0=0;
- for(i=0;i<4;i++) //一次鎖存紅外接收的四個十六進制數到a[4]中
- {
- for(j=0;j<8;j++)
- {
- …………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
|