资讯详情

基于89S51的实时数字温度计(DS1302 18B20)

#include<reg51.h> #include<intrins.h> #include<math.h>

#define uchar unsigned char #define uint unsigned int #define S_R DS_RST=1 #define C_RST DS_RST=0 #define S_CLK DS_CLK=1 #define C_CLK DS_CLK=0 #define Write_Disable RW_DS1302(0x8e,0x80) //写保护 #define Write_Enable RW_DS1302(0x8e,0x00) //允许写入

sbit SET = P1^5; //设置按键 sbit ADD = P1^4; //调整加 sbit DEC = P1^6; //调整减 #define RdefineT1 TH1=0;=0;TR1=0;a=0; //初始化超时检测

//#define Delay2us() _nop_();_nop_(); //延时2us,每nop 1us //#define Delay8us() _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();

#define ReDetectTime 20 //设置重复检测次次数,超出次数则超时

//ds18b20命令 #define SkipROM 0xCC #define MatchROM 0x55 #define ReadROM 0x33 #define SearchROM 0xF0 #define AlarmSearch 0xEC

#define Convert 0x44 //启动温度转换 #define WriteScr 0x4E #define ReadScr 0xBE #define CopyScr 0x48 #define RecallEE 0xB8 #define Read 0xB4

#define md collect_time[0]&0x0f #define mg (collect_time[0]&0x70)/16 #define fd collect_time[1]&0x0f #define fg (collect_time[1]&0x70)/16 #define sd collect_time[2]&0x0f #define sg (collect_time[2]&0x30)/16

sbit DS_RST = P1^2; //DS复位端 sbit DS_CLK = P1^0; //SCLK端 sbit DS_IO = P1^1; //IO端 sbit DS18B20 = P1^3; //

bit keyboard,flash,STA=1; uchar choose,a; uchar collect_time[3]={0x45,0x23,0x11};//定义变量秒分时 uchar collect_temperature[2] = {0}; uchar num[10] = {0x7e,0x48,0x3d,0x6d,0x4b,0x67,0x77,0x4c,0x7f,0x6f}; //七段显示的段码 uchar display[8] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08};

void delay(uint i) { uint k; while(i--) { for(k=0;k<120;k++){;} } }

void Dat_Int(void)//数据初始化 { P0=0xff; P1=0xff; P2=0xff; choose=0; flash=1; }

void Time01_Int(void) { TMOD = 0x12; //定时器0为8位自动重载定时采样,定时器1为16位超时检测处理 TC = 0x00; TH0 = 0x60; TL0 = 0x60; TR0 = 1;

IE = 0x0a; //允许定时器0、1中断 IP = 0x00; }

/******************************************************** * * * DS18B20温度程序段 * * * ********************************************************/ /***********11微秒延时函数**********/ // void delayus(uint t) { for(;t>0;t--); }

/***********18B20复位函数**********/ void ow_reset(void) { char presence=1; while(presence) { while(presence) { DS18B20 = 1;_nop_();_nop_(); DS18B20 = 0; delayus(50); // 550us DS18B20 = 1; delayus(6); // 66us presence=DS18B20; // presence=0继续下一步 } delayus(45); //延时500us presence = ~DS18B20; } DS18B20 = 1; }

/**********18B20写命令函数*********/ //向 1-WE 总线上写一个字节 void write_byte(uchar val) { uchar i; for (i=8; i>0; i--) // { DS18B20 = 1;_nop_();_nop_(); DS18B20 = 0;_nop_();_nop_();_nop_();_nop_();_nop_();//5us DS18B20 = val&0x01; //最低位移出 delayus(6); //66us val=val/2; //右移一位 } DS18B20 = 1; delayus(1); } // /*********18B20读1个字节函数********/ //从总线上读取一个字节 uchar read_byte(void) { uchar i; uchar value = 0; for (i=8;i>0;i--) { DS18B20 = 1;_nop_();_nop_(); value>>=1; DS18B20 = 0; // _nop_();_nop_();_nop_();_nop_(); //4us DS18B20 = 1;_nop_();_nop_();_nop_();_nop_(); //4us if(DS18B20)value|=0x80; delayus(6); //66us } DS18B20 = 1; return(value); } // /***********读出温度函数**********/ // void Ds18b20_ReadEE(void) { ow_reset(); write_byte(SkipROM); // Skip ROM write_byte(Convert); // 发转换命令 ow_reset(); //总线复位 write_byte(SkipROM); // 发Skip ROM命令 write_byte(ReadScr); // 发读命令 collect_temperature[0]=read_byte(); //温度低8位 collect_temperature[1]=read_byte(); //温度高8位 }

/******************************************************** * * * DS1302时钟芯片程序段 * * * ********************************************************/ void DS1302_InputByte(uchar byte) //往DS1302写入1Byte数据 { uchar i; uchar temp; temp = byte; for(i=8; i>0; i--) { DS_IO = temp&0x01; S_CLK; C_CLK; temp = temp >> 1; } }

uchar DS1302_OutputByte(void) //从DS1302读取1Byte数据 { uchar i; uchar temp=0;

for(i=0; i<8;i++) { C_CLK; if(DS_IO!=0) temp|=(1<<i); S_CLK; } return(temp); }

void RW_DS1302(uchar reg, uchar byte)//向DS1302寄存器写数据 { C_RST; C_CLK; S_RST; DS1302_InputByte(reg); DS1302_InputByte(byte); S_CLK; C_RST; }

uchar Read_DS1302(uchar reg)//从DS1302寄存器读数据 { uchar byte; C_RST; C_CLK; S_RST; DS1302_InputByte(reg); byte = DS1302_OutputByte(); S_CLK; C_RST; return(byte); }

void GetTime_DS1302(uchar *ucCurtime) //读取DS1302当前时间 {

ucCurtime[0] = Read_DS1302(0x81);//格式为: 秒 分 时 ucCurtime[1] = Read_DS1302(0x83); ucCurtime[2] = Read_DS1302(0x85); }

void Set_Time(uchar *receive) //写时间 { Write_Enable; //控制命令,允许写操作

RW_DS1302(0x80,receive[0]); RW_DS1302(0x82,receive[1]); RW_DS1302(0x84,receive[2]);

Write_Disable; // 控制命令,写保护 }

/******************************************************** * * * 数码管显示程序段 * * * ********************************************************/ void deal(void)//送显前的数据处理 {uint timer2; uint lstemp; timer2++;

if(STA) {GetTime_DS1302(collect_time);} if(flash)//用于闪动效果的控制的 { display[0] = num[sg]; display[1] = num[sd]; display[2] = num[fg]; display[3] = num[fd]; display[4] = num[mg]; display[5] = num[md]; } else {switch(choose) { case 1:display[0]=0;break; case 2:display[1]=0;break; case 3:display[2]=0;break; case 4:display[3]=0;break; case 5:display[4]=0;break; case 6:display[5]=0;break; } } if(timer2==3000)//间断性获取温度 { timer2=0; if(STA) {TR0=0; Ds18b20_ReadEE(); TR0=1; } } if(collect_temperature[1]>127) { collect_temperature[0]=255-collect_temperature[0]; collect_temperature[1]=255-collect_temperature[1]; } lstemp=((collect_temperature[0])>>4)|((collect_temperature[1])<<4);

display[6] = num[(uchar)((lstemp)/10)]; display[7] = num[(uchar)((lstemp)%10)];

}

/******************************************************** * * * 按键控制程序段 * * * ********************************************************/

void Scan(void) { if(SET==0&&keyboard==1) //检测设置键有无按下,并进行相应操作 { if(SET==0&&keyboard==1) { RdefineT1; //超时检测初始化 choose++; while(SET==0); if(choose==7) {TR0=0; Set_Time(collect_time); TR0=1; STA=1; //设置完毕,重新开始采集时间 choose=0; } } }

if(choose) //只有在时间调整时,加减按键才有作用 { if(ADD==0&&keyboard==1) //检测加调整键有无按下,并进行相应操作 { if(ADD==0&&keyboard==1) { RdefineT1; //超时检测初始化a=0 TR0=0; switch (choose) { case 1 :if(sg==2) collect_time[2] = collect_time[2]&0x0f; else {collect_time[2]+=16;} break; case

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台