龙空技术网

STM32嵌入式-DS18B20温度传感器

量子幽灵 499

前言:

现在你们对“stm32温度算法”大致比较看重,小伙伴们都想要分析一些“stm32温度算法”的相关文章。那么小编也在网摘上收集了一些关于“stm32温度算法””的相关资讯,希望咱们能喜欢,大家快快来了解一下吧!

STM32 虽然内部自带了温度传感器,但是因为芯片温升较大等问题,与实际温度差别较大,所以本章我们将向大家介绍如何通过 STM32 来读取外部数字温度传感器的温度,来得到较为准确的环境温度。在本章中,我们将学习使用单总线技术,通过它来实现 STM32 和外部温度传感器( DS18B20)的通信,并把从温度传感器得到的温度数据通过 printf 打印输出在串口助手上。 本章分为以下学习目标:

1. 学习 DS18B20 的操作

1.1 DS18B20 简介

DS18B20 是由 DALLAS 半导体公司推出的一种“一线总线”接口的温度传感器。与传统的热敏电阻等测温元件相比,它是一种新型的体积小、适用电压宽、与微处理器接口简单的数字化温度传感器。一线总线结构具有简洁且经济的特点,可使用户轻松地组建传感器网络,从而为测量系统的构建引入全新概念,测量温度范围为-55~+125℃ ,精度为±0. 5℃。现场温度直接以“一线总线”的数字方式传输,大大提高了系统的抗干扰性。它能直接读出被测温度,并且可根据实际要求通过简单的编程实现 9~l2 位的数字值读数方式。它工作在3—5. 5 V 的电压范围,采用多种封装形式,从而使系统设计灵活、方便,设定分辨率及用户设定的报警温度存储在 EEPROM 中,掉电后依然保存。其内部结构如图所示:

ROM 中的 64 位序列号是出厂前被光刻好的,它可以看作是该 DS18B20 的地址序列码,每个 DS18B20 的 64 位序列号均不相同。 64 位 ROM 的排列是:前 8 位是产品家族码,接着 48 位是 DS18B20 的序列号,最后 8 位是前面 56 位的循环冗余校验码(CRC=X8+X5+X4 +1)。 ROM 作用是使每一个 DS18B20 都各不相同,这样就可实现一根总线上挂接多个。所有的单总线器件要求采用严格的信号时序,以保证数据的完整性。 DS18B20 共有 6 种信号类型:复位脉冲、应答脉冲、写 0、写 1、读 0 和读 1。所有这些信号,除了应答脉冲以外,都由主机发出同步信号。并且发送所有的命令和数据都是字节的低位在前。这里我们简单介绍这几个信号的时序:

1) 复位脉冲和应答脉冲

单总线上的所有通信都是以初始化序列开始。主机输出低电平,保持低电平时间至少480us,,以产生复位脉冲。接着主机释放总线, 4.7K 的上拉电阻将单总线拉高,延时 15~60 us,并进入接收模式(Rx)。接着 DS18B20 拉低总线 60~240 us,以产生低电平应答脉冲,若为低电平,再延时 480 us。

2) 写时序

写时序包括写 0 时序和写 1 时序。所有写时序至少需要 60us,且在 2 次独立的写时序之间至少需要 1us 的恢复时间,两种写时序均起始于主机拉低总线。写 1 时序:主机输出低电平,延时 2us,然后释放总线,延时 60us。写 0 时序:主机输出低电平,延时 60us,然后释放总线,延时 2us。

3)读时序

单总线器件仅在主机发出读时序时,才向主机传输数据,所以,在主机发出读数据命令后,必须马上产生读时序,以便从机能够传输数据。所有读时序至少需要 60us,且在 2 次独立的读时序之间至少需要 1us 的恢复时间。每个读时序都由主机发起,至少拉低总线1us。主机在读时序期间必须释放总线,并且在时序起始后的 15us 之内采样总线状态。典型的读时序过程为:主机输出低电平延时 2us,然后主机转入输入模式延时 12us,然后读取单总线当前的电平,然后延时 50us。

在了解了单总线时序之后,我们来看看 DS18B20 的典型温度读取过程, DS18B20 的典型温度读取过程为:

复位发 SKIP ROM 命令( 0XCC)

发开始转换命令( 0X44)

延时复位发送 SKIP ROM 命令( 0XCC) 发读存储器命令( 0XBE) 连续读出两个字节数据(即温度)。

结束。DS18B20 的介绍就到这里,更详细的介绍,请大家参考 DS18B20 的技术手册。

1.2 DS18B20 原理图

从原理图中,我们知道了 DS18B20 使用的是单片机的 PG11。

1.3 DS18B20 的初始化

1. 在进行初始化之前,要先进行 IO 口的初始化。

/******************************************************************************** 函 数 名 : ds18b20_init* 函数功能 : IO 端口时钟初始化函数* 输 入 : 无* 输 出 : 无*******************************************************************************/void ds18b20_init(){GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG,ENABLE);GPIO_InitStructure.GPIO_Pin=dq;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIO_ds18b20,&GPIO_InitStructure);}

管脚定义是在其头文件内:

#define dq (GPIO_Pin_11) //PG11#define GPIO_ds18b20 GPIOG#define ds18b20_dq_H GPIO_SetBits(GPIO_ds18b20,dq)#define ds18b20_dq_L GPIO_ResetBits(GPIO_ds18b20,dq)

2. DS18B20 的初始化

主机首先发出一个 480-960 微秒的低电平脉冲,然后释放总线变为高电 平,并在随后的 480 微秒时间内对总线进行检测,如果有低电平出现说明总 线上有器件已做出应答。若无低电平出现一直都是高电平说明总线上无器件 应答。作为从器件的 DS18B20 在一上电后就一直在检测总线上是否有 480-960 微秒的低电平出现,如果有,在总线转为高电平后等待 15-60 微秒后将 总线电平拉低 60-240 微秒做出响应存在脉冲, 告诉主机本器件已做好准备。 若没有检测到就一直在检测等待。

3. 初始化时序图

4. 例程代码:

/******************************************************************************** 函 数 名 : ds18b20init* 函数功能 : DS18B20 初始化时序* 输 入 : 无* 输 出 : 无*******************************************************************************/void ds18b20init(){DQOUTINT();//输出ds18b20_dq_L;delay_us(480);//延时 480 微妙ds18b20_dq_H;delay_us(480);//延时 480 微妙}

1.4DS18B20 读操作

主机发出各种操作命令都是向 DS18B20 写 0 和写 1 组成的命令字节, 接 收数据时也是从 DS18B20 读取 0 或 1 的过程。因此首先要搞清主机是如何 进行写 0、写 1、读 0和读 1 的。写周期最少为 60 微秒,最长不超过 120 微秒。写周期一开始做为主机先 把总线拉低1 微秒表示写周期开始。随后若主机想写 0,则将总线置为低电 平,若主机想写 1,则将总线置为高电平,持续时间最少 60 微秒直至写周期 结束,然后释放总线为高电平至少 1微秒给总线恢复 。而 DS18B20 则在检 测到总线被拉底后等待 15 微秒然后从 15us 到45us 开始对总线采样, 在采样 期内总线为高电平则为 1,若采样期内总线为低电平则为0。

1.读操作时序图

2.读操作程序

/******************************************************************************** 函 数 名 : DS18b20rd* 函数功能 : DS18B20 读数据时序* 输 入 : 无* 输 出 : value*******************************************************************************/u8 DS18b20rd(){u8 i=0,value=0;for(i=0;i<8;i++){value>>=1;DQOUTINT();//输出ds18b20_dq_L;//拉低delay_us(4);//延时 4 微妙ds18b20_dq_H;delay_us(10);//延时 10 微妙DQININT();//输入配置if(GPIO_ReadInputDataBit(GPIO_ds18b20,dq)==1){ value|=0x80;//读数据 从低位开始}delay_us(45);//延时 45 微妙}return value;}

1.5DS18B20 写操作

对于读数据操作时序也分为读 0 时序和读 1 时序两个过程。 读周期是从主机把单总线拉低 1 微秒之后就得释放单总线为高电平,以让 DS18B20 把数据传输到单总线上。作为从机 DS18B20 在检测到总线被拉低 1 微 秒后,便开始送出数据,若是要送出 0 就把总线拉为低电平直到读周期结束。若 要送出 1 则释放总线为高电平。主机在一开始拉低总线 1 微秒后释放总线,然后 在包括前面的拉低总线电平 1 微秒在内的 15 微秒时间内完成对总线进行采样检 测,采样期内总线为低电平则确认为 0。采样期内总线为高电平则确认为 1。完 成一个读时序过程,至少需要 60 微秒才能完成。

1.写操作时序图

2.写操作程序

/******************************************************************************** 函 数 名 : ds18b20wr* 函数功能 : DS18B20 写数据时序* 输 入 : dat* 输 出 : 无*******************************************************************************/void ds18b20wr(u8 dat){u8 i=0;DQOUTINT();//输出for(i=0;i<8;i++){ds18b20_dq_L;//拉低delay_us(15);//延时 15 微妙if((dat&0x01)==1){ds18b20_dq_H;}else{ds18b20_dq_L;}delay_us(60);//延时 60 微妙ds18b20_dq_H;dat>>=1;//准备下一位数据的发送}}

1 .6 DS18B20 的寄存器简介

1.DS18B20 内部结构主要由四部分组成

1) 64 位光刻 ROM光刻 ROM 中的 64 位序列号是出厂前被光刻好的,它可以看作是 该 DS18B20的地址序列码。 64 位光刻 ROM 的排列是:开始 8 位 (地址: 28H )是产品类型标号,接着的 48 位是该 DS18B20 自身 的序列号,并且每个 DS18B20 的序列号都不相同,因此它可以看作是 该 DS18B20 的地址序列码; 最后 8 位则是前面 56 位的循环冗余校验 码( CRC=X8+X5+X4+1 ) 。由于每一个 DS18B20 的ROM 数据都各 不相同,因此微控制器就可以通过单总线对多个 DS18B20 进行寻址, 从而实现一根总线上挂接多个 DS18B20 的目的。

2) 温度传感器

3) 非挥发的温度报警触发器 TH 和 TL

4) 配置寄存器。

2.DS18B20 的存储器由一个高速暂存 RAM 和一个非易失性、 电可擦除 (E2)RAM 组成。

在这里我们看一下第 4 个字节(CONFIG)配置寄存器。

出场设置默认 R0、R1 为 11。也就是 12 位分辨率,也就是 1 位代表 0.0625 摄氏度。

1 .7DS18B20 命令简介

1.8 读取温度操作

1. 读取温度操作

DS18B20 经转换所得的温度值以二字节补码形式存放在高速暂存存储器 的第 0 和第1 个字节。所以当我们只想简单的读取温度值的时候,只用读取 暂存器中的第 0 和第 1 个字节就可以了。读取一次 D18B20 温度的操作步骤 如下:

a) 初始化 DS18B20

b) 跳过 ROM 操作(ROM 里面可以读取 DS18B20 的地址、型号,还有 配置分辨率等,我们只使用一个 DS18B20,所以不用读取地址型号,配置直接使用默认的 12 位分辨率就好了。 )

c) 发送温度转换命令。

d) 跳过 ROM 操作

e) 发送读取温度命令

f) 读取温度值。

2 补码介绍 什么是补码

1) 正数的补码是正数本身

2) 负数的补码是原码取反,然后再加 1。

 DS18B20 存储的温度值是以补码的形式存储的,所以读出来的温度 值是实际温度值的补码,要把的转换为原码。

1) 正温度的话,原码就是补码本身,所以在 12 位分辨率下,温度 的计算公式是: 温度值=读取值*0.0625

2) 负温度的话,原码是补码减 1 再取反,所以在 12 位分辨率下, 计算公式为: 温度值= -(读取值减 1 再取反)*0.0625

3. 读取温度程序函数

/******************************************************************************** 函 数 名 : readtemp* 函数功能 : DS18B2 温度寄存器配置,温度读取* 输 入 : 无* 输 出 : value*******************************************************************************/double readtemp() //读取温度内需要复位的{u16 temp;u8 a,b;double value;ds18b20init();//初始化ds18b20wr(0xcc); //发送忽略 ROM 指令ds18b20wr(0x44); //发送温度转换指令delay_ms(800);ds18b20init(); //初始化ds18b20wr(0xcc); //发送忽略 ROM 指令ds18b20wr(0xbe); //发读暂存器指令a=DS18b20rd();//温度的低八位b=DS18b20rd();//温度的高八位temp=b;temp=(temp<<8)+a;if((temp&0xf800)==0xf800){temp=(~temp)+1;value=temp*(-0.0625);}else{value=temp*0.0625;}return value;}

1.9 例程主函数

/***************************************************************************** Function Name : main* Description : Main program.* Input : None* Output : None* Return : None****************************************************************************/int main(){double temp;printf_init(); //printf 初始化ds18b20_init();//DS18B20 初始化while(1){temp=readtemp(); //读取温度printf("当前温度为:%0.4lf ℃\r\n",temp);}}

主程序的效果是,读取到的温度值通过 printf 输出打印到串口助手上,如下:

当程序下载进去后,打开串口,对 DTR 前进行勾选,然后在取消。再通过发送字符即可以显示。

标签: #stm32温度算法 #基于stm32温度控制器汇报总结