本文主要是介绍CC2652RB读取温度传感器DS18B20,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
DS18B20温度传感器
1. 简介
DS18B20数字温度传感器提供9-12位摄氏度温度测量数据,可编程非易失存储器设置温度监测的上限和下限,提供温度报警。DS18B20通过1-Wire®总线通信,只需要一条数据线 (和地线) 即可与处理器进行数据传输。器件可以工作在-55°C至+125°C范围,在-10°C至+85°C范围内测量精度为±0.5°C。此外,DS18B20还可以直接利用数据线供电 (寄生供电),无需外部电源。
每个DS18B20具有唯一的64位序列号,从而允许多个DS18B20挂接在同一条1-Wire总线。可以方便地采用一个微处理器控制多个分布在较大区域的DS18B20。该功能非常适合HVAC环境控制、楼宇/大型设备/机器/过程监测与控制系统内部的温度测量等应用。
2. 关键时序解读
单总线对时序的要求比较严格,需要提供相对精确的 us 延时函数 ,时序需要满足数据手册里的极限值,以防止在高低温下出现读取温度异常的情况。
-
复位时序
首先主机由高电平拉低DQ,持续最少 480us,然后释放DQ,等待DQ被上拉电阻拉高,约 15-60us;随后 DS18B20 将驱动DQ为低 60-240us,这个信号叫 presence pulse (在位脉冲,表示DS18B20准备就绪 可以接受命令);如果主机检测到这个低电平的应答信号,表示DS18B20复位成功,可进行后续操作 -
读、写时序
写时序:
写0时整个过程时间需要大于60us且需要小于120us;且前15us用来准备数据,而后的15us-45us DS18B20 获取总线上的低电平,等到数据;写1时需要先拉低1us总线,而后在15us内拉高总线,而后的 15us-45us DS18B20 获取总线上的高电平;
连续 2 次写数据之间需要加上大于1us以上的延时;
读时序:
主机读取总线数据时,主机需要先将总线拉低最少1us且不超过15us的时候,随后在从拉低总线开始的15us内读取总线电平;
连续 2 次读数据之间需要加上大于1us以上的延时;
使用CC2652RB读取DS18B20
- us级延时函数的实现
static void DS18B20_DELAY_US(uint16_t nus)
{volatile uint8_t i = 0;while(nus--){for(i = 0; i < 4; i++ ){asm("NOP");}}
}
- DS18B20 复位函数
/******************************************************************************** 名 称: bsp_Ds18b20Reset* 功 能: 复位DS18B20。* 入口参数: 无* 出口参数: 0 失败; 1 表示成功* 作 者: Roger-WY.* 创建日期: 2015-12-05* 修 改:* 修改日期:* 备 注: 拉低DQ为低,持续最少480us,然后等待*******************************************************************************/
int8_t bsp_Ds18b20Reset(void)
{uint8_t i;uint16_t k;int8_t ret = -1;BSP_DS18B20_DISABLE_INT();/* 禁止全局中断 *//* 复位,如果失败则返回0 */for ( i = 0; i < 1; i++ ) {DS18B20_IO_1(); /* 释放DQ */DS18B20_DELAY_US(10);DS18B20_IO_0(); /* 拉低DQ */DS18B20_DELAY_US(540); /* 延迟 540uS, 要求这个延迟大于 480us */DS18B20_IO_1(); /* 释放DQ */DS18B20_DELAY_US(15); /* 等待15us *//* 检测DQ电平是否为低 */for ( k = 0; k < 24; k++ ) {if ( DS18B20_IO_IS_LOW() ) {ret = 0;break;}DS18B20_DELAY_US(10); /* 等待10us */}if (k >= 24) {continue; /* 失败 */}/* 等待DS18B20释放DQ */for (k = 0; k < 30; k++) {if ( !DS18B20_IO_IS_LOW() ) {break;}DS18B20_DELAY_US(10); /* 等待65us */}if (k >= 30) {continue; /* 失败 */}break;}BSP_DS18B20_ENABLE_INT(); /* 使能全局中断 */DS18B20_DELAY_US(5);return ret;
}
- DS18B20 写字节函数
/******************************************************************************** 名 称: bsp_DS18B20_WriteByte* 功 能: 向DS18B20写入1字节数据。* 入口参数: _val : 写入的字节* 出口参数: 无* 作 者: Roger-WY.* 创建日期: 2015-12-05* 修 改:* 修改日期:* 备 注:*******************************************************************************/
static void bsp_DS18B20_WriteByte(uint8_t _val)
{uint8_t i;for ( i = 0; i < 8; i++ ) {if((_val & 0x01)){DS18B20_IO_0();DS18B20_DELAY_US(5);DS18B20_IO_1();DS18B20_DELAY_US(60);}else{DS18B20_IO_0();DS18B20_DELAY_US(60);DS18B20_IO_1();DS18B20_DELAY_US(5);}_val >>= 1;}
}
- DS18B20 读字节函数
/******************************************************************************** 名 称: bsp_DS18B20_ReadByte* 功 能: 从DS18B20读取1字节数据。* 入口参数: 无* 出口参数: 读出的字节* 作 者: Roger-WY.* 创建日期: 2015-12-05* 修 改:* 修改日期:* 备 注:*******************************************************************************/
static uint8_t bsp_DS18B20_ReadByte(void)
{/*读数据时序, 见DS18B20 page 16*/uint8_t i;uint8_t read = 0;for ( i = 0; i < 8; i++ ) {read >>= 1;DS18B20_IO_0();DS18B20_DELAY_US(3); // 2~15usDS18B20_IO_1();DS18B20_DELAY_US(3);if ( DS18B20_IO_IS_LOW() ) { //需要在15us内完成采样;} else {read |= 0x80;}DS18B20_DELAY_US(60); //延时 > 45us}return read;
}
- DS18B20 读取温度函数
/******************************************************************************** 名 称: CRC8* 功 能: DS18B20使用的校验算法* 入口参数: ptr:需要校验的数组 len:需要校验的数组的长度* 出口参数: 校验值* 作 者: Roger-WY.* 创建日期: 2017-12-05* 修 改:* 修改日期:* 备 注:*******************************************************************************/
uint8_t CRC8(uint8_t *ptr, uint8_t len)
{uint8_t i;uint8_t crc=0;while(len-- != 0) {for(i = 1; i!=0; i*=2) {if((crc&1)!=0) {crc /= 2;crc ^= 0x8C;} else {crc /= 2;}if((*ptr&i)!=0) {crc ^= 0x8C;}}ptr++;}return(crc);
}
/******************************************************************************** 名 称: bsp_ReadDs18b20Temp* 功 能: 读DS18B20的温度值* 入口参数: 无* 出口参数: 放大十倍之后的温度值* 作 者: Roger-WY.* 创建日期: 2015-12-05* 修 改:* 修改日期:* 备 注: 存储的温度是16 位的带符号扩展的二进制补码形式* 当工作在12位分辨率时,其中5个符号位,7个整数位,4个小数位** |---------整数----------|-----小数 分辨率 1/(2^4)=0.0625----|* 低字节 | 2^3 | 2^2 | 2^1 | 2^0 | 2^(-1) | 2^(-2) | 2^(-3) | 2^(-4) |*** |-----符号位:0->正 1->负-------|-----------整数-----------|* 高字节 | s | s | s | s | s | 2^6 | 2^5 | 2^4 |*** 温度 = 符号位 + 整数 + 小数*0.0625* !!!读取温度值时,需要加上临界区保护 !!!*******************************************************************************/
int16_t bsp_Ds18b20ReadTemp( void )
{//uint8_t temp1, temp2;uint8_t tDs18b20Buff[9] = {0};int16_t t_18b20temp;uint8_t tCrc8Value;/* 总线复位 */if ( bsp_Ds18b20Reset() != 0 ) {return 0;}BSP_DS18B20_DISABLE_INT(); /* 禁止全局中断 */bsp_DS18B20_WriteByte(DS18B20_SKIP_ROM); /* 发命令 跳过 ROM */bsp_DS18B20_WriteByte(DS18B20_CONVERT_TEMPERATURE); /* 发转换命令 */bsp_Ds18b20Reset(); /* 总线复位 */bsp_DS18B20_WriteByte(DS18B20_SKIP_ROM); /* 发命令 跳过 ROM */bsp_DS18B20_WriteByte(DS18B20_READ_SCRATCHPAD); /* 读温度值 */for(uint8_t i = 0; i < 9; i++) {/*读取DS18B20暂存器中的9个字节 */tDs18b20Buff[i] = bsp_DS18B20_ReadByte();}BSP_DS18B20_ENABLE_INT(); /* 使能全局中断 */tCrc8Value = CRC8(tDs18b20Buff,8);if( tCrc8Value == tDs18b20Buff[8]) {t_18b20temp = (int16_t)(( (tDs18b20Buff[1] << 8) + tDs18b20Buff[0] ) * DS18B20_DECIMAL_STEPS_12BIT ); //现在测得的是真是的十进制值(与下面的进过放大十倍的值,两者取其一)//t_18b20temp = (int16_t)(( (tDs18b20Buff[1] << 8) + tDs18b20Buff[0] )*0.625 ) + 0.5;//放大十倍,将小数点的后一位也转换(与上面的测实际值,两者取其一)} else { //注意:加0.5是为了四舍五入t_18b20temp = DS18B20_ERROR_TEMP; /*当检验不通过时,赋值为-100度*/}return (t_18b20temp);
}
- DS18B20 读取 64bit ID函数
/******************************************************************************** 名 称: bsp_Ds18b20ReadId* 功 能: 读DS18B20的ROM ID, 总线上必须只有1个芯片* 入口参数: _id 存储ID* 出口参数: 0 表示失败, 1表示检测到正确ID* 作 者: Roger-WY.* 创建日期: 2015-12-05* 修 改:* 修改日期:* 备 注:*******************************************************************************/
int8_t bsp_Ds18b20ReadId(uint8_t *_id)
{uint8_t i = 0;BSP_DS18B20_DISABLE_INT(); /* 禁止全局中断 */if ( bsp_Ds18b20Reset() == 0 ) { /* 总线复位 */return 0;}bsp_DS18B20_WriteByte(DS18B20_READ_ROM); /* 发命令 */for ( i = 0; i < 8; i++ ) {_id[i] = bsp_DS18B20_ReadByte();}bsp_Ds18b20Reset(); /* 总线复位 */BSP_DS18B20_ENABLE_INT(); /* 使能全局中断 */if(_id[7] == CRC8(_id,7)) {return 1;}return 0;
}
- DS18B20 通过 ID 读温度的函数
/******************************************************************************** 名 称: bsp_Ds18b20ReadTempById* 功 能: 读指定ID的温度寄存器的值(原始数据)* 入口参数: 无* 出口参数: 温度寄存器数据 (除以16得到 1摄氏度单位, 也就是小数点前面的数字)* 作 者: Roger-WY.* 创建日期: 2015-12-05* 修 改:* 修改日期:* 备 注:*******************************************************************************/
int16_t bsp_Ds18b20ReadTempById(uint8_t *_id)
{uint8_t tDs18b20Buff[9] = {0};int16_t t_18b20temp = 0;uint8_t tCrc8Value = 0;BSP_DS18B20_DISABLE_INT(); /* 禁止全局中断 */bsp_Ds18b20Reset(); /* 总线复位 */bsp_DS18B20_WriteByte(DS18B20_MATCH_ROM); /* 发命令 */for (uint8_t i = 0; i < 8; i++) {bsp_DS18B20_WriteByte(_id[i]);}bsp_DS18B20_WriteByte(DS18B20_CONVERT_TEMPERATURE); /* 发转换命令 */bsp_Ds18b20Reset(); /* 总线复位 */bsp_DS18B20_WriteByte(DS18B20_MATCH_ROM); /* 发命令 */for (uint8_t i = 0; i < 8; i++) {bsp_DS18B20_WriteByte(_id[i]);}bsp_DS18B20_WriteByte(DS18B20_READ_SCRATCHPAD);for(uint8_t i = 0; i < 9; i++) {/*读取DS18B20暂存器中的9个字节 */tDs18b20Buff[i] = bsp_DS18B20_ReadByte();}BSP_DS18B20_ENABLE_INT(); /* 使能全局中断 */tCrc8Value = CRC8(tDs18b20Buff,8);if( tCrc8Value == tDs18b20Buff[8]) {t_18b20temp = (int16_t)(( (tDs18b20Buff[1] << 8) + tDs18b20Buff[0] ) * DS18B20_DECIMAL_STEPS_12BIT ); //现在测得的是真是的十进制值(与下面的进过放大十倍的值,两者取其一)//t_18b20temp = (int16_t)(( (tDs18b20Buff[1] << 8) + tDs18b20Buff[0] )*0.625 ) + 0.5;//放大十倍,将小数点的后一位也转换(与上面的测实际值,两者取其一)} else { //注意:加0.5是为了四舍五入t_18b20temp = DS18B20_ERROR_TEMP; /*当检验不通过时,赋值为 DS18B20_ERROR_TEMP 度*/}return (t_18b20temp);
}
- ds18b20.h 头文件
/******************************************************************************** Filename: bsp_ds18b20.h* Revised: All copyrights reserved to Roger.* Date: 2014-08-11* Revision: v1.0* Writer: Roger-WY.** Description: 单总线数字温度传感器驱动模块 头文件*** Notes:** All copyrights reserved to Roger-WY*******************************************************************************/#ifndef _BSP_DS18B20_H__
#define _BSP_DS18B20_H__#include <stdint.h>/* Every onewire chip has different ROM code, but all the same chips has same family code */
/* in case of DS18B20 this is 0x28 and this is first byte of ROM address */
#define DS18B20_FAMILY_CODE 0x28
#define DS18B20_CMD_ALARMSEARCH 0xEC
#define DS18B20_NOBODY 0xF0
#define DS18B20_SEARCH 0xF0
#define DS18B20_SKIP_ROM 0xCC
#define DS18B20_READ_ROM 0x33
#define DS18B20_MATCH_ROM 0x55
#define DS18B20_CONVERT_TEMPERATURE 0x44
#define DS18B20_READ_SCRATCHPAD 0xBE
#define DS18B20_WRITE_SCRATCHPAD 0x4E
#define DS18B20_COPY_SCRATCHPAD 0x48
#define DS18B20_RECALL_E2 0xB8/* DS18B20 read temperature command */
#define DS18B20_CMD_CONVERTTEMP 0x44 /* Convert temperature */
#define DS18B20_DECIMAL_STEPS_12BIT 0.0625
#define DS18B20_DECIMAL_STEPS_11BIT 0.125
#define DS18B20_DECIMAL_STEPS_10BIT 0.25
#define DS18B20_DECIMAL_STEPS_9BIT 0.5/* Bits locations for resolution */
#define DS18B20_RESOLUTION_R1 6
#define DS18B20_RESOLUTION_R0 5#define DS18B20_ERROR_TEMP (-100)/***********************************************
* 描述: 外部调用函数声明
*/
int8_t bsp_Ds18b20Init(void);
int8_t bsp_Ds18b20Reset(void);
int16_t bsp_Ds18b20ReadTempReg(void);
int8_t bsp_Ds18b20ReadId(uint8_t *_id);
int16_t bsp_Ds18b20ReadTemp( void );
int16_t bsp_Ds18b20ReadTempById(uint8_t *_id);#endif
完整工程
- 完整的工程下载,请点击 CC2652RB读取温度传感器DS18B20,如果您没有积分可以留言,我单独发您。
PS:
- 使用IAR搭建CC2652RB的开发环境
- IAR FOR ARM 需要 8.50.9 及以上版本才能打开.
- 需要先安装 CC2652RB 的 SDK,且需要安装在默认位置(C:\ti).
这篇关于CC2652RB读取温度传感器DS18B20的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!