用数码管与DS18B20设计温度报警器
用数码管与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这个芯片应用很广。也简单。
看看~
继续努力