DS18B20温度传感器的特性、原理、驱动(华大半导体HC32L136、ESP32驱动)

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
img
img

如果你需要这些资料,可以戳这里获取

需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

Gpio_Init(GpioPortB,GpioPin8,&stcGpioCfg); ///< 端口初始化

Gpio_SetIO(GpioPortB,GpioPin8); ///< 默认置高电平
}


第2步:配置延时,本案例基于HC32L136 24MHz时钟频率下工作的,一个机器周期约为2us(num参数,不是倍数关系,HC32L136延时相当不精准,需要用示波器验证),代码如下所示:



void delay_us(uint32_t num)
{
while(num–)
{
__NOP();
}
}


第3步:初始化以及检测DS18B20是否存在,当DS18B20响应复位信号的存在脉冲后,则其向主设备表明其在该总线上,并且已经做好操作命令。


在初始化序列期间,总线上的主设备通过拉低1-Wire总线**超过480us**来发送(TX)复位脉冲。之后主设备释放总线而进入接收模式(RX)。当总线释放后,5kΩ左右的上拉电阻将1-Wire总线拉至高电平。当DS18B20检测到该上升边沿信号后,其**等待15us至60us**后通过将1-Wire总线**拉低60us至240us**来实现发送一个存在脉冲。初始化时序如下图所示:


![](https://img-blog.csdnimg.cn/2020031311423742.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM4MTA2OTIz,size_16,color_FFFFFF,t_70)


初始化时序代码如下所示:



//复位DS18B20
void DS18B20_Rst(void)
{
DS18B20_IO_OUT(); ///< 配置端口输出
Gpio_ClrIO(GpioPortB,GpioPin8); ///< 拉低DQ
delay100us(7); ///< 拉低700us
Gpio_SetIO(GpioPortB,GpioPin8); ///< 拉高DQ
delay10us(1); ///< 拉高15us
}

//等待DS18B20的回应
//返回1:未检测到DS18B20的存在
//返回0:存在
uint8_t DS18B20_Check(void)
{
uint8_t retry=0;
DS18B20_IO_IN(); ///< 配置端口输入
while ((Gpio_GetInputIO(GpioPortB,GpioPin8)==1) && (retry<100)) ///< 最多200us
{
retry++;
delay_us(1); ///< 每次等待2us
}

if(retry>=200)
{
return 1;
}
else
{
retry=0;
}

while ((Gpio_GetInputIO(GpioPortB,GpioPin8)==0 )&& (retry<120)) ///< 最多240us
{
retry++;
delay_us(1); ///< 每次等待2us
}

if(retry>=120)
{
return 1;
}

return 0;
}


运行程序,时序效果如下所示:


![](https://img-blog.csdnimg.cn/20200313122034418.PNG?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM4MTA2OTIz,size_16,color_FFFFFF,t_70)


第4步:开始转换DS18B20,写入ROM命令:0XCC和0X44。写时段有两种情况:“写1”时段和“写0”时段,主设备通过写1时段来向DS18B20中写入逻辑1以及通过写0时段来向DS18B20中写入逻辑0。每个写时段**最小必须有60us**的持续时间且独立的写时段间**至少有1us**的恢复时间。


为了形成写1时段,在将1-Wire总线拉低后,主设备必须在15us之内释放总线。当总线释放后,5kΩ的上拉电阻将总线拉至高。为了形成写0时段,在将1-Wire总线拉低后,在整个时段期间主设备必须一直拉低总线(至少60us)。


在主设备初始化写时段后,DS18B20将会在15us至60us的时间窗口内对总线进行采样。如果总线在采样窗口期间是高电平,则逻辑1被写入DS18B20;若总线是低电平,则逻辑0被写入DS18B20。读/写时段时序如下所示:


![](https://img-blog.csdnimg.cn/20200313123001189.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM4MTA2OTIz,size_16,color_FFFFFF,t_70)


 转换DS18B20代码如下所示:



//写一个字节到DS18B20
//dat:要写入的字节
void DS18B20_Write_Byte(uint8_t dat)
{
uint8_t j;
uint8_t testb;
DS18B20_IO_OUT(); ///< 配置端口输出
for (j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if (testb) ///< 写入1
{
Gpio_ClrIO(GpioPortB,GpioPin8);
delay_us(1); ///< 拉低2us

  Gpio_SetIO(GpioPortB,GpioPin8); 
  delay10us(5);                    ///< 拉高64us
}
else                              ///< 写入0
{
  Gpio_ClrIO(GpioPortB,GpioPin8);     
  delay10us(5);                    ///< 拉低64us

  Gpio_SetIO(GpioPortB,GpioPin8); 
  delay_us(1);                     ///< 拉高2us   
}

}
}

//开始温度转换
void DS18B20_Start(void)
{
DS18B20_Rst();
DS18B20_Check();
DS18B20_Write_Byte(0xCC); ///< skip rom
DS18B20_Write_Byte(0x44); ///< convert
}


运行程序,写入0XCC(二进制:‭1100 1100‬)时序效果如下所示:


![](https://img-blog.csdnimg.cn/20200313124904726.PNG?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM4MTA2OTIz,size_16,color_FFFFFF,t_70)


写入0X44(二进制:0100 0100‬)时序效果如下所示:


![](https://img-blog.csdnimg.cn/20200313125316479.PNG?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM4MTA2OTIz,size_16,color_FFFFFF,t_70)


第5步: 写入读取DS18B20暂存器功能命令:0XCC和0XBE,代码如下所示:



DS18B20_Write_Byte(0xCC); ///< skip rom
DS18B20_Write_Byte(0xBE); ///< convert


运行程序,写入0XBE(二进制:‭1011 1110‬)时序效果如下所示:


![](https://img-blog.csdnimg.cn/20200313134314751.PNG?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM4MTA2OTIz,size_16,color_FFFFFF,t_70)


第6步:  读取温度寄存器数据,这里只需要读取两个字节(16位)即可。每个读时段**最小必须有60us**的持续时间且独立的写时段间**至少有1us**的恢复时间。读时段通过主设备将总线**拉低超过1us**再释放总线来实现初始化,当主设备初始化完读时段后,DS18B20将会向总线发送0或者1。DS18B20通过将总线拉至高来发送逻辑1,将总线拉至低来发送逻辑0。当发送完0后,DS18B20将会释放总线,则通过上拉电阻该总线将会恢复到高电平的闲置状态。从DS18B20中输出的数据在初始化读时序后**仅有15us的有效时间**,因此,主设备在开始改读时段后的**15us之内必须释放总线**,并且对总线进行采样。读时段时序图如下所示:


![](https://img-blog.csdnimg.cn/20200313134704794.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM4MTA2OTIz,size_16,color_FFFFFF,t_70)



读时段代码如下所示:




//从DS18B20读取一个位
//返回值:1/0
uint8_t DS18B20_Read_Bit(void)
{
uint8_t data;
DS18B20_IO_OUT(); ///< 配置端口输出
Gpio_ClrIO(GpioPortB,GpioPin8);
delay_us(1); ///< 等待2us

Gpio_SetIO(GpioPortB,GpioPin8);
DS18B20_IO_IN(); ///< 配置端口输入
delay_us(40); ///< 等待12us

if(Gpio_GetInputIO(GpioPortB,GpioPin8)==1)
{
data=1;
}
else
{
data=0;
}

delay10us(4); ///< 等待52us
return data;
}

//从DS18B20读取一个字节
//返回值:读到的数据
uint8_t DS18B20_Read_Byte(void)
{
uint8_t i=0,j=0,dat=0;
uint8_t num1,num2;
for (i=1;i<=8;i++) ///< 一次读取一个字节,8位
{
j=DS18B20_Read_Bit();
num1=j<<7;
num2=dat>>1;
dat=num1|num2;
}
return dat;
}

TL=DS18B20_Read_Byte(); ///< 读取LSB,低八位数据
TH=DS18B20_Read_Byte(); ///< 读取MSB,高八位数据


运行程序,读取低八位数据时序效果如下所示:


![](https://img-blog.csdnimg.cn/20200313135455947.PNG?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM4MTA2OTIz,size_16,color_FFFFFF,t_70)


 读取高八位数据时序效果如下所示:


![](https://img-blog.csdnimg.cn/2020031313574856.PNG?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM4MTA2OTIz,size_16,color_FFFFFF,t_70)




所以读到的数据为,二进制:101101010。


第7步:将十六进制数据转换为十进制形式,代码如下所示:



if(TH>7) ///< 温度为负
{
TH=~TH;
TL=~TL;
temp_flag=0;
}
else ///< 温度为正
{
temp_flag=1;
}

tem=TH;
tem<<=8;
tem+=TL;
temp=(float)tem/16.0; ///< 转换数据

if(temp_flag)
{
return temp;
}

return -temp;


二进制:101101010按照数据手册转换为十进制362,362除以16为22.625‬,与此时程序串口打印效果完全一致,说明转换无误。


![](https://img-blog.csdnimg.cn/20200312163013111.png)


## 4、ESP32驱动


闲来无事为了验证温度检测的精准性(HC32L136精度较差),特使用ESP32又写了一版驱动程序,完整示例代码如下所示(可直接复制使用):



#include <OneWire.h>

int DS18B20_Pin = D3; //DS18B20信号引脚在D3上

//温度芯片I/O
OneWire ds(DS18B20_Pin); //配置数字引脚D3

void setup(void) {
Serial.begin(9600);
Serial.println(“Start!\n”);
}

void loop(void) {
float temperature = getTemp();
Serial.println(temperature);

delay(1000);
}

float getTemp(){
//获取DS18B20温度数据

byte data[12];
byte addr[8];

if ( !ds.search(addr)) {
//若无传感器继续搜索
ds.reset_search();
return -1000;
}

if ( OneWire::crc8( addr, 7) != addr[7]) {
Serial.println(“CRC is not valid!”);

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新

需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)

如果你需要这些资料,可以戳这里获取

[外链图片转存中…(img-M4sseoCh-1715868682769)]
[外链图片转存中…(img-13E5ZL4u-1715868682770)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新

需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)

如果你需要这些资料,可以戳这里获取

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值