单总线协议(ds18b20)读写详解

1、时序图
2、51c代码
3、总结

                         1、时序图
    1、初始化

 

    2、  写

 

    3、  读

 

 2、代码

#include <reg52.h>
sbit DQ = P2^0; //定义总线的I/O管脚
void SendByte(unsigned char dat);
void Delay4us() //延时4us
{
;
}
void Delay(unsigned char j) //一个循环15us
{
unsigned char i;
while(j--)
{
i = 5;
while (--i);
}
}
bit d18b20_qs() //18b20 起始
{
bit dat;
DQ = 1; //DQ复位
Delay4us();
DQ = 0; //拉低总线
Delay(35); //这里延时大概 525us
DQ = 1; //拉高总线
Delay(2); //这里延时大概 30us
dat = DQ; //读取返回值(0:有18b20存在 1:是没有)
Delay(2);
return dat; //返回数值
}

void d18b20_x(unsigned char dat) //写 8 位 数 据
{
unsigned char i;
for(i=0;i<8;i++) //8位计数器
{
DQ = 0; //拉低总线
DQ = dat & 0x01; //取最低位赋值给总线
Delay(3); //延时45us
DQ = 1; //拉过总线准备写下一个数据(或者总线复位)
dat >>= 1; //数据右移一位
}
}
unsigned char d18b20_d() //读 8 位 数 据
{
unsigned char i,dat=0;
for(i=0;i<8;i++) //8位计数器
{
DQ = 0; //拉低总线
dat >>= 1; //数据右移一位
DQ = 1; //拉过总线(准备读取数据)
if(DQ) //判断是否是 1 如果是就把数据赋值给变量的高位
dat |= 0x80;
Delay(4);
}
return dat; //返回读取到数据数据
}


unsigned int wd() //读取温度函数
{
unsigned char i = 0; //低8位数据
unsigned char j = 0; //高8位数据
unsigned int k = 0; //无符号16整形用来存储读回来的 16位温度数据(j和i组合后的数据)

d18b20_qs(); //初始化
d18b20_x(0xCC); //跳过序列号的操作(因为18b20在总线上可以挂很多个,这个序列号和网卡MAC地址类似)
d18b20_x(0x44); //开启温度转换
Delay(200); //开启温度转换需要时间这里延时一下
d18b20_qs(); //初始化
d18b20_x(0xCC); //跳过序列号的操作(因为18b20在总线上可以挂很多个,这个序列号和网卡MAC地址类似)
d18b20_x(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
i = d18b20_d(); //读取低8位
j = d18b20_d(); //读取高8位

k = j;
k <<= 8;
k = k + i;
return k; //返回读取到的16位数据
}
void CSH  (void) //初始化串口
{

    SCON  = 0x50;        // SCON: 模式 1, 8-bit UART, 使能接收  
    TMOD |= 0x20;               // TMOD: timer 1, mode 2, 8-bit 重装
    TH1   = 0xFD;               // TH1:  重装值 9600 波特率 晶振 11.0592MHz  
    TR1   = 1;                  // TR1:  timer 1 打开                         
    EA    = 1;                  //打开总中断
    //ES    = 1;                  //打开串口中断
}
void SendByte(unsigned char dat) //发送一个字符
{
 SBUF = dat; //SBUF 串行数据缓冲器
 while(!TI);  //TI发送中断标志位 (当数据发送完毕后由硬件置 1 否则等待硬件置 1)
      TI = 0; 
}             
void main()
{
unsigned char i,j;
unsigned int w;
CSH();
while(1)
{
w = wd();
i= w & 0xff; //取低8位
j= (w >> 8)&0xff; //取高8位
SendByte(j); //通过串口把高8位数据返回给上位机
SendByte(i); //通过串口把低8位数据返回给上位机
P1 = j; //使用8个LED 输出高8位数据
Delay(200); //延时3毫秒
Delay(200); //延时3毫秒
Delay(200); //延时3毫秒
Delay(200); //延时3毫秒
Delay(200); //延时3毫秒
Delay(200); //延时3毫秒
Delay(200); //延时3毫秒
Delay(200); //延时3毫秒
Delay(200); //延时3毫秒
Delay(200); //延时3毫秒


P1 = i; //使用8个LED输出低8位数据

Delay(200); //延时3毫秒
Delay(200); //延时3毫秒
Delay(200); //延时3毫秒
Delay(200); //延时3毫秒
Delay(200); //延时3毫秒
Delay(200); //延时3毫秒
Delay(200); //延时3毫秒
Delay(200); //延时3毫秒
Delay(200); //延时3毫秒
Delay(200); //延时3毫秒

}
}
3、总结

1)使用的是11.0592的晶振
2)使用下面的公式可以计算出摄氏度的温度
            wd :读取到的16位数据
            摄氏度 = wd x 0.0625

猜你喜欢

转载自blog.csdn.net/linxubin321/article/details/80539331