DS18B20使用的是一种比较特殊的传输协议,仅需一个接线口就能实现通信
DS18B20独特的单线接口仅需一个端口引脚进行通讯,这让每一个学习到这里的人都感到很神奇。在这片文章中我们将通过学习18B20的数据传输方式来为IIC协议做下铺垫。
提示:以下是本篇文章正文内容,下面案例可供参考
达拉斯DS18B20
半导体可编程分辨率的单总线®数字温度计
DS18B20 数字温度计提供9-12 位摄氏温度测量而且有一个由高低电平触发的可编程的不因电源消失而改变的报警功能。DS18B20通过一个单线接口发送或接受信息,因此在中央处理器和DS18B20 之间仅需一条连接线(加上地线)。它的测温范围为-55~+125℃,并且在-10~+85℃精度为±5℃。除此之外,DS18B20能直接从单线通讯线上汲取能量,除去了对外部电源的需求。
每个 DS18B20 都有一个独特的64 位序列号,从而允许多只DS18B20 同时连在一根单线总线上;因此,很简单就可以用一个微控制器去控制很多覆盖在一大片区域的DS18B20。这一特性在HVAC 环境控制、探测建筑物、仪器或机器的温度以及过程监测和控制等方面非常有用。
清翔51开发板接口:
这里值得注意的是,就算将18B20的接口接反也不会使该模块烧坏,但是会特别特别烫,不能正常工作。冬日乱手神器
DS18B20采用1-wire Bus所有数据都在一条线上传输,因此单总线协议对时序要求非常严格以确保数据的完整性。
单总线信号类型:复位脉冲、存在脉冲、写0、写1、读0、读1。所有这些信号除存在脉冲由DS18B20发出的以外其他信号都由总线控制器发出。数据传输总是从最低有效位开始。
初始化时序里面包含了复位DS18B20和接收DS18B20返回的存在信号。
主机和DS18B20做任何通讯前都需要对其初始化。初始化期间,总线控制器拉低总线并保持480us以上挂在总线上的器件将被复位,然后释放总线,等到15-60us,此时18B20将返回一个60-240us之间的低电平存在信号。
写时序分为写0时序和写1时序。
总线控制器通过控制单总线高低电平持续时间从而把逻辑1或0写DS18B20中。
总线控制器要产生一个写时序,必须将总线拉低最少1us,产生写0时序时总线必须保持低电平60~120us之间,然后释放总线,产生写1时序时在总线产生写时序后的15us内允许把总线拉高。注意:2次写周期之间至少间隔1us
读时序分为读0时序和读1时序。
总线控制器通过读取由DS18B20控制的总线高低电平接收DS18B20数据。
总线控制器要产生一个读时序,必须将总线拉低至少1us,然后释放总线,在读信号开始后15us内总线控制器采样总线数据,读一位数据至少保持在60us以上。注意:2次读周期之间至少间隔1us
根据暂存器我们可以看出,一般仅仅测量温度时,我们只需要读取byte0和1就行了,用到温度报警的话,可以继续读取后面的数据。温度寄存器的位置一开始默认为85摄氏度。下面是温度寄存器图表
温度寄存器举例:
忽略ROM指令(CCh)
这条指令允许总线控制器不用提供64 位ROM 编码就使用功能指令。例如,总线控制器可以先发出一条忽略ROM 指令,然后发出温度转换指令[44h],从而完成温度转换操作。在单点总线情况下使用该命令,器件无需发回64 位ROM 编码,从而节省了时间。如果总线上有不止一只从机,若发出忽略ROM指令,由于多只从机同时传送信号,总线上就会发生数据冲突。
DS18B20初始化函数:
uchar DS18b20_Init()
{
bit i;
DQ = 1;
Delay_us(1);//6.5us
DQ = 0;
Delay500us();
DQ = 1;
Delay_us(4);//26us
i = DQ;
Delay_us(20);//130us
DQ = 1;
Delay_us(1);//6.5us
return i;
}
不难看到这里的延时数字并不对应,原因是在11.0592MHz的环境下,执行每条指令的时间有区别。可以在调试界面自己调试,也可以用STC下载器自动生成
DS18B20写数据函数
void DS18b20_Write(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
DQ = 0;
_nop_();
DQ = dat & 0x01;
Delay_us(13);//84.5us
DQ = 1;
_nop_();
dat >>=1;
}
}
这里用到了一个比较重要的与运算,将一个数与上“0x01”,这一句话的意思其实是这样
整个与运算符合这个思路“0&1=0”“1&1=1”“0&0=0”,dat通过右移,在最高位补0,防止与运算时高位出错。就这样重复8次就分离出了0和1发送出去了。也就是说,一般发送数据时,可以用到“dat & 0x01”
DS18B20读取函数
uchar DS18b20_Red()
{
uchar i,dat,j;
for(i=0;i<8;i++)
{
DQ = 0;
_nop_();
DQ = 1;
_nop_();
j = DQ;
Delay_us(13);//84.5us
dat = (j<<7)|(dat>>1);
DQ = 1;
_nop_;
}
return dat;
}
这里用到了另外一个比较重要的运算——或运算
或运算的运算思路:“0|0=0”“0|1=1”“1|1=1”,先将总线上的数据赋予给j,然后j左移7位放在最高位上,dat向右移1位位最高位腾出位置。将j和dat进行一次或运算,则达到让DQ的数据放在dat的最高位的目的,而低位与0进行或运算,数据不变。
DS18B20调用函数
float DS18b20()
{
int i;
uchar L,M;
DS18b20_Init();//初始化
DS18b20_Write(0xcc);//跳过ROM,因为只用到了一个DS18B20,不需要操作
DS18b20_Write(0x44);//0x44,温度转换指令
DS18b20_Init();//根据协议,再次初始化
DS18b20_Write(0xcc);
DS18b20_Write(0xbe);//读取暂存器
L = DS18b20_Red();//将暂存器的值赋予给L
M = DS18b20_Red();//将暂存器的值赋予给L
i = M;
i <<= 8;//意思是将M放在高8位
i |= L;//这样就是16位,高八位是M,低八位是L
i = i * 0.0625 * 10 +0.5;//这里*10+0.5的目的是为了取整,所以这里的i其实是真实温度的十倍
return i;
}
这里是我用的延时函数
void Delay500us() //@11.0592MHz
{
unsigned char i;
_nop_();
i = 497;
while (--i);
}
void Delay_us(uchar i) //@11.0592MHz
{
while(i--);//一次6.5us
}
想调用DS18B20,可以直接这样完成
int y;
y=DS18b20();
或者
unsigned char XXX函数(int x)
{
...
}
int main(void)
{
XXX函数(DS18b20());
}
以上就是DS18B20的运用,通过这个模块的学习,不仅了解到了该传感器,还简单的了解到了或运算与运算,以及传输协议时序图
欢迎大家关注我
微信公众号:小白写编程
交流群:1033131250