九、单总线操作DS18B20采集温度

1、DS18B20温度传感器介绍

  • 测温范围为-55℃到+125℃,在-10℃到+85℃范围内误差为±0.4°;
  • 返回16位二进制温度数值;
  • 主机和从机通信使用单总线,即使用单线进行数据的发送和接收;
  • 在使用中不需要任何外围元件,独立芯片即可完成工作;
  • 掉电保护功能 DS18B20 内部含有 EEPROM ,通过配置寄存器可以设定数字转换精度和报警温度,在系统掉电以后,它仍可保存分辨率及报警温度的设定值;
  • 每个DS18B20都有独立唯一的64位-ID,此特性决定了它可以将任意多的DS18b20挂载到一根总线上,通过ROM搜索读取相应DS18B20的温度值;
  • 宽电压供电,电压2.5V~5.5V;
  • DS18B20返回的16位二进制数代表此刻探测的温度值,其高五位代表正负。如果高五位全部为1,则代表返回的温度值为负值。如果高五位全部为0,则代表返回的温度值为正值。后面的11位数据代表温度的绝对值,将其转换为十进制数值之后,再乘以0.0625即可获得此时的温度值。

2、接线方式

   上拉电阻是必须的。

3、DS18B20内部构成

  • 64位ROM;
    • 存储独有的序列号,出厂前被光刻好的,每个DS18B20序列号均不相同,可以实现一根总线上挂接多个DS18B20的目的。
  • 高速暂存器;
    • 温度传感器,字节0保存温度低八位,字节1保存温度高八位;
    • 温度上限和下限报警触发器,字节2高温触发器数据,字节3低温触发器数据;
    • 配置寄存器,允许设置温度分辨率,9、10、11、12位,对应分辨率为0.5、0.25、0.125、0.0625℃。
  • 存储器
    • 由一个高速RAM和一个可擦除的EEPROM组成,EEPROM存储着温度上下限和配置寄存器的数据。

 4、DS18B20工作步骤

  • 初始化DS18B20
  • 执行ROM命令
  • 执行DS18B20功能指令

5、时序介绍

5.1. 初始化

  •  单片机拉低总线至少480us,产生复位脉冲,然后释放总线(拉高电平);
  • 等待15-60us后DS18B20会拉低信号,在60-240us内低电平表示DS18B20应答;
  • DS18B20拉低60-240us后会释放总线,复位脉冲产生释放总线开始到接收完应答信号时间至少480us。

复位初始化代码如下:

复制代码
 1 static u8 DS18B20_Rest(void)
 2 {
 3     u8 ack=1;
 4     DQ_To_Out();
 5     DQ_OUT=0;//拉低总线
 6     Delay_Us(500);//拉低总线时间大于480us小于960us
 7     DQ_OUT=1;
 8     Delay_Us(20);
 9     Delay_Us(40);//拉高总线时间15~60us
10     DQ_To_In();
11     Delay_Us(40);//等待40us后接收数据,60-240us存在数据
12     if(DQ_IN){
13         ack=1;
14     }else{
15         ack=0;
16     }
17     Delay_Us(140);//接收时间达到240us,等待DS18B20释放总线
18     Delay_Us(300);//接收存在信号至少480us
19     return ack;
20 }
复制代码

5.2. 写时序

  •  单片机拉低总线至少1us;
  • 然后判断发送时序“1”还是时序“0”,DS18B20在15-60us之间采样,在此期间,总线为1则向DS18B20写1,总线为0则向DS18B20写0;
  • 当发送时序0时,需要保持拉低单总线时间大于60us并且小于120us,然后释放总线,至少1us进行下一次数据发送;
  • 当发送时序1时,需要在拉低总线后15us内释放总线,并在15us-60us之间保持高电平。

写一个字节数据代码如下:

复制代码
 1 static void DS18B20_Write_Byte(u8 cmd)
 2 {
 3     DQ_To_Out();
 4     for(u8 i=0;i<8;i++){
 5         DQ_OUT=0;
 6         Delay_Us(5);//拉低总线至少1us,15us之内拉高发送"1"
 7         DQ_OUT=1;
 8         Delay_Us(10);//达到15us
 9         if(cmd&0x01){//最低位为1,发送"1"
10             DQ_OUT=1;
11             Delay_Us(50);//15-60us内为DS18B20采样时间
12         }else{
13             DQ_OUT=0;
14             Delay_Us(50);//15-60us内为DS18B20采样时间
15         }
16         DQ_OUT=1;//释放总线
17         Delay_Us(3);//两个写时隙之间时间至少有1us
18         cmd>>=1;
19     }
20 }
复制代码

5.3. 读时隙

  • 单片机拉低单总线至少1us,然后释放总线,在15us之内读取DS18B20发送过来的数据;
  • 15us后DS18B20释放总线,然后保持至少45us,开始下一次读时序,两个读时隙之间至少需要1us的恢复时间。

读一字节的代码如下:

复制代码
 1 static u8 DS18B20_Read_Byte(void)
 2 {
 3     u8 data=0;
 4     for(int i=0;i<8;i++){
 5         DQ_To_Out();
 6         DQ_OUT=0;
 7         Delay_Us(2);//拉低总线
 8         DQ_OUT=1;//释放总线
 9         Delay_Us(3);//拉低总线后15us内有效
10         data>>=1;
11         DQ_To_In();
12         if(DQ_IN){
13             data|=0x80;
14         }
15         Delay_Us(60);//读时隙至少60us
16         Delay_Us(2);
17     }
18     
19     return data;
20 }
复制代码

6.DS18B20命令

  • 0xCC:跳过ROM
  • 0x44:温度转换指令
  • 0xBE:读暂存器指令
  • 0x33:读ROM
  • 0x55:匹配ROM,发送此命令后,发送64位的ROM编码进行匹配
  • 0xF0:搜索ROM
  • 0xEC:警报搜索

7.获取温度的代码如下:

复制代码
 1 static void DS18B20_Start(void)
 2 {
 3     DS18B20_Rest();//复位初始化DS18B20
 4     DS18B20_Write_Byte(0xCC);//跳过ROM指令
 5     DS18B20_Write_Byte(0x44);//温度转换指令
 6     Delay_Us(100);
 7 }
 8 
 9 float DS18B20_Get_Temp(void)
10 {
11     u8 TL,TH;
12     float temp;
13     int tem;
14     DS18B20_Start();
15     DS18B20_Rest();//复位初始化DS18B20
16     DS18B20_Write_Byte(0xCC);//跳过ROM指令
17     DS18B20_Write_Byte(0xBE);//读取数据指令
18     
19     TL=DS18B20_Read_Byte();
20     TH=DS18B20_Read_Byte();
21     
22     //转换温度数据,没有考虑负数情况
23     tem=TH<<8;
24     tem+=TL;
25     temp=tem*6.25;
26     return temp;
27 }
复制代码

8.头文件和其他代码

复制代码
 1 #ifndef __DS18B20_H__
 2 #define __DS18B20_H__
 3 #include "stm32f10x.h"
 4 #include "sys.h"
 5 #include "delay.h"
 6 
 7 #define DQ_IN PAin(0)
 8 #define DQ_OUT PAout(0)
 9 
10 #define DQ_To_Out() {GPIOA->CRL&=0xFFFFFFF0;GPIOA->CRL|=3<<0;}
11 #define DQ_To_In() {GPIOA->CRL&=0xFFFFFFF0;GPIOA->CRL|=8<<0;}
12 
13 //初始化DS18B20
14 void DS18B20_Init(void);
15 //改变引脚输出输入状态
16 //void DQ_To_In(void);
17 //void DQ_To_Out(void);
18 //复位初始化DS18B20
19 static u8 DS18B20_Rest(void);
20 //写一字节数据
21 static void DS18B20_Write_Byte(u8 cmd);
22 //读一字节数据
23 static u8 DS18B20_Read_Byte(void);
24 //开启温度转换命令
25 static void DS18B20_Start(void);
26 //读取温度数据
27 float DS18B20_Get_Temp(void);
28 
29 #endif
30 
31 
32 void DS18B20_Init(void)
33 {
34     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
35     
36     GPIO_InitTypeDef GPIO_InitStruct;
37     GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
38     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
39     GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
40     GPIO_Init(GPIOA,&GPIO_InitStruct);
41     
42     Delay_Init();
43 }
44 
45 //void DQ_To_In(void)
46 //{
47 //    GPIO_InitTypeDef GPIO_InitStruct;
48 //    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
49 //    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
50 //    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
51 //    GPIO_Init(GPIOA,&GPIO_InitStruct);
52 //}
53 
54 //void DQ_To_Out(void)
55 //{
56 //    GPIO_InitTypeDef GPIO_InitStruct;
57 //    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
58 //    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
59 //    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
60 //    GPIO_Init(GPIOA,&GPIO_InitStruct);
61 //}
复制代码

 

posted @   稚终KINO  阅读(608)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示