这个博客名好长
参考了郭天祥的《51单片机》和一个学长的讲解
http://blog.csdn.net/xiaocheng_sky/article/details/50743176
DS18B20是支持一线总线接口的温度传感器,它与微处理器连接时仅需要一条口线即可实现与微处理器与DS18B20的双向通信 。可直接将温度转化为串行数字信号供处理器处理,测温范围在-55°~+125°,温度传感器的精度为用户可编程的9,10,11或12位,分别以0.5℃,0.25℃,0.125℃和0.0625℃增量递增。
与单片机相连:
所以只要控制P1^4口就可以了
工作原理:
DS18B20的所有通信都是以由复位脉冲组成的初始化序列开始的,并采用的是单总线协议。 DS18B20启动后保持低功耗等待状态,当需要执行温度测量(和AD转换)时,总线控制器必须发出[44h]命令。(44H,向DS18B20写入0x44的指令,启动DS18B20进行温度转化,结果保存入内部9字节的RAM。)
温度转换[44h]
该命令为初始化单次温度转换。温度转换完后,温度转换的数据存储在暂存寄存器RAM的2个字节长度的温度寄存器中,之后DS18B20恢复到低功耗的闲置状态。如果该设备是采用的“寄生电源“供电模式,在该命令执行10uS(最大)后主设备在温度转换期间必须强制拉高数据线(“DS18B20的供电”章节所描述)。如果该设备是采用的外部供电模式,主设备在温度转换命令之后可以执行读取数据时序,若DS18B20正在进行温度转换则会响应0电平,温度转换完成则响应1电平。在“寄生电源”供电模式下,因为在整个温度转换期间总线都是强制拉高的状态,故不会有上述响应。
【高速暂存缓存器RAM由9个字节存储器组成,温度值存储在前两个字节,读取后将二进制转化为10进制后再乘以0.0625便为所测的实际温度值】之后写入0xbe的指令,从RAM中读出温度数据。这个指令相当于一个开启读的命令,接下来就是读取的语句。
具体代码:
数据线定义为DQ或者ds。
对于DS18B20的操作基本就是三种类型:初始化,写时序,读时序。
延时函数: (15+15*z)us 的延时
(1)初始化:
这是学长的讲解和代码。
带返回值,有利于检验。
DS18B20检测到I/O口引脚上的升沿后,等待,然后以拉低总线的方式发出脉冲,此时DQ为0,ask被赋值。所以若是返回的ask值为0,DS18B20成功应答。这点学长写反了,我和他说然而他不愿意改哈哈,可能是想坑更多的人吧。若是有人看他的讲解前有幸看了我这个菜鸟的代码, 我想还是比较幸运的。(如果他后来改了就忽略这段话
(2)写时序
来自他的文章:
主机在写时隙向DS18B20写入数据,其中分为写”0”时隙,和写”1”时隙。总线主机使用写“1”时间隙向DS18B20写入逻辑1,使用写“0”时间隙向DS18B20写入逻辑0.所有的写时隙必须有最少60us的持续时间,相邻两个写时隙必须要有最少1us的恢复时间。两种写时隙都通过主机拉低总线产生(见下图)为了产生写1时隙。
在拉低总线后主机必须在15μs内释放总线。在总线被释放后,由于上拉电阻将总线恢复为高电平。为了产生写”0”时隙,在拉低总线后主机必须继续拉低总线以满足时隙持续时间的要求(至少60μs)。
在主机产生写时隙后,DS18B20会在其后的15~60us的一个时间段内采样单总线(DQ)。在采样的时间窗口内,如果总线为高电平,主机会向DS18B20写入1;如果总线为低电平,主机会向DS18B20写入0。
综上所述,所有的写时隙必须至少有60us的持续时间。相邻两个写时隙必须要有最少1us的恢复时间。所有的写时隙(写0和写1)都由拉低总线产生。
他的代码,哈哈丧心病狂,主要是我觉得这些没什么好再说的,我也补充不了什么
写字节函数、由低位至高位,向DS18B20写入一个字节的数据。
无返回值。
形参byte是待写入的字节数据,读取8次,移位8次,保证每位都传输至DQ
(3)读时序
主机发起读时序时,DS18B20仅被用来传输数据给控制器。因此,总线控制器在发出读暂存器指令[0xBE]或读电源模式指令[0xB4]后必须立刻开始读时序,DS18B20可以提供请求信息。除此之外,总线控制器在发出发送温度转换指令[0x44] (或召回EEPROM指令[0xB8])之后读时序,详见DS18B20 的芯片手册上的功能指令。
所有读时序必须最少60us,包括两个读周期间至少1us的恢复时间。当总线控制器把数据线从高电平拉到低电平时,读时序开始,数据线必须至少保持1us,然后总线被释放。DS18B20 通过拉高或拉低总线上来传输”1”或”0”。当传输逻辑”0”结束后,总线将被释放,通过上拉电阻回到上升沿状态。从DS18B20输出的数据在读时序的下降沿出现后15us 内有效。因此,总线控制器在读时序开始后必须停止把I/O口驱动为低电15us,以读取I/O口状态。
DS18B20的读时序的代码
读字节函数、由低位至高位,读取DS18B20所采集到的数据。
带返回值,可结合前面的写时序,对写、读数据函数进行检验(后面会提到检验过程及效果)
byte 是读取到的字节数据。其中,此函数读取8次,移位7次(实际移位8次)
具体再具体代码
忽略<>里的内容,文章发表后自动加上去的
主函数:
void main()
{
int j;
DS18B20_init();//初始化,这个可以写成int型返回值检测有没有回应
while(1)
{
tempchange();//温度zhun
for(j=10;j>0;j--)
{
dis_temp(get_temp());
}
}
}
函数:
void tempchange()
{
DS18B20_init();
delay(1);
tempwritebytle(0xcc);//写跳过读ROM指令
tempwritebytle(0x44);//写温度转化指令
}
关于这个0xcc的指令,
此时I/O口只连接了一个DS18B20。如果要控制多个DS18B20进行温度采集,只要将所有DS18B20的I/O口全部连接在一起就可以了。在具体操作时,通过读取每个DS18B20内部芯片的序列号来识别。
uint get_temp()
{
uchar a,b;
DS18B20_init();
delay(1);
tempwritebytle(0xcc);
tempwritebytle(0xbe);//读取暂存寄存器
a=tempreadbytle();
b=tempreadbytle();
temp=b;
temp<<=8;
temp=temp|a;//两个字节组合为一个字
f_temp=temp*0.0625;
temp=f_temp*10+0.5;//因为temp为整型,乘以10表示取小数点后取一位,加0.5四舍五入
f_temp=f_temp+0.05;
return temp;
}
数据存在寄存器的前两位,所以读取两次,将两个二进制整合为一个10进制数字后得到温度temp,再显示到数码管上。
void dis_temp(uint t)
{
uchar i;
i=t/100;
display(0,i);
i=t%100/10;
display(1,i+10);//加10为了显示小数点
i=t%10;
display(2,i);
}
void display(int wei,int duan)
{
P2=(P2&0X1F)|0XE0;
P0=0X00;
P2=(P2&0X1F);
P2=(P2&0X1F)|0XC0;
P0=DIG_PLACE[wei];
P2=(P2&0X1F);
P2=(P2&0X1F)|0XE0;
P0=tab[duan];
P2=(P2&0X1F);
delay(5);
}
定义们:
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
unsigned char tab[]= {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,//没有小数点
0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};//有小数点
unsigned char code DIG_PLACE[8] = {
0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
sbit ds=P1^4;
uint temp;
float f_temp;
这个tab是特制的
嗯组合起来可以直接烧录了
比赛成绩,不存在的,我都被打击得转行了。
悲伤。