微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 用数码管与DS18B20设计温度报警器

用数码管与DS18B20设计温度报警器

时间:10-02 整理:3721RD 点击:

                         用数码管与DS18B20设计温度报警器

                              我将这两天我写的  用数码管与DS18B20设计温度报警器  的程序贴上来,希望对正在研究或者刚开始学DS1802这个芯片的的兄弟们有所帮助。这个程序我写的很不好,但是功能基本上实现了。

#include<reg51.h>

#include<intrins.h>

#include<math.h>

#define uchar unsigned char

#define uint  unsigned int

sbit DQ=P3^6;

sbit sounder=P3^7; //定义蜂鸣器口

sbit D1=P1^4;        //高温报警灯

sbit D2=P1^5;       //低温报警灯

uchar temperature1,temperature0,TH,TL;

float tt;                     //注意变量类型

int t;                               //注意变量类型

uint count0,count1;

int baojing[]={700,-200};//注意这里,是把高温值*10,低温值*10      

uchar code smg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};      //共阴极数码管编码

uchar codesmg1[]={0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0xF7,0xFC,0xB9,0xDE,0xF9,0xF1};//带小数点共阴极数码管编码

void delayms(int j)

{

                         intaa,kk;

                         for(aa=0;aa<j;aa++)

                            for(kk=120;kk>0;kk--);

}

void delay5us()     //延时5us

{

                         _nop_();

}

void delay10us()//延时10us,主函数调用delay10us( )时,先执行一个LCALL指令(2 μs),然后执行6个_nOP_()语句(6 μs),最后执行了一个RET指令(2μs),所以执行上述函数时共需要10 μs。

{                        

                         _nop_();

                         _nop_();

                         _nop_();

                         _nop_();

                         _nop_();

                         _nop_();

}

void delay102us()     //延时102us

{

                         delay10us();

                         delay10us();

                         delay10us();

                         delay10us();

                         delay10us();

                         delay10us();

                         delay10us();

                         delay10us();

                         delay10us();

                         delay10us();

}

void delay614us()                 //延时614us

{

                         delay102us();

                         delay102us();

                         delay102us();

                         delay102us();

                         delay102us();

                         delay102us();

}

/********************DS18B20初始化操作***************************/

uchar init_DS18B20()

{

                         ucharstatus ;

                         DQ=1;

                         delay10us();       //延时10us

                         DQ=0;

                         delay614us();

                         DQ=1;              //延时等待30us

                         delay10us();

                         delay10us();

                         delay10us();

                         status=DQ;  //这个时间一定要长最少204us

                         delay102us();

                         delay102us();

                         delay102us();

                         delay102us();

                         DQ=1;               //最后总线又拉高

                         returnstatus;

}  

/**************************DS18B20读操作*****************************/

uchar DS18B20_readbyte()

{                        

                         uchari,dat=0;

                         DQ=1;

    _nop_();       //稍微延时1us

                         for(i=0;i<8;i++)

                         {

                            DQ=0;            //最少延时1us

                            _nop_();

                            _nop_();

                            _nop_();

                            dat>>=1;

                            DQ=1;      

                            _nop_();

                            _nop_();

                            if(DQ)dat|=0x80;

                            else

                            dat=dat|0x00;

/****下面的延时时间一定要搞仔细了,时间太短会闪烁,估计是每两个读之间必须得隔离相当长的时间*****/               

                            delay102us();

                            delay102us();

                            delay102us();

                            delay102us();  

                            DQ=1;       //数据线拉高

                         }

                         returndat;

}

/**************************************DS18B20写操作************************************/

void DS18B20_writebyte(uchar dat)

{

                         uchar i;

                         for(i=0;i<8;i++)

                         {

                           

                            DQ=0;

                            DQ=dat&0x01;   //要延时确定时间15us

                            delay10us();

                            delay5us();

                            dat>>=1;         //延时为45us     ,同时需要注意写的时候是一位一位的写。

                            delay10us();

                            delay10us();

                            delay10us();

                            delay10us();

                            delay5us();

                            DQ=1;

                         }

                         DQ=1;                      //数据线最后又拉高

}

/************************************读取DS18B20当前温度值***********************************/

void  read_temperature()

{

                         if(init_DS18B20()==0)

                         {

                            DS18B20_writebyte(0xcc);    //跳过ROM

                            DS18B20_writebyte(0x44);    //温度转换

                          }

                         if(init_DS18B20()==0)                   //注意啊,每一次读写操作都得先要将DS18B20初始化,而且还得确保初始化成功

                          {                                 

                            DS18B20_writebyte(0xcc);    //跳过ROM               

                            DS18B20_writebyte(0xbe);   //读取RAM中温度

                            temperature0=DS18B20_readbyte();

                            temperature1=DS18B20_readbyte();

                         }

                        

}

/***********************************数码管显示函数**********************************/

void xianshi()

{                        

                         uchar  bai,shi,ge,i;

                         uintwendu;

                         read_temperature();

                         t=temperature1;

                         t<<=8;        //两个字节合并成一个字

                         t=t|temperature0;

                         tt=t*0.0625;

                         t=tt*10+(t>0?0.5:-0.5);//这一步猛然很难理解,这里面还包括着变量的强制转换,注意tt是float型,t是uint型。强制转换后会舍弃小数点后面的数。乘以10表示保留小数点后一位,加0.5是四舍五入。

                         TH=t>=baojing[0]?1:0;      

                         TL=t<=baojing[1]?1:0;

                         wendu=abs(t);

                         bai=wendu/100;//为温度10位

                         shi=wendu/10%10;//为温度个位

                         ge=wendu%10;//为温度后小数点位

                         for(i=0;i<30;i++)             //此处可以让按键不那么敏感,不至于按得太快让数码管显示出错,显示更稳定

                         {

                            if(t<0)

                            {

                                   P2=0xfb;

                                   P0=0x40;

                                   delayms(2);

                            }

                            P2=0xff;

                            P2=0xf7;

                            P0=smg[bai];

                            delayms(2);

                            P2=0xef;

                            P0=smg1[shi];

                            delayms(2);

                            P2=0xdf;

                            P0=smg[ge];

                            delayms(2);

                            P2=0xbf;

                            P0=0x63;

                            delayms(2);

                            P2=0x7f;

                            P0=0x39;

                            delayms(2);

                         }

}                           

void main()

{

                         D1=1;

                         D2=1;

                         sounder=0;   

                         P2=0x00;

                         P0=0x00;

                         TMOD=0x11;

                         TH0=-(1000/256);

                         TL0=-(1000%256);

                         TH1=-(1000/256);

                         TL1=-(1000%256);

                         ET0=1;

                         ET1=1;

                         EA=1;

                         TR1=0;

                         TR0=0;

                         read_temperature();

                         while(1)

                         {

                            read_temperature();

                            xianshi();

                            if(TH==1)TR0=1;   //如果这里不用定时中断功能来处理报警 而是直接能把程序写在下面的话,会导致数码管显示闪烁。因此,这又是一招!

                            else   TR0=0;

                            if(TL==1)TR1=1;

                            else      TR1=0;

                           

                         }

}

void ET0_time1() interrupt 1

{

                         TH0 =-(1000 / 256);

                         TL0 =-(1000 % 256);

                         sounder=~sounder;

                         if(++count0== 400)

                         {

                            count0= 0;

                            if(TH)     D1= ~D1;       else  D1 = 1;

                         }

}                          

void ET1_time1()interrupt 3

{

                         TH1 =-(1000 / 256);

                         TL1 =-(1000 % 256);

                         sounder=~sounder;

                         if(++count1== 400)

                         {

                            count1= 0;

                            if(TL)     D2 = ~D2;      else  D2 = 1;

                         }

}

/**************************************************************************

后记:这两天半的课外时间全花在这题上了,真心感觉温度传感器DS18B20很特殊。本题我在处理报警功能时,没有向DS18B20写入报警值,因为写入报警值后还得读值。刚开始我也是那样做的,

但是不知是程序没写好还是程序之间组合的不好,没有效果。所以,本题就干脆没有写报警值,直接外部判断。

由于刚接触DS18B20,所以以上程序写的很乱,很繁琐。 还话说,DS18B20这个芯片我还是没有真正熟悉理解它!

感谢网上热心分享资料的前辈们

参考资料:

DS18B20的百度百科

郭天祥的书

**************************************************************************/   

                        

                        

                                                                                                     胡海松

                                                                                                     2013.3.1

                        

                        


下面是proteus仿真图                             

仿真图


里面有很多不对的地方希望大家指教

999999999999999999999999999999999

延时函数太麻烦了

DS18B20的时序要求比较严格,你有什么更好的办法吗?求教

菜鸟进来学习下
主要是照抄

菜鸟进来学习下

厉害

话说,有没有多点的测温电路

其实不用这么多行延时语句。
void Delay(unsigned int x)
{
        while(x--);
}
x的具体数值多少得经过测试才确定。

嗯,我试试

这个还没有接触到

延时子函数加个入口参数,要延时多少就填多少
/********************************************************************************************
* 函数名称:DelaymS()
* 功    能:1mS延时函数
* 入口参数:16位整型     延时时间(mS)
* 出口参数:无
*********************************************************************************************/
void DelaymS(uint16 b){
uint8 i;
while( --b != 0){
  for(i = 0; i < 92; i++);
}
}

18B20这个芯片应用很广。也简单。

看看~

继续努力

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top