当前位置:网站首页>STM32入门开发 编写DS18B20温度传感器驱动(读取环境温度、支持级联)
STM32入门开发 编写DS18B20温度传感器驱动(读取环境温度、支持级联)
2022-07-07 09:21:00 【华为云】
一、环境介绍
编程软件: keil5
操作系统: win10
MCU型号: STM32F103C8T6
STM32编程方式: 寄存器开发 (方便程序移植到其他单片机)
温度传感器: DS1820
DS18B20是一个数字温度传感器,采用的是单总线时序与主机通信,只需要一根线就可以完成温度数据读取;
DS18B20内置了64位产品序列号,方便识别身份,在一根线上可以挂接多个DS18B20传感器,通过64位身份验证,可以分别读取来至不同传感器采集的温度信息。
二、DS18B20介绍
2.1 DS18B20 的主要特征
\1. 全数字温度转换及输出。
\2. 先进的单总线数据通信。
\3. 最高 12 位分辨率,精度可达土 0.5 摄氏度。
\4. 12 位分辨率时的最大工作周期为 750 毫秒。
\5. 可选择寄生工作方式。
\6. 检测温度范围为–55° C ~+125° C (–67° F ~+257° F)
\7. 内置 EEPROM,限温报警功能。
\8. 64位光刻 ROM,内置产品序列号,方便多机挂接。
\9. 多样封装形式,适应不同硬件系统。
2.2 DS18B20 引脚功能
GND 电压地
DQ 单数据总线
VDD 电源电压
NC 空引脚
2.3 DS18B20 工作原理及应用
DS18B20 的温度检测与数字数据输出全集成于一个芯片之上,从而抗干扰力更强。其一个工作周期可分为两个部分,即温度检测和数据处理。
18B20 共有三种形态的存储器资源,它们分别是:ROM 只读存储器,用于存放 DS18B20ID 编码,其前 8 位是单线系列编码(DS18B20 的编码是19H),后面 48 位是芯片唯一的序列号,最后 8 位是以上 56 的位的 CRC 码(冗余校验)。数据在出产时设置不由用户更改,DS18B20 一共有 64 位 ROM。
RAM 数据暂存器,用于内部计算和数据存取,数据在掉电后丢失, DS18B20 共 9 个字节 RAM,每个字节为 8 位。第 1、 2 个字节是温度转换后的数据值信息,第 3、 4 个字节是用户 EEPROM(常用于温度报警值储存)的镜像。在上电复位时其值将被刷新。第 5 个字节则是用户第 3 个 EEPROM的镜像。第 6、 7、 8 个字节为计数寄存器,是为了让用户得到更高的温度分辨率而设计的,同样也是内部温度转换、计算的暂存单元。第 9 个字节为前 8 个字节的 CRC 码。 EEPROM 非易失性记忆体,用于存放长期需要保存的数据,上下限温度报警值和校验数据,DS18B20 共 3 位 EEPROM,并在 RAM 都存在镜像,以方便用户操作。
DS18B20默认工作在12位分辨率模式,转换后得到的12位数据,存储在DS18B20的两个8比特的RAM中(最前面的两个字节),二进制中的前面5位是符号位,如果测得的温度大于0,这5位为0,只要将测到的数值乘于0.0625即可得到实际温度;如果温度小于0,这5位为1,测到的数值需要取反加1再乘于0.0625即可得到实际温度。或者使用位运算方式提取温度: 小数位是占用的是低4位,高位是整数位(不考虑负数情况)。
2.4 DS18B20 芯片 ROM 指令表
1. Read ROM(读 ROM) [33H] (方括号中的为 16 进制的命令字)
这个命令允许总线控制器读到 DS18B20 的 64 位 ROM。只有当总线上只存在一个 DS18B20 的时候才可以使用此指令,如果挂接不只一个,当通信时将会发生数据冲突
2. atch ROM(指定匹配芯片) [55H]
这个指令后面紧跟着由控制器发出了 64 位序列号,当总线上有多只 DS18B20 时,只有与控制发出的序列号相同的芯片才可以做出反应,其它芯片将等待下一次复位。这条指令适应单芯片和多芯片挂接。
3. Skip ROM(跳跃 ROM 指令) [CCH]
这条指令使芯片不对 ROM 编码做出反应,在单总线的情况之下,为了节省时间则可以选用此指令。如果在多芯片挂接时使用此指令将会出现数据冲突,导致错误出现。
4. Search ROM(搜索芯片) [F0H]
在芯片初始化后,搜索指令允许总线上挂接多芯片时用排除法识别所有器件的 64 位 ROM。
5. Alarm Search(报警芯片搜索) [ECH]
在多芯片挂接的情况下,报警芯片搜索指令只对附合温度高于 TH 或小于 TL 报警条件的芯片做出反应。只要芯片不掉电,报警状态将被保持,直到再一次测得温度什达不到报警条件为止。
6. Write Scratchpad (向 RAM 中写数据) [4EH]
这是向 RAM 中写入数据的指令,随后写入的两个字节的数据将会被存到地址 2(报警 RAM 之 TH)和地址 3(报警 RAM 之 TL)。写入过程中可以用复位信号中止写入。
7. Read Scratchpad (从 RAM 中读数据) [BEH]
此指令将从 RAM 中读数据,读地址从地址 0 开始,一直可以读到地址 9,完成整个 RAM 数据的读出。芯片允许在读过程中用复位信号中止读取,即可以不读后面不需要的字节以减少读取时间。
8. Copy Scratchpad (将 RAM 数据复制到 EEPROM 中) [48H]
此指令将 RAM 中的数据存入 EEPROM 中,以使数据掉电不丢失。此后由于芯片忙于 EEPROM 储存处理,当控制器发一个读时间隙时,总线上输出“0”,当储存工作完成时,总线将输出“1”。
在寄生工作方式时必须在发出此指令后立刻超用强上拉并至少保持 10MS,来维持芯片工作。
9. Convert T(温度转换) [44H]
收到此指令后芯片将进行一次温度转换,将转换的温度值放入 RAM 的第 1、 2 地址。此后由于芯片忙于温度转换处理,当控制器发一个读时间隙时,总线上输出“0”,当储存工作完成时,总线将输出“1”。在寄生工作方式时必须在发出此指令后立刻超用强上拉并至少保持 500MS,来维持芯片工作。
10. Recall EEPROM(将 EEPROM 中的报警值复制到 RAM) [B8H]
此指令将 EEPROM 中的报警值复制到 RAM 中的第 3、 4 个字节里。由于芯片忙于复制处理,当控制器发一个读时间隙时,总线上输出“0”,当储存工作完成时,总线将输出“1”。另外,此指令将在芯片上电复位时将被自动执行。这样 RAM 中的两个报警字节位将始终为 EEPROM 中数据的镜像。
11. Read Power Supply(工作方式切换) [B4H]
此指令发出后发出读时间隙,芯片会返回它的电源状态字,“0”为寄生电源状态,“1”为外部电源状态。
2.5 DS18B20时序图
2.5.1 DS18B20 复位及应答关系示意图
每一次通信之前必须进行复位,复位的时间、等待时间、回应时间应严格按时序编程。
DS18B20 读写时间隙:DS18B20的数据读写是通过时间隙处理位和命令字来确认信息交换的。
2.5.2 向DS18B20写数据0和数据1
在写数据时间隙的前 15uS 总线需要是被控制器拉置低电平,而后则将是芯片对总线数据的采样时间,采样时间在 15~60uS,采样时间内如果控制器将总线拉高则表示写“1”,如果控制器将总线拉低则表示写“0”。
每一位的发送都应该有一个至少 15uS的低电平起始位,随后的数据“0”或“1”应该在 45uS 内完成。
整个位的发送时间应该保持在 60~120uS,否则不能保证通信的正常。
注意: DS18B20读写数据都是从低位开始传输。
2.5.3 从DS18B20读数据0和数据1
读时间隙时控制时的采样时间应该更加的精确才行,读时间隙时也是必须先由主机产生至少1uS的低电平,表示读时间的起始。随后在总线被释放后的 15uS 中 DS18B20 会发送内部数据位,这时控制如果发现总线为高电平表示读出“1”,如果总线为低电平则表示读出数据“0”。每一位的读取之前都由控制器加一个起始信号。
注意:必须在读间隙开始的 15uS 内读取数据位才可以保证通信的正确。
在通信时是以 8 位“0”或“1”为一个字节,字节的读或写是从低位开始的。
2.5.4 读取一次温度的顺序(总线上只有单个DS18B20情况)
\1. 发送复位信号
\2. 检测回应信号
\3. 发送0xCC
\4. 发送0x44
\5. 发送复位信号
\6. 检测回应信号
\7. 写0xcc
\8. 写0xbe
\9. 循环8次读取温度低字节
\10. 循环8次读取温度高字节
\11. 合成16位温度数据,处理
三、驱动代码
3.1 DS18B20.c
#include "ds18b20.h"/*函数功能: DS18B20初始化硬件连接: PB15*/void DS18B20_Init(void){ RCC->APB2ENR|=1<<3; //PB GPIOB->CRH&=0x0FFFFFFF; GPIOB->CRH|=0x30000000; GPIOB->ODR|=1<<15; //上拉}/*函数功能: 检测DS18B20设备是否存在返回值 : 1表示设备不存在 0表示设备正常*/u8 DS18B20_CheckDevice(void) //包含了复位脉冲、检测存在脉冲{ DS18B20_OUTPUT_MODE();//初始化为输出模式 DS18B20_OUT=0; //产生复位脉冲 DelayUs(750); //产生750us的低电平 DS18B20_OUT=1; //释放总线 DelayUs(15); //等待DS18B20回应 if(DS18B20_CleckAck())//检测存在脉冲 { return 1; } return 0;}/*函数功能: 检测DS18B20设备的存在脉冲返回值 : 1表示错误 0表示正常*/u8 DS18B20_CleckAck(void){ u8 cnt=0; DS18B20_INPUT_MODE();//初始化为输入模式 while(DS18B20_IN&&cnt<200) //等待DS18B20响应存在脉冲 { DelayUs(1); cnt++; } if(cnt>=200)return 1; //错误 cnt=0; while((!DS18B20_IN)&&cnt<240) //等待DS18B20释放总线 { DelayUs(1); cnt++; } if(cnt>=240)return 1; //错误 return 0;}/*函数功能: 写一个字节首先学会如何写一个位。*/void DS18B20_WriteByte(u8 cmd){ u8 i; DS18B20_OUTPUT_MODE(); //初始化为输出模式 for(i=0;i<8;i++) { DS18B20_OUT=0; //产生写时间间隙(写开始) DelayUs(2); DS18B20_OUT=cmd&0x01; //发送实际的数据位 DelayUs(60); //等待写完成 DS18B20_OUT=1; //释放总线,准备下一次发送 cmd>>=1; //继续发送下一位数据 }}/*函数功能: 读一个字节首先学会如何读一个位。*/u8 DS18B20_ReadByte(void){ u8 i,data=0; for(i=0;i<8;i++) { DS18B20_OUTPUT_MODE(); //初始化为输出模式 DS18B20_OUT=0; //产生读时间间隙(读开始) DelayUs(2); DS18B20_OUT=1; //释放总线 DS18B20_INPUT_MODE(); //初始化为输入模式 DelayUs(8); //等待DS18B20的数据输出 data>>=1; //高位补0,默认以0为准 if(DS18B20_IN) data|=0x80; DelayUs(60); DS18B20_OUT=1; //释放总线,等待读取下一位数据 } return data;}/*函数功能: 读取一次DS18B20的温度数据返 回 值: 读取的温度数据考虑的情况: 总线上只是接了一个DS18B20的情况*/u16 DS18B20_ReadTemp(void){ u16 temp=0; u8 temp_H,temp_L; DS18B20_CheckDevice(); //发送复位脉冲、检测存在脉冲 DS18B20_WriteByte(0xCC); //跳过ROM序列检测 DS18B20_WriteByte(0x44); //启动一次温度转换 //等待温度转换完成 while(DS18B20_ReadByte()!=0xFF){} DS18B20_CheckDevice(); //发送复位脉冲、检测存在脉冲 DS18B20_WriteByte(0xCC); //跳过ROM序列检测 DS18B20_WriteByte(0xBE); //读取温度 temp_L=DS18B20_ReadByte(); //读取的温度低位数据 temp_H=DS18B20_ReadByte(); //读取的温度高位数据 temp=temp_L|(temp_H<<8); //合成温度 return temp;}
3.2 DS18B20.h
#ifndef DS18B20_H#define DS18B20_H#include "stm32f10x.h"#include "sys.h"#include "delay.h"#include "ds18b20.h"#include "usart.h"/*封装接口*///初始化DS18B20为输入模式#define DS18B20_INPUT_MODE() {GPIOB->CRH&=0x0FFFFFFF;GPIOB->CRH|=0x80000000;}//初始化DS18B20为输出模式#define DS18B20_OUTPUT_MODE(){GPIOB->CRH&=0x0FFFFFFF;GPIOB->CRH|=0x30000000;}//DS18B20 IO口输出#define DS18B20_OUT PBout(15)//DS18B20 IO口输入#define DS18B20_IN PBin(15) //函数声明u8 DS18B20_CleckAck(void);u8 DS18B20_CheckDevice(void);void DS18B20_Init(void);u16 DS18B20_ReadTemp(void);u8 DS18B20_ReadByte(void);void DS18B20_WriteByte(u8 cmd);#endif
3.3 延时函数
/*函数功能: 延时us单位*/void DelayUs(int us){#ifdef _SYSTICK_IRQ_ int i,j; for(i=0;i<us;i++) for(j=0;j<72;j++);#else u32 tmp; SysTick->VAL=0; //CNT计数器值 SysTick->LOAD=9*us; //9表示1us SysTick->CTRL|=1<<0; //开启定时器 do { tmp=SysTick->CTRL; //读取状态 }while((!(tmp&1<<16))&&(tmp&1<<0)); SysTick->VAL=0; //CNT计数器值 SysTick->CTRL&=~(1<<0); //关闭定时器 #endif }
3.4 main.c 调用DS18B20读取温度打印到串口
#include "stm32f10x.h"#include "ds18b20.h"u8 DS18B20_ROM[8]; //存放DS18B20的64为ROM编码int main(void){ u16 temp; USARTx_Init(USART1,72,115200);//串口1的初始化 DS18B20_Init(); //DS18B20初始化 /*1. 读取DS18B20的64位ROM编码*/ //发送复位脉冲、检测存在脉冲 while(DS18B20_CheckDevice()) { printf("DS18B20设备不存在!\n"); DelayMs(500); } //发送读取64为ROM编码的命令 DS18B20_WriteByte(0x33); //循环读取64位ROM编码 for(i=0;i<8;i++) { DS18B20_ROM[i]= DS18B20_ReadByte(); printf("DS18B20_ROM[%d]=0x%X\n",i,DS18B20_ROM[i]); } while(1) { /*2. 同时操作总线上所有的DS18B20开始转换温度*/ DS18B20_CheckDevice(); //发送复位脉冲、检测存在脉冲 DS18B20_WriteByte(0xCC); //跳过ROM序列检测 DS18B20_WriteByte(0x44); //启动一次温度转换(让总线上所有的DS18B20都转换温度) DelayMs(500); //等待线上所有的DS18B20温度转换完成 /*3. 单个针对性读取每个DS18B20的温度*/ DS18B20_CheckDevice(); //发送复位脉冲、检测存在脉冲 DS18B20_WriteByte(0x55); //发送匹配ROM的命令 for(i=0;i<8;i++) //发送64位编码 { DS18B20_WriteByte(DS18B20_ROM[i]); } DS18B20_WriteByte(0xBE); //读取温度 temp=DS18B20_ReadByte(); //读取的温度低位数据 temp|=DS18B20_ReadByte()<<8; //读取的温度高位数据 printf("temp1=%d.%d\n",temp>>4,temp&0xF); printf("temp2=%f\n",temp*0.0625); DelayMs(500); } }
边栏推荐
- 2021-04-23
- Project ERROR: Unknown module(s) in QT: core gui
- Transaction rolled back because it has been marked as rollback only
- CentOS系统下Redis安装和自启动配置的步骤
- 关于jmeter中编写shell脚本json的应用
- 【时间格式工具函数的封装】
- shardingsphere分库分表示例(逻辑表,真实表,绑定表,广播表,单表)
- The fifth training assignment
- MIF file format record
- The seventh training assignment
猜你喜欢
随机推荐
滚动踩坑--UNI_APP(八)
Verilog 实现数码管显视驱动【附源码】
Process control (creation, termination, waiting, program replacement)
electron添加SQLite数据库
The eighth training assignment
CentOS系统下Redis安装和自启动配置的步骤
Hash / (understanding, implementation and application)
Rolling puddle Uni_ App (VIII)
基于DE2 115开发板驱动HC_SR04超声波测距模块【附源码】
基于Retrofit框架的金山API翻译功能案例
Table replication in PostgreSQL
Arduino board description
The use of list and Its Simulation Implementation
Template initial level template
Static semantic check of clang tidy in cicd
How to remove addition and subtraction from inputnumber input box
解决VSCode只能开两个标签页的问题
[untitled]
[pyqt] the cellwidget in tablewidget uses signal and slot mechanism
2021-04-08