DS18B20 数字温度传感器的使用和基于RT-Thread操作系统的实现

一、传感器介绍及其特点

DS18B20 是由 DALLAS 半导体公司推出的一种的“一线总线”接口的温度传感器。与传统的热敏电阻等测温元件相比,它是一种新型的体积小、适用电压宽、与微处理器接口简单的数字化温度传感器。一线总线结构具有简洁且经济的特点,可使用户轻松地组建传感器网络,从而为测量系统的构建引入全新概念。

特点如下:

◉测量温度范围为-55 ~ +125℃ 。
◉在-10 ~ +85°C范围内, 精度为±0.5°C。
◉可程序设定 9~12 位的分辨率。
◉3.0 ~ 5.5V 的工作电压范围。
◉自带EEPROM,可用于存储设定分辨率及用户设定的报警温度。
◉转换得到一次数字输出需要750ms(Max)
◉数据线(DQ)也可以用来提供电源(寄生电源,实现方式见datasheet)


直接以“一线总线”的数字方式传输,大大提高了系统的抗干扰性。它能直接读出被测温度,并且可根据实际要求通过简单的编程实现 9 ~ l2 位的数字值读数方式。采用多种封装形式,从而使系统设计灵活、方便。

其ROM 中的 64 位序列号是出厂前被光记好的,它可以看作是该 DS18B20 的地址序列码,每DS18B20 的 64 位序列号均不相同。64 位 ROM 的排列是:前 8 位是产品家族码,接着 48 位是DS18B20 的序列号,最后 8 位是前面 56 位的循环冗余校验码(CRC=X8+X5+X4+1)。ROM 作用是使每一个 DS18B20 都各不相同,这样就可实现一根总线上挂接多个 DS18B20。


可以在总线上只挂载一个DS18B20时使用其的ROM指令来获取这64位的序列号。

一般的电路连接方式如下:


二、通信信号类型的介绍和对应代码的实现
所有的单总线器件要求采用严格的信号时序,以保证数据的完整性。
DS18B20 共有 6 种信号类型:复位脉冲、应答脉冲、写 0、写 1、读 0 和读 1。所有这些信号,除了应答脉冲以外,都由主机发出同步信号。并且发送所有的命令和数据都是字节的低位在前。

2.1 复位脉冲(单片机发送)
单总线上的所有通信都是以初始化序列开始,这里的初始化序列为复位脉冲。
主机输出低电平,保持低电平时间480~960us,以产生复位脉冲。接着主机释放总线,4.7K的上拉电阻将单总线拉高,并进入接收模式(Rx)。


代码实现
使用的是RT-Thread的BSP开发,使用PIN设备框架来实现对IO的控制。

 1///* 引脚编号,通过查看设备驱动文件drv_gpio.c确定 */
 2#define DS18B20_DQ       11  /* PA11 */
 3//复位DS18B20
 4void DS18B20_Rst(void)       
 5{       
 6    rt_pin_mode(DS18B20_DQ, PIN_MODE_OUTPUT);// 引脚为输出模式
 7    rt_pin_write(DS18B20_DQ, PIN_LOW);       //拉低DQ
 8    rt_hw_us_delay(750);                     //拉低750us(480 ~ 960us)
 9    rt_pin_mode(DS18B20_DQ, PIN_MODE_INPUT); //设置为输入,即可释放总线的占用
10    //进入接收模式,等待应答信号。
11}

RT-Thread实现微秒延时的方法:

微秒延时:https://www.rt-thread.org/qa/forum.php?mod=viewthread&tid=11840&highlight=%E5%BE%AE%E7%A7%92

2.2 应答信号(DS18B20发送)

在接收到单片机发出的复位脉冲后(其实是检测到上升沿),等待15~60 us后,DS18B20拉低总线60~240us,以产生应答脉冲。接收到此信号说明该通信线挂载有DS18B20。

代码实现

 1//等待DS18B20的回应
 2//返回1:未检测到DS18B20的存在    返回0:存在
 3//等待了30us,  从机回应为108us,正常。
 4
 5uint8_t DS18B20_Check(void)        
 6{   
 7    uint8_t retry=0;
 8    //------------------等待时间----------------------------------
 9    rt_hw_us_delay(15);                          //15 ~60us 等待
10    while (rt_pin_read(DS18B20_DQ)&&retry<100)  //最多还等待100us
11    {
12           retry++;
13           rt_hw_us_delay(1);
14     };     
15    if(retry>=100)  return 1;                 //100us未响应,则判断未检测到
16    else retry=0;
17
18     //----------------------从机拉低时间开始----------------------
19
20    while (!rt_pin_read(DS18B20_DQ)&&retry<240)  
21    {
22            retry++;
23            rt_hw_us_delay(1);
24    };
25    if(retry>=240)  return 1;     //最长拉低240us    
26    return 0;
27}

复位与应答的时间序列

2.3 写时序(单片机发送数据)
写时序包括写0时序和写1时序。所有写时序至少需要60us,且在2次独立的写时序之间至少需要1us的恢复时间,两种写时序均起始于主机拉低总线。利用输出低电平的时间长短来实现写1或0。

写1时序:主机输出低电平,延时2us,然后释放总线,延时60us。
写0时序:主机输出低电平,延时60us,然后释放总线,延时2us。


代码实现

 1//写一个字节到DS18B20
 2//dat:要写入的字节
 3void DS18B20_Write_Byte(uint8_t dat)     
 4 {             
 5    uint8_t j;  
 6    uint8_t testb;
 7    rt_pin_mode(DS18B20_DQ, PIN_MODE_OUTPUT); // DQ引脚为输出模式
 8    for (j=1;j<=8;j++) 
 9    {
10        testb=dat&0x01;  
11        dat=dat>>1;
12        if (testb) //输出高
13        {
14            rt_pin_write(DS18B20_DQ, PIN_LOW);       //拉低DQ,主机输出低电平
15            rt_hw_us_delay(2);                       //延时2us
16            rt_pin_write(DS18B20_DQ, PIN_HIGH);       //主机输出高电平
17            rt_hw_us_delay(60);                      //延时60us            
18        }
19        else       //输出低
20        {
21            rt_pin_write(DS18B20_DQ, PIN_LOW);       //拉低DQ,主机输出低电平
22            rt_hw_us_delay(60);                      //延时60us
23
24            rt_pin_write(DS18B20_DQ, PIN_HIGH);       //主机输出高电平
25            rt_hw_us_delay(2);                        //延时2us        
26        }  
27    }
28    rt_pin_mode(DS18B20_DQ, PIN_MODE_INPUT);         //设置为输入,释放总线
29}

2.4 读时序(单片机读取数据)

单总线器件仅在主机发出读时序时,才向主机传输数据,所以,在主机发出读数据命令后,必须马上产生读时序,以便从机能够传输数据。


所有读时序至少需要60us,且在2次独立的读时序之间至少需要1us的恢复时间。每个读时序都由主机发起,至少拉低总线1us。主机在读时序期间必须释放总线,并且在时序起始后的15us之内采样总线状态。

典型的读时序过程为:

主机输出低电平,延时2us
然后主机转入输入模式,延时12us
然后读取单总线当前的电平,然后延时50us


代码实现

 1//从DS18B20读取一个位
 2//返回值:1/0
 3uint8_t  DS18B20_Read_Bit(void)              // read one bit
 4{
 5    uint8_t data;
 6    rt_pin_mode(DS18B20_DQ, PIN_MODE_OUTPUT); // DQ引脚为输出模式
 7    rt_pin_write(DS18B20_DQ, PIN_LOW);       //拉低DQ,主机输出低电平
 8    rt_hw_us_delay(2);                       //延时2us
 9    rt_pin_mode(DS18B20_DQ, PIN_MODE_INPUT); //设置为输入,释放总线
10    rt_hw_us_delay(1);//延时1us
11
12    if(rt_pin_read(DS18B20_DQ))
13        data=1;//读取总线数据
14    else 
15        data=0;     
16    rt_hw_us_delay(60);  //延时60us(读一位至少60us)         
17    return data;
18}
19
20//从DS18B20读取一个字节
21//返回值:读到的数据
22uint8_t DS18B20_Read_Byte(void)    // read one byte
23{        
24    uint8_t i,j,dat;
25    dat=0;
26
27    for (i=1;i<=8;i++) 
28   {
29      j=DS18B20_Read_Bit();
30      dat=(j<<7)|(dat>>1);
31   }                            
32    return dat;
33}
读写时间序列(读写一个位作为一个周期,至少60us)

三、温度获取的代码实现
DS18B20的各个ROM命令:datasheet上有说明,或者DS18B20的ROM指令中文

DS18B20的典型温度读取过程为:

1、MCU发送复位信号,发SKIP ROM命令(0XCC,匹配指令)。// 每次对设备发指令都需要这两步。

注:该匹配命令只适合挂载一个设备的情况下,即不需要匹配DS18B20的64位的地址编码。

2、发开始转换命令(0X44),温度一次转换指令,DS18B20内部实现温度转换成数字量。

3、延时一段时间(12bit分辨率时需要750ms)。

4、MCU发送复位信号,发送SKIP ROM命令(0XCC)。

5、发读存储器命令(0XBE),读取暂存器内容。

注:读取将从第1个字节开始,一直进行下去,直到第9(CRC)字节读完。如果不想读完所有字节,控制器可以在任何时间发出复位命令来中止读取。其中第0、1个字节分别为温度值的低位、高位。

6、连续读出两个字节数据(即温度)。
7、对得到的温度值进行转换。

转化后得到的12位数据(采用二进制补码的方式),采用如下方法进行温度换算。

1、二进制中的前面5位是符号位,如果测得的温度大于0, 这5位为0,只要将测到的数值乘于0.0625即可得到实际温度。
2、如果温度小于0,这5位为1,测到的数值需要取反加1再乘于0.0625即可得到实际温度。

温度代码实现

 1//从ds18b20得到温度值
 2//精度:0.5度
 3//返回值:温度值 (-550~1250) 
 4int16_t DS18B20_Get_Temp(void)
 5{
 6    uint8_t temp;         //用来判断符号
 7    uint8_t TL,TH;
 8    uint16_t tem;
 9    rt_base_t level;
10
11    level = rt_hw_interrupt_disable();    //API:进入临界区,退出前系统不会发生任务调度
12    // ds1820 start convert
13    DS18B20_Rst();    
14    DS18B20_Check();
15    DS18B20_Write_Byte(0xcc); // skip rom
16    DS18B20_Write_Byte(0x44); // convert    
17    rt_hw_interrupt_enable(level);    //API:退出临界区
18
19    rt_thread_mdelay(800);  //等待转换完成,至少750ms
20
21    level = rt_hw_interrupt_disable();    //API:进入临界区,退出前系统不会发生任务调度
22    DS18B20_Rst();        //复位
23    DS18B20_Check();     
24    DS18B20_Write_Byte(0xcc);   // skip rom
25    DS18B20_Write_Byte(0xbe);   // 读取命令        
26    TL=DS18B20_Read_Byte(); 
27    TH=DS18B20_Read_Byte();  
28    rt_hw_interrupt_enable(level);    //API:退出临界区
29    if(TH>7)
30    {
31        TH=~TH;
32        TL=~TL; 
33        temp=0;//温度为负  
34    }else temp=1;//温度为正          
35    tem=TH; //获得高八位
36    tem<<=8;    
37    tem+=TL;//获得底八位
38    tem=(float)tem*0.625;//转换 
39
40    if(temp)
41        return tem; //返回温度值
42    else 
43        return -tem;    
44} 

四、RT-Thread实现

其实很简单,就是创建了一个线程,然后在入口函数上调用温度获取函数,得到温度值。

 1/* 
 2说明:ds18b20温度获取线程的入口函数
 3*/
 4void ds18b20_tid_entry(void *parameter)
 5{
 6    int16_t dat;
 7    while(1)
 8    {
 9       rt_thread_mdelay(1000); //1s读取一次     
10        dat =  DS18B20_Get_Temp();    
11       rt_kprintf("temp:%d\n",dat); //读取温度数据并发送到串口。 温度扩大十倍 
12    }
13}
14void ds18b20_init(void)
15{
16    ds18b20_tid = rt_thread_create("ds18b20_thread",     //线程名字
17                            ds18b20_tid_entry,     //线程入口函数  
18                            RT_NULL,             //线程入口参数
19                            THREAD_STACK_SIZE,     //堆栈大小,
20                            THREAD_PRIORITY,      //线程优先级
21                            THREAD_TIMESLICE);   //时间片长度
22    /* 如果获得线程控制块,启动这个线程 */
23    if (ds18b20_tid != RT_NULL)
24        rt_thread_startup(ds18b20_tid);  
25}

效果如下:(得到的结果是扩大了十倍,由于目的仅仅是测试一下,就懒得美化结果了)

五、使用DS18B20注意事项


1、12bit分辨率的转换时间最大为750ms(别的分辨率看手册),需延时大于此值。


2、The power on reset register value is +85°C


3、TH, TL, and CONFIG必须同时连续被写(不能只写一个),


4、CONFIG控制分辨率,分辨率越高,转换时间越长(默认12bit,时间为750ms)


5、初始化信号:每次通信必须初始化一次,
过程,主机一个复位脉冲触发,从机用一个脉冲响应,表示线上有ds18b20存在且准备操作。


6、Read ROM [33h]
读序列号,要求总线上只有一个从机。


7、Match ROM [55h]
匹配序列号


8、Skip ROM [CCh]
无需序列号即可读,适用于只有一个从机的情况。


9、Write Scratchpad [4Eh]
写TH、TL和CONFIG寄存器,三个必须一起写。


10、Convert T [44h]
温度开始转换命令,发送此命令,需要转换时间(12bit 750ms)


11、写时序
一位至少60us,且每个写周期至少有1us恢复时间。
ds18b20在检测到DQ下降沿后15~60us内采集该线信号,若为高,则为1,若为低,则为0.


12、读时序
从主机将DQ线从高拉低开始,保持最低1us,然后释放改为输入模式,也是从这个下降沿开始的15us,从机输出的电平就是有效值(我们要读的高或者低)。之后从机会释放总线

13、the sum of T INIT , T RC(上升时间) , and T SAMPLE must be less than 15 µs(读一位的时间),尽量留给采样最多的时间。

作者:GlYoung

来源:https://blog.csdn.net/m0_37697335/article/details/96384644

往期回顾

1.开源项目|RT-Thread 软件包应用作品:水墨屏桌面台历

2.一站式开发工具:RT-Thread Studio 正式发布

3.熊大:致社区小伙伴们的信

4.STM32 上使用 USB Host 读写 U 盘

5.智能家居 DIY 教程连载4——手把手教你连云

6.社区专访|王君杰:软件包制作经验及使用体验分享

7.“新冠”之下,如何安全返程?如何安全居家办公?

8.RT-Thread视频中心正式上线,在家也能高效学习!

你可以添加微信17775982065为好友,注明:公司+姓名,拉进 RT-Thread 官方微信交流群!

RT-Thread


让物联网终端的开发变得简单、快速,芯片的价值得到最大化发挥。Apache2.0协议,可免费在商业产品中使用,不需要公布源码,无潜在商业风险。

长按二维码,关注我们

点击阅读原文,进入RT-Thread GitHub

你点的每个“在看”,我都认真当成了喜欢

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值