本系統由AT89C51單片機、DS18B20溫度檢測部分、DS1302日期時間記錄部分、數碼管顯示部分、按鍵輸入部分和蜂鳴器報警部分組成。該系統通過按鍵一來調整模式,共五個模式。模式一是DS18B20采集環境溫度并保存在存儲器中通過單片機將溫度顯示在數碼管上,當溫度低于下限或高于上限時蜂鳴器報警;模式二是利用按鍵二和按鍵三調整報警的最高溫度加減;模式三是利用按鍵二和按鍵三調整報警的最低溫度加減;模式四是DS1302記錄的日期通過單片機顯示在數碼管上;模式五是DS1302記錄的時間通過單片機顯示在數碼管上。
仿真原理圖如下
單片機源程序如下:
#include #include"intrins.h" #define uchar unsigned char #define uint unsigned int sbit dula = P2^0; //數碼管引腳定義 sbit wela = P2^1; sbit DQ = P2^2; // sbit key1 = P2^5; sbit key2 = P2^6; sbit key3 = P2^7; sbit buzz = P2^3; sbit led = P3^7; sbit RST=P1^0; sbit DSIO=P1^1; sbit SCLK=P1^2; //定義ds1302使用的IO口 int bai,shi,ge; uchar fuhao,flag; uint ff,Hff=50,Lff=10; uchar count=0,t100ms=0,t500ms,t1s,t2s; uchar cishu=0; uchar jiange=0; uchar biaozhi1=0; //由低于下限到高于下限標志 uchar biaozhi2=0; //有高于上限到低于上限標志 uchar biaozhi3=0; //2s長鳴標志 uchar biaozhi4=0; uchar TIMEBCD[7] = {0x00, 0x00, 0x12, 0x1, 0x01, 0x01, 0x18}; //存儲順序是秒分時日月周年,存儲格式是用BCD碼 uchar TIME[7] = {0}; //十進制時間 //DS1302時鐘初始化2018年1月1日星期一12點00分00秒。 uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d}; uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c}; //DS1302寫入和讀取時分秒的地址命令(最低位控制讀寫) unsigned char code table[]={ 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f, 0x6f}; unsigned char code table1[]={ 0xbf,0x86,0xdb,0xcf, 0xe6,0xed,0xfd,0x87, 0xff, 0xef}; unsigned char code tablefu[]={ 0x40, 0x76 , 0x38 , 0x39 }; //數碼管符號 - H L C /*延時函數*/ void delayms(uint xms) { uint i,j; for(i=xms;i>0;i--) for(j=114;j>0;j--); } /*****溫度延時*****/ void Delaywendu(int num) { while(num--) ; } /*****初始化DS18B20*****/ void Init_DS18B20() { DQ = 1; //DQ復位 Delaywendu(8); //稍做延時 DQ = 0; //單片機將DQ拉低 Delaywendu(80); //精確延時,大于480us DQ = 1; //拉高總線 Delaywendu(40); } /*****讀一個字節*****/ uchar ReadOneChar() { uchar i=0; uchar dat = 0; for (i=8;i>0;i--) { DQ = 0; // 給脈沖信號 dat>>=1; DQ = 1; // 給脈沖信號 if(DQ) dat|=0x80; Delaywendu(4); } return(dat); } /*****寫一個字節*****/ void WriteOneChar(uchar dat) { uchar i=0; for (i=8; i>0; i--) { DQ = 0; DQ = dat&0x01; Delaywendu(5); DQ = 1; dat>>=1; } } /*****讀取溫度*****/ uint ReadTemperature() { uint a=0,b=0; int temp=0; float tt=0; Init_DS18B20(); WriteOneChar(0xCC); //跳過讀序號列號的操作 1100 1100 WriteOneChar(0x44); //啟動溫度轉換 0100 0100 Init_DS18B20(); WriteOneChar(0xCC); //跳過讀序號列號的操作 WriteOneChar(0xBE); //讀取溫度寄存器 1011 1110 a=ReadOneChar(); //讀低8位 b=ReadOneChar(); //讀高8位 temp=b; temp<<=8; temp=temp|a; if(temp&0xf800) { temp=~temp+1; fuhao=1; } else fuhao=0; tt=temp*0.0625; temp=tt*10+0.5; //放大10倍輸出并四舍五入 return(temp); } /*****讀取溫度*****/ void check_wendu() { uint f; f=ReadTemperature(); //獲取溫度值并減去DS18B20的溫漂誤差 ff=f; bai=f/100; shi=f %100/10; ge= f%10; } /****讀設定值*****/ void check_v_set(int v_set) { int bb; bb=v_set*10; bai=bb/100; shi=bb %100/10; ge= bb %10; } /*****顯示溫度子程序*****/ void display() { P0=0xff; wela=1; P0=0xfb; wela=0; dula=1; P0=table[bai]; dula=0; delayms(5); P0=0xff; wela=1; P0=0xf7; wela=0; dula=1; P0=table1[shi]; dula=0; delayms(5); P0=0xff; wela=1; P0=0xef; wela=0; dula=1; P0=table[ge]; dula=0; delayms(5); P0=0xff; wela=1; P0=0xdf; wela=0; dula=1; P0=tablefu[3]; dula=0; delayms(5); } void keyscan() { if(key1==0) { delayms(5); if(key1==0) { flag++; if(flag==5) flag=0; while(!key1); } } } int keyad(int num) { if(flag!=0) { if(key2==0) { delayms(5); if(key2==0) { num++; while(!key2); } } if(key3==0) { delayms(5); if(key3==0) { num--; while(!key3); } } } return num; } /**************************************************************/ /**************************日歷計時部分************************/ void Ds1302Write(uchar addr, uchar dat) //向DS1302發送命令(地址+數據) { uchar n; RST = 0; _nop_(); SCLK = 0;//先將SCLK置低電平。 _nop_(); RST = 1; //然后將RST(CE)置高電平。 _nop_(); for (n=0; n<8; n++)//開始傳送八位地址命令 { DSIO = addr & 0x01;//數據從低位開始傳送 addr >>= 1;
上一篇:ESP8266無線18B20溫度手機接收有源代碼和開源
下一篇:51單片機控制LCD12864顯示漢字
- 熱門資源推薦
- 熱門放大器推薦