前言:
现在你们对“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温度控制器汇报总结