本帖最后由 Kalman 于 2021-2-28 18:47 编辑

DS18B20是一款DALLAS公司推出的单总线数字温度测量芯片。它具有体积小,硬件开销低,抗干扰能力强,精度高的特点
这次实现在ART-Pi开发板上挂载1个DS18B20测量温度功能
硬件如下:
1.png
2.png
VDD接到电源,DQ接MCU引脚,GND接地,由于DQ引脚为开漏输出,不具有输出高电平的能力,必须要接一个上拉电阻


①新建工程
在RT-Thread Studio中新建基于ART-Pi开发板的模板工程
3.png
4.png

②初始化DS18B20
初始化时序如下:
5.png
MCU拉低总线至少480us,产生复位脉冲,然后释放总线(拉高电平);这时DS8B20检测到请求之后,会拉低信号,大约60~240us表示应答;DS8B20拉低电平的60~240us之间,单片机读取总线的电平,如果是低电平,那么表示初始化成功;DS18B20拉低电平60~240us之后,会释放总线
代码实现:
//复位DS18B20
  • void DS18B20_Rst(void)
  • {
  •     rt_pin_mode(DS18B20_DQ, PIN_MODE_OUTPUT); //输出模式
  •     rt_pin_write(DS18B20_DQ, PIN_LOW); //拉低DQ
  •     rt_hw_us_delay(750); //拉低750us(480~960us)
  •     rt_pin_write(DS18B20_DQ, PIN_HIGH); //拉高DQ
  • }
  • //等待DS18B20应答,有应答返回0,无应答返回1
  • uint8_t DS18B20_Check(void)
  • {
  •     uint8_t retry=0;
  •     //进入接收模式,等待应答信号
  •     //等待时间
  •     rt_pin_mode(DS18B20_DQ, PIN_MODE_INPUT); //输入模式
  •     rt_hw_us_delay(15); //等待15~60us
  •     while(rt_pin_read(DS18B20_DQ)&&retry<120) //最多再等待120us
  •     {
  •         retry++;
  •         rt_hw_us_delay(1);
  •     };
  •     if(retry>=120)
  •         return 1; //120us未响应,则判断未检测到
  •     else
  •         retry=0;
  •     //DS18B20开始拉低DQ
  •     while(!rt_pin_read(DS18B20_DQ)&&retry<240) //最长拉低240us
  •     {
  •         retry++;
  •         rt_hw_us_delay(1);
  •     };
  •     if(retry>=240)
  •         return 1;
  •     return 0;
  • }
  • 复制代码

    ③写DS18B20时序
    写时序如下:

    6.png
    MCU给DS18B20写0时,MCU引脚拉低,延时60us,然后释放总线,延时2us
    MCU给DS18B20写1时,MCU引脚拉低,延时2us,然后释放总线,延时60us
    在写时序起始后15μs到60μs期间,DS18B20处于采样单总线电平状态。如果在此期间总线为高电平,则向DS18B20写入1;如果总线为低电平,则向DSl8B20写入0
    代码实现:
    //写字节到DS18B20
  • void DS18B20_Write_Byte(uint8_t dat)
  • {
  •     uint8_t j;
  •     uint8_t temp;
  •     rt_pin_mode(DS18B20_DQ, PIN_MODE_OUTPUT); //输出模式
  •     for(j=1;j<=8;j++)
  •     {
  •         temp=dat&0x01;
  •         dat=dat>>1;
  •         if (temp) //输出高
  •         {
  •             rt_pin_write(DS18B20_DQ, PIN_LOW); //拉低DQ
  •             rt_hw_us_delay(2); //延时2us
  •             rt_pin_write(DS18B20_DQ, PIN_HIGH); //拉高DQ
  •             rt_hw_us_delay(60); //延时60us
  •         }
  •         else //输出低
  •         {
  •             rt_pin_write(DS18B20_DQ, PIN_LOW); //拉低DQ
  •             rt_hw_us_delay(60); //延时60us
  •             rt_pin_write(DS18B20_DQ, PIN_HIGH); //拉高DQ
  •             rt_hw_us_delay(2); //延时2us
  •         }
  •     }
  •     rt_pin_mode(DS18B20_DQ, PIN_MODE_INPUT); //输入模式
  • }
  • 复制代码
    ④读DS18B20时序
    读时序如下:
    7.png
    MCU拉低电平,延时2us;MCU转为输入模式,延时12us;然后读取单总线当前的电平,延时50us
    代码实现:
    //从DS18B20读位
  • uint8_t DS18B20_Read_Bit(void)
  • {
  •     uint8_t data;
  •     rt_pin_mode(DS18B20_DQ, PIN_MODE_OUTPUT); //输出模式
  •     rt_pin_write(DS18B20_DQ, PIN_LOW); //拉低DQ
  •     rt_hw_us_delay(2); //延时2us
  •     rt_pin_write(DS18B20_DQ, PIN_HIGH); //拉高DQ
  •     rt_pin_mode(DS18B20_DQ, PIN_MODE_INPUT); //输入模式
  •     rt_hw_us_delay(12); //延时12us
  •     if(rt_pin_read(DS18B20_DQ)) //读DQ数据
  •         data=1;
  •     else
  •         data=0;
  •     rt_hw_us_delay(50); //延时50us
  •     return data;
  • }
  • //从DS18B20读字节
  • uint8_t DS18B20_Read_Byte(void)
  • {
  •     uint8_t i, j, dat=0;
  •     for(i=1;i<=8;i++)
  •     {
  •         j=DS18B20_Read_Bit();
  •         dat=(j<<7)|(dat>>1);
  •     }
  •     return dat;
  • }
  • 复制代码
    ⑤温度读取
    MCU发送复位信号,发送SKIP ROM命令(0XCC,匹配指令)
    发开始转换命令(0X44)
    延时等待转换完成(12bit分辨率时需要750ms)
    MCU发送复位信号,发送SKIP ROM命令(0XCC)
    发读存储器命令(0XBE),读取暂存器内容
    连续读出两个字节数据
    对读取的温度值进行转换
    代码实现:
    //开始温度转换
  • void DS18B20_Start(void)
  • {
  •     DS18B20_Rst();
  •     DS18B20_Check();
  •     DS18B20_Write_Byte(0xcc);
  •     DS18B20_Write_Byte(0x44);
  • }
  • //读取温度值
  • float DS18B20_Get_Temp(void)
  • {
  •     uint8_t sign; //温度符号,0为-,1为+
  •     uint8_t TL,TH;
  •     uint16_t temp;
  •     float temp1;
  •     DS18B20_Start ();
  •     rt_thread_mdelay(800); //等待转换完成
  •     DS18B20_Rst();
  •     DS18B20_Check();
  •     DS18B20_Write_Byte(0xcc);
  •     DS18B20_Write_Byte(0xbe);
  •     TL=DS18B20_Read_Byte();
  •     TH=DS18B20_Read_Byte();
  •     if(TH>7)
  •     {
  •         TH=~TH;
  •         TL=~TL;
  •         sign=0; //温度为负
  •     }
  •     else
  •         sign=1; //温度为正
  •     temp=TH; //高八位
  •     temp<<=8;
  •     temp+=TL; //低八位
  •     temp1=(float)temp*0.0625; //转换实际温度
  •     if(sign)
  •         return temp1; //返回温度值
  •     else
  •         return -temp1;
  • }
  • 复制代码
    ⑥实现如下:
    8.png
    本次实现单总线上挂载1个DS18B20测量温度,后续再实现总线上挂载多个DS18B20测量温度。