创建好“ds18b20.c”和“ds18b20.h”文件,把下面代码添加进各自的文件。
1.ds18b20.c代码
我们在宋老师的代码基础上添加了温度转换函数,原理在上一讲已经讲解清楚了。
#include #include #include unsigned char temp_i=0;//定义全局变量temp_i用来帮助液晶屏灵活显示 /* 软件延时函数,延时时间(t*10)us */ void DelayX10us(unsigned char t) { do { _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); } while (--t); } /* 复位总线,获取存在脉冲,以启动一次读写操作 */ unsigned char Get18B20Ack() { unsigned char ack; EA = 0; //禁止总中断 IO_18B20 = 0; //产生500us复位脉冲 DelayX10us(50); IO_18B20 = 1; DelayX10us(6); //延时60us ack = IO_18B20; //读取存在脉冲 while(!IO_18B20); //等待存在脉冲结束 EA = 1; //重新使能总中断 return ack; } /* 向DS18B20写入一个字节,dat-待写入字节 */ void Write18B20(unsigned char dat) { unsigned char mask; EA = 0; //禁止总中断 for (mask=0x01; mask!=0; mask<<=1) //低位在先,依次移出8个bit { IO_18B20 = 0; //产生2us低电平脉冲 _nop_(); _nop_(); if ((mask&dat) == 0) //输出该bit值 IO_18B20 = 0; else IO_18B20 = 1; DelayX10us(6); //延时60us IO_18B20 = 1; //拉高通信引脚 } EA = 1; //重新使能总中断 } /* 从DS18B20读取一个字节,返回值-读到的字节 */ unsigned char Read18B20() { unsigned char dat; unsigned char mask; EA = 0; //禁止总中断 for (mask=0x01; mask!=0; mask<<=1) //低位在先,依次采集8个bit { IO_18B20 = 0; //产生2us低电平脉冲 _nop_(); _nop_(); IO_18B20 = 1; //结束低电平脉冲,等待18B20输出数据 _nop_(); //延时2us _nop_(); if (!IO_18B20) //读取通信引脚上的值 dat &= ~mask; else dat |= mask; DelayX10us(6); //再延时60us } EA = 1; //重新使能总中断 return dat; } /* 启动一次18B20温度转换,返回值-表示是否启动成功 */ unsigned char Start18B20() { unsigned char ack; ack = Get18B20Ack(); //执行总线复位,并获取18B20应答 if (ack == 0) //如18B20正确应答,则启动一次转换 { Write18B20(0xCC); //跳过ROM操作 Write18B20(0x44); //启动一次温度转换 } return !ack; //ack==0表示操作成功,所以返回值对其取非,返回值就是1了 } /* 读取DS18B20转换的温度值,返回值-表示是否读取成功 */ unsigned char Get18B20Temp(int *temp) { unsigned char ack; unsigned char LSB, MSB; //16bit温度值的低字节和高字节 ack = Get18B20Ack(); //执行总线复位,并获取18B20应答 if (ack == 0) //如18B20正确应答,则读取温度值 { Write18B20(0xCC); //跳过ROM操作 Write18B20(0xBE); //发送读命令 LSB = Read18B20(); //读温度值的低字节 MSB = Read18B20(); //读温度值的高字节 *temp = ((unsigned int)MSB << 8) + LSB; //合成为16bit整型数 } return !ack; //ack==0表示操作成功,所以返回值对其取非,返回值就是1了 } /* 温度转换 */ unsigned char TEMP_CONV(unsigned int *temp, unsigned char *str) { unsigned char res; float temp_float; res = Get18B20Temp(temp); //读取当前温度,传入的参数是指针类型 if (res) //读取成功时,进行温度转换 { if( (*temp>>11)==0 ) //温度大于等于0度 { temp_float=( (float)(*temp) ) *0.0625*10.0; //*temp就是没有转换时的16位那个变量,然后再把实际温度值再乘以10倍 *temp=(unsigned int)temp_float; //得到16位整型的数值 str[0]='0'+( (*temp/1000)%10 ); //当温度大于等于100度时需要显示百位数 str[1]='0'+( (*temp/100)%10 ); //当温度大于等于10度时需要显示十位数 str[2]='0'+( (*temp/10)%10 ); //当温度大于等于1度时需要显示个位数 str[3]='.'; str[4]='0'+( (*temp)%10 ); //温度必须显示小数点后的一位 if(str[0]=='0')temp_i++; if(str[1]=='0')temp_i++; return 1;//读取温度成功,返回值一律为1 } else if( (*temp>>11)>0 )//温度小于0度 { *temp=(*temp)&0x07FF; //清除掉高5位使其变为0 *temp=2048-(*temp); //此时的temp为补码 temp_float=( (float)(*temp) )*0.0625*10.0; //实际温度值再乘以10倍 *temp=(unsigned int)temp_float; //得到16位整型的数值 str[0]='-'; //添加负数的符号 str[1]='0'+( (*temp/100)%10 ); //当温度在-10度以下时需要显示十位数 str[2]='0'+( (*temp/10)%10 ); //温度必须显示个位数,哪怕是0,比如“-0.5” str[3]='.'; str[4]='0'+( (*temp)%10 ); //温度必须显示小数点后的一位 if(str[1]=='0') { str[1]='-'; temp_i=1;//实际温度大于-10.0度的时候,假如是-5.4度,那么“LcdShowStr(0, 0, str+temp_i);”就是显示“-5.4”,小数点就是在第3个显示格上显示 //实际温度小于等于-10.0度的时候,假如是-12.6度,str[1]不等于‘0’, //这样temp_i是等于0的,那么“LcdShowStr(0, 0, str+temp_i);”显示“-12.6”,小数点就是在第4个显示格上显示 } return 1; //读取温度成功,返回值一律为1 } } return 0;//读取温度不成功,返回值为0 } 2.ds18b20.h代码 #ifndef __DS18B20_H__ #define __DS18B20_H__ sbit IO_18B20 = P3^2; //DS18B20通信引脚
上一篇:51单片机-温度传感器代码解析Ⅱ
下一篇:51单片机-AD与DA合成文件
推荐阅读最新更新时间:2024-11-19 06:45
设计资源 培训 开发板 精华推荐
- LTC2192IUKG、16 位、65Msps 低功耗双通道 ADC 的典型应用
- EV-AD7768-1FMCZ,用于评估具有功率调节功能的 AD7768-1 24 位、256 kSPS、Sigma-Delta ADC 的评估板
- LTC2908CDDB-A1、3.3V、2.5V、1.8V、1.2V四路电源监视器的典型应用电路
- 1.2V DC 至 DC 单路输出电源,适用于台式电脑电源
- EVAL-AD7321CBZ,AD7321 评估板,13 位,500 KSPS,2CH ADC
- NX4108 1A 同步降压开关电路 (VOUT=2.5V) 电路板上带有 FET 的典型应用
- 使用 Analog Devices 的 LTC1728HS5-5 的参考设计
- 全金属化镊子尖
- AM2F-2407SH30Z 7.2V 2 瓦 DC/DC 转换器的典型应用
- AD8316ACP-EVAL,AD8316 评估板,0.1GHz 至 2.5GHz,70dB 对数检波器/控制器