本系統由AT89C51單片機、DS18B20溫度檢測部分、DS1302日期時間記錄部分、數碼管顯示部分、按鍵輸入部分和蜂鳴器報警部分組成。該系統通過按鍵一來調整模式,共五個模式。模式一是DS18B20采集環境溫度并保存在存儲器中通過單片機將溫度顯示在數碼管上,當溫度低于下限或高于上限時蜂鳴器報警;模式二是利用按鍵二和按鍵三調整報警的最高溫度加減;模式三是利用按鍵二和按鍵三調整報警的最低溫度加減;模式四是DS1302記錄的日期通過單片機顯示在數碼管上;模式五是DS1302記錄的時間通過單片機顯示在數碼管上。
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
WIM2E$E6{`DF5)EBBJUR~2U.png (96.44 KB, 下載次數: 94)
下載附件
2019-4-9 19:01 上傳
單片機源程序如下:
- #include <reg52.h>
- #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;
- SCLK = 1;//數據在上升沿時,DS1302讀取數據
- _nop_();
- SCLK = 0;
- _nop_();
- }
- for (n=0; n<8; n++)//寫入8位數據
- {
- DSIO = dat & 0x01;
- dat >>= 1;
- SCLK = 1;//數據在上升沿時,DS1302讀取數據
- _nop_();
- SCLK = 0;
- _nop_();
- }
-
- RST = 0;//傳送數據結束
- _nop_();
- }
- uchar Ds1302Read(uchar addr) //讀取一個地址的數據
- {
- uchar n,dat,dat1;
- RST = 0;
- _nop_();
- SCLK = 0;//先將SCLK置低電平。
- _nop_();
- RST = 1;//然后將RST(CE)置高電平。
- _nop_();
- for(n=0; n<8; n++)//開始傳送八位地址命令
- {
- DSIO = addr & 0x01;//數據從低位開始傳送
- addr >>= 1;
- SCLK = 1;//數據在上升沿時,DS1302讀取數據
- _nop_();
- SCLK = 0;//DS1302下降沿時,放置數據
- _nop_();
- }
- _nop_();
- for(n=0; n<8; n++)//讀取8位數據
- {
- dat1 = DSIO;//從最低位開始接收
- dat = (dat>>1) | (dat1<<7);
- SCLK = 1;
- _nop_();
- SCLK = 0;//DS1302下降沿時,放置數據
- _nop_();
- }
- RST = 0;
- _nop_(); //以下為DS1302復位的穩定時間
- SCLK = 1;
- _nop_();
- DSIO = 0;
- _nop_();
- DSIO = 1;
- _nop_();
- return dat;
- }
- void Ds1302ReadTime() //讀取時鐘信息
- {
- uchar n;
- for (n=0; n<7; n++)//讀取7個字節的時鐘信號:分秒時日月周年
- {
- TIMEBCD[n] = Ds1302Read(READ_RTC_ADDR[n]);
- TIME[n] = TIMEBCD[n]/16*10+TIMEBCD[n]%16;
- }
- }
- void Ds1302Init() // 初始化DS1302
- {
- uchar n;
- Ds1302ReadTime(); //首次讀取時間
- if(TIME[5]==0) //判斷時間值是否有效
- {
- Ds1302Write(0x8E,0X00); //禁止寫保護,就是關閉寫保護功能
- for (n=0; n<7; n++)//寫入7個字節的時鐘信號:分秒時日月周年
- {
- Ds1302Write(WRITE_RTC_ADDR[n],TIMEBCD[n]);
- }
- Ds1302Write(0x8E,0x80); //打開寫保護功能
- }
- }
- void displaytime()
- {
- P0=0xff;
- wela=1;
- P0=0xfe;
- wela=0;
- dula=1;
- P0=table[TIME[2]/10];
- dula=0;
- delayms(5);
- P0=0xff;
- wela=1;
- P0=0xfd;
- wela=0;
- dula=1;
- P0=table1[TIME[2]%10];
- dula=0;
- delayms(5);
-
- P0=0xff;
- wela=1;
- P0=0xfb;
- wela=0;
- dula=1;
- P0=table[TIME[1]/10];
- dula=0;
- delayms(5);
-
- P0=0xff;
- wela=1;
- P0=0xf7;
- wela=0;
- dula=1;
- P0=table1[TIME[1]%10];
- dula=0;
- delayms(5);
- P0=0xff;
- wela=1;
- P0=0xef;
- wela=0;
- dula=1;
- P0=table[TIME[0]/10];
- dula=0;
- delayms(5);
- P0=0xff;
- wela=1;
- P0=0xdf;
- wela=0;
- dula=1;
- P0=table1[TIME[0]%10];
- dula=0;
- delayms(5);
- }
- void displaydate()
- {
- P0=0xff;
- wela=1;
- P0=0xfe;
- wela=0;
- dula=1;
- P0=table[TIME[6]/10];
- dula=0;
- delayms(5);
- P0=0xff;
- wela=1;
- P0=0xfd;
- wela=0;
- dula=1;
- P0=table1[TIME[6]%10];
- dula=0;
- delayms(5);
-
- P0=0xff;
- wela=1;
- P0=0xfb;
- wela=0;
- dula=1;
- P0=table[TIME[4]/10];
- dula=0;
- delayms(5);
-
- P0=0xff;
- wela=1;
- P0=0xf7;
- wela=0;
- dula=1;
- P0=table1[TIME[4]%10];
- dula=0;
- delayms(5);
- P0=0xff;
- wela=1;
- P0=0xef;
- wela=0;
- dula=1;
- P0=table[TIME[3]/10];
- dula=0;
- delayms(5);
- P0=0xff;
- wela=1;
- P0=0xdf;
- wela=0;
- dula=1;
- P0=table1[TIME[3]%10];
- dula=0;
- delayms(5);
- }
- /*主函數*/
- void main()
- {
-
- int z;
- buzz=1; //低電平響,
- led=0;
- TMOD=0x01;//設置定時器0工作模式1
- TH0=(65536-50000)/256;//定時器裝初值
- TL0=(65536-50000)%256;
- EA=1; //開總中斷
- ET0=1; //開定時器0中斷
- Ds1302Init( );
- for(z=0;z<100;z++)
- {
- check_wendu();
- }
- TR0=1;
- while(1)
- {
- keyscan();
- if(flag==0)
- {
- check_wendu();
- if(fuhao==1) //當溫度值為負數
- {
- P0=0xff;
- wela=1;
- P0=0xfd;
- wela=0;
- dula=1;
- P0=tablefu[0];
- dula=0;
- delayms(5); //顯示負
- }
- else
- {
- P0=0xff;
- wela=1;
- P0=0xfd;
- wela=0;
- dula=1;
- P0=0x00;
- dula=0;
- delayms(5); //顯示正
- }
- display();
- }
- else if(flag==1)
- {
- Hff=keyad(Hff);
- check_v_set(Hff);
-
- P0=0xff;
- wela=1;
- P0=0xfe;
- wela=0;
- dula=1;
- P0=tablefu[1];
- dula=0;
- delayms(5); //顯示H
- display();
- }
- else if(flag==2)
- {
- Lff=keyad(Lff);
- check_v_set(Lff);
- P0=0xff;
- wela=1;
- P0=0xfe;
- wela=0;
- dula=1;
- P0=tablefu[2];
- dula=0;
- delayms(5); //顯示L
- display();
- }
- else if(flag==3)
- {
- Ds1302ReadTime();
- delayms(10);
- displaydate();
- }
- else if(flag==4)
- {
- Ds1302ReadTime();
- delayms(10);
- displaytime();
-
- }
- }
- }
- /*中斷函數*/
- void timer0() interrupt 1//定時器0中斷服務程序
- {
- TH0=(65536-50000)/256;//再次裝定時器初值
- TL0=(65536-50000)%256;
- count++; //中斷次數累加 //50毫秒
- // ff=ReadTemperature();
- if(count%2==0)
- {
- t100ms = 1;
- }
- if(count%10==0)
- {
- t500ms = 1;
- }
- if(count%20==0)
- {
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
test1.zip
(156.81 KB, 下載次數: 173)
2019-4-9 18:59 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|