` 用数码管与DS18B20设计温度报警器 我将这两天我写的 用数码管与DS18B20设计温度报警器 的程序贴上来,希望对正在研究或者刚开始学DS1802这个芯片的的兄弟们有所帮助。这个程序我写的很不好,但是功能基本上实现了。 #include #include #include #define uchar unsigned char #define uint unsigned int ***it DQ=P3^6; ***it sounder=P3^7; //定义蜂鸣器口 ***it D1=P1^4; //高温报警灯 ***it 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 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 `
|