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

发布者:火星叔叔最新更新时间:2015-06-15 来源: 51hei关键字:89S51  数字温度计  DS1302  18B20 手机看文章 扫描二维码
随时随地手机看文章




#include
#include
#include

#define uchar unsigned char
#define uint unsigned int
#define S_RST 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;TL1=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     ReadPower    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位超时检测处理
 TCON = 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-WIRE 总线上写一个字节
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<     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;
}

[page]
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 2 :if((sg<2)&&(sd==9))
     collect_time[2] &= 0x30;
     if((sg>=2)&&(sd==3))
     collect_time[2] &= 0x30;
     else {collect_time[2]++;}
     break;
   case 3: if(fg==5)
     collect_time[1] &= 0x0f;
     else {collect_time[1]+=16;}
     break;
   case 4: if(fd==9)
     collect_time[1] &= 0xf0;
     else {collect_time[1]++;}
     break;
   case 5: if(mg==5)
     collect_time[0] &= 0x0f;
     else {collect_time[0]+=16;}
     break;
   case 6: if(md==9)
     collect_time[0] &= 0xf0;
     else {collect_time[0]++;}
     break;
   }
  TR0=1;
  while(ADD==0);
  }
   }

 if(DEC==0&&keyboard==1)  //检测减调整键有无按下,并进行相应操作
   { 
    if(DEC==0&&keyboard==1)
  { RdefineT1; //超时检测初始化

  TR0=0; 
  switch (choose)
   {
   case 1 :if(sg==0)
      collect_time[2]=0x20;
     else collect_time[2]-=16;
     break;
   case 2 :if(sg<2&&sd==0)
      collect_time[2] |= 0x09;
     if(sg==2&&sd==0)
      collect_time[2] |= 0x03;
     else collect_time[2]-=1;
     break;
   case 3 :if(fg==0)
      collect_time[1] |= 0x50;
     else collect_time[1]-=16;
     break;
   case 4 :if(fd==0)
      collect_time[1] |= 0x09;
     else collect_time[1]-=1;
     break;
   case 5 :if(mg==0)
      collect_time[0] |= 0x50;
     else collect_time[0]-=16;
     break;
   case 6 :if(md==0)
      collect_time[0] |= 0x09;
     else collect_time[0]-=1;
     break;
   }
  TR0=1;
  while(DEC==0);
  }
   }
 }
 
if(choose!=0){TR1=1;STA=0;}  //在设置模式下停止采集时间
 else {TR1=0;STA=1;}
}

/********************************************************
*                                                      *
*                   AT89S51主程序段                    *
*                                                      *
********************************************************/
void main(void)
{
 Time01_Int();
 Dat_Int();
 
 EA = 1;  //开中断

 ow_reset();       // 开机先转换一次
 write_byte(0xCC); // Skip ROM
 write_byte(0x44); // 发转换命令
 delay(100);

 Set_Time(collect_time);
 delay(10);

while(1)
{
Scan();
deal();
}//while循环的结束
}//main函数的结束


void Time0_seve() interrupt 1  //定时器0中断服务程序
{
  uint timer;
  uchar i,ktemp;
if((P1&0x70)<0x70) //防抖控制用
  keyboard=1;
 else keyboard=0;

  timer++;
if(timer==800)//控制数码管的闪动效果
   {
 if(choose !=0)
   flash=~flash;
  else flash = 1;
  timer=0;
   }

  TR0=0;
  ktemp=P0;
 if(P0==0xfe)i=1;
 else if(P0==0xfd)i=2;
 else if(P0==0xfb)i=3;
 else if(P0==0xf7)i=4;
 else if(P0==0xef)i=5;
 else if(P0==0xdf)i=6;
 else if(P0==0xbf)i=7;
 else if(P0==0x7f)i=0;
 else i=1;

  ktemp=ktemp*2+1;
 if(ktemp==0xff)ktemp=0xfe;
  P0=ktemp;
  P2=display[i];
  TR0=1;
}

void Time1_seve() interrupt 3  //定时器1中断服务程序
{
  TR1=0;TH1=0;TL1=0;
  a++;
 if(a>4*ReDetectTime)
   {
     choose=0;
     a=0;
    Set_Time(collect_time);
  STA=1;  //超过按键等待时间,自动写入并开始采集时间
   }
}

关键字:89S51  数字温度计  DS1302  18B20 引用地址:基于89S51的实时数字温度计(DS1302 18B20)

上一篇:C8051F330 16*16点阵(SPI 、SMBus、I2C)PCF8563
下一篇:RF1100SE单片机C8051F310程序

推荐阅读最新更新时间:2024-03-16 14:03

PIC16F877A例程---DS1302程序
#include pic.h //调用头文件 //#include pic1687x.h __CONFIG(0x3F32); //芯片配置字 //__CONFIG(HS&UNPROTECT&PWRTEN&BORDIS&WDTDIS);//芯片配置字 //__CONFIG(0x3FFD&0x3FFF&0x3FF7&0x3FBF&0x3FFB);//芯片配置字 #define uchar unsigned char #define uint unsigned int //联接DS1302的端口定义 #define ds1302_rst RC2 //定义13
[单片机]
51单片机控制的数字温度计
总览部分 MCU部分 显示部分 开仿真以后实时显示温度 因为这个程序比较简单,我就直接上代码了,有不明白的请看我以前的文章,谢谢哦! 参考代码如下: #include “reg51.h” char disp ={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40}; char disp_dot ={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef,0xc0}; sbit DQ = P1^3; //定义通信端口 //晶振12MHz void delay_18B20(unsigned int i) {
[单片机]
51单片机控制的<font color='red'>数字温度计</font>
51单片机DS1302时钟芯片简单程序
#include reg51.h #include intrins.h #define uchar unsigned char #define uint unsigned int data_7seg ={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,}; uchar hour,min,sec; sbit shi=P1^0; sbit fen=P1^1; sbit miao=P1^2; sbit rst=P1^4; sbit sck=P1^5; sbit io=P1^6; sbit fm=P1^7; /*函数声明:*/ void write_ds1302_byte(ucha
[单片机]
一个简单的18B20程序
'////////////////////////////////////// '读取DS18B20温度数据,并在LCD上显示出来 '设计者 啊艺 '编译器BASCOM-AVR1.11.8.1 '////////////////////////////////////// $regfile = M16def.dat $crystal = 1000000 Config 1wire = Portb.7 '定义单总线器件的接口 Config Lcdpin = Pin , Db4 = Portb.2 , Db5 = Portb.3 , Db
[单片机]
89S51看门狗功能的使用方法与程序设计
在ATMEL的89S51系列的89S51与89C51功能相同。指令兼容。HEX程序无需任何转换可以直接使用。89S51只比89C51增加了一个看门狗功能。89S51的其它功能可以参见89C51的资料。   看门狗具体使用方法如下:   在程序初始化中向看门狗寄存器(WDTRST地址是0A6H)中先写入01EH,再写入0E1H。即可激活看门狗。 Org 0000 Ljmp begin Begin: Mov 0A6H,#01EH ;先送1E Mov 0A6H,#0E1H ;后送E1 ;在程序初始化中激活看门狗。 …… …… For: …… Mov 0A6H,#01EH ;先送1E Mov 0A6H,#0E1H ;后送E1 ;喂狗指令
[单片机]
单片机数字温度计的课程设计
绪论 1.1 背景 在日常生活及工农业生产中,经常要用到温度的检测及控制,传统的测温元件有热电偶和热电阻。而热电偶和热电阻测出的一般都是电压,再转换成对应的温度,需要比较多的外部硬件支持, 其缺点如下:1. 硬件电路复杂;2. 软件调试复杂;3. 制作成本高。为了提高对传感器的认识和了解,尤其是对温度传感器的深入研究以及其用法与用途,基于实用、广泛和典型的原则而设计了本系统。 1.2 设计目的 1.2.1掌握温度计,报警系统的设计、组装与调试方法。 1.2.2熟悉仿真软件(proteus)的使用。 1.2.3重点掌握单片机的使用及其各引脚的功能。 第二章 原理分析 2.1原理框图 protues仿真图 Protu
[单片机]
单片机<font color='red'>数字温度计</font>的课程设计
DS1302读写驱动程序
/************************** 文件所用资源 1.端口:P0.4,P0.5,P0.6 2.调用delay_ms函数 **************************/ /*********************** 1302引脚定义 ***********************/ sbit T_RST = P0^4; sbit T_DAT = P0^5; sbit T_CLK = P0^6; /******************************** 1302子程序区 ********************************/ /***************************
[单片机]
DS1302时钟芯片的MSP430程序
//MSP430 Advanced Developping Components - ////DS1302 Trickle Charge Timekeeping Chip //MSP430高级实验开发组件 - DS1302时钟芯片 //时钟设置: ////ACLK=N/A,MCLK=SMCLK=default(DCO~800k) //硬件连接: //// MSP430 MCU DS1302 //// ------------------ ------------------ //// | P20 | ------ | SCLK
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved