一.介绍
DS18B20是一种常用的数字温度传感器,输出数字信号,体积小,硬件成本低,抗干扰能力强,精度高。 [1] DS18B20数字温度传感器接线方便,包装后可应用于管道、螺纹、磁铁吸附、不锈钢包装、各种型号LTM8877,LTM8874等等。
它的外观主要根据不同的应用场合而变化。DS18B20可用于各种非极限温度场合,如电缆沟测温、高炉水循环测温、锅炉测温、机房测温、农业温室测温、洁净室测温、弹药库测温等。耐磨耐碰,体积小,使用方便,包装形式多样,适用于各种狭小空间设备的数字测温和控制。 来源(百度百科)。
初步了解后,有需要的同学可以看看这篇文章来了解它的原理来自一位优秀的博主Z小旋
二.cubemx配置和代码部分
由于DS8B20只有三个引脚,VCC,GND,剩下的引脚接单片机GPIO配置为输出上拉模式。
/** ****************************************************************************** * @file bsp_ds18b20.c * @author * @date * @version v1.0 * @note DHT11 driver ****************************************************************************** */ #include "ds18b20.h" void Delay_us(uint32_t time) { uint8_t i=0; while(time--) { i=10; //定义自己 while(i--) ; } } /** * @brief DS18B20 输出模式 */ static void DS18B20_Mode_OUT_PP(void) { GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = BSP_DS18B20_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(BSP_DS18B20_PORT, &GPIO_InitStruct); } /** * @brief DS18B20 输入模式 */ static void DS18B20_Mode_IN_NP(void) { GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = BSP_DS18B20_PIN; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(BSP_DS18B20_PORT, &GPIO_InitStruct); } /** * @brief 主机向从机发送复位脉冲 */ static void DS18B20_Reset(void) { DS18B20_Mode_OUT_PP(); // 主机输出 DS18B20_OUT_0; // 至少生成主机 480us 低电平复位信号 Delay_us(750); DS18B20_OUT_1; // 主机产生复位信号后,需要拉高总线 // 接收到主机的复位信号后,会在 15 ~ 60 us 然后给主机发脉冲 Delay_us(15); } /** * @brief 检测从机返回主机的脉冲 * @return 0:成功 1:失败 */ static uint8_t DS18B20_Presence(void) { uint8_t pulse_time = 0; DS18B20_Mode_IN_NP(); // 主机设置为输入 // 等待存在脉冲的到来,存在脉冲为一个 60 ~ 240 us 低电平信号 // 如果脉冲没有来,则应加班。从机器接收到主机的复位信号后,会在 15 ~ 60 us 然后给主机发脉冲 while (DS18B20_IN && (pulse_time < 100)) // 等待低电平响应脉冲 { pulse_time ; Delay_us(1); } // 经过 100 us 后,脉冲尚未到来 if (pulse_time >= 100) { return 1; } else { pulse_time = 0; } // 响应脉冲(低电平)到来,存在时间不能超过 240 us while(!(DS18B20_IN) && pulse_time < 240) { pulse_time ; Delay_us(1); } if(pulse_time >= 240) { return 1; } else { return 0; } } /** * @brief DS18B20 初始化函数 * @reurn 0:成功 1:失败 */ uint8_t DS18B20_Init(void) { DS18B20_Mode_OUT_PP(); DS18B20_OUT_1; DS18B20_Reset(); return DS18B20_Presence(); } /** * @brief 从DS18B20读取一个bit */ static uint8_t DS18B20_ReadBit(void) { uint8_t dat; DS18B20_Mode_OUT_PP(); // 读 0 和读 1 至少时间大于 60 us DS18B20_OUT_0; // 阅读时间的开始:必须由主机生成 > 1us < 15us 低电平信号 // 这一次很重要,设置为 < 15.需要多次尝试;如果设置不合理,数据将直接出错 // 建议设置参数 10 11 12.具体值应根据延迟函数的执行效率进行测试 Delay_us(10); DS18B20_Mode_IN_NP(); // 设置为输入,释放总线,外部上拉电阻拉高总线 if (DS18B20_IN == 1) { dat = 1; } else { dat = 0; } Delay_us(45); // 延迟参数参考时序图 return dat; } /** * @brief 从 DS18B20 读字节,低位先行 */ static uint8_t DS18B20_ReadByte(void) { uint8_t i, j, dat = 0; for(i = 0; i < 8; i ) { j = DS18B20_ReadBit(); dat = (dat) | (j << i); } return dat; } /** * @brief 写字节到 DS18B20,低位先行 */ static void DS18B20_WriteByte(uint8_t dat) { uint8_t i, testb; DS18B20_Mode_OUT_PP(); for( i = 0; i < 8; i ) { testb = dat & 0x01; dat = dat >> 1; // 写 0 和写 1 至少60岁以上us if (testb) // 当前位写 1 { DS18B20_OUT_0; Delay_us(5); // 降低写作时间段信号的发送 DS18B20_OUT_1; // 读取电平时间保持高电平 Delay_us(65); } else // 当前位写 0 { DS18B20_OUT_0; // 降低写作时间段信号的发送 Delay_us(70); // 读取电平时间保持低电平 DS18B20_OUT_1; Delay_us(2); // 恢复时间 } } } /** * @brief 跳过匹配 DS18B20 ROM */ static void DS18B20_SkipRom(void) { DS18B20_Reset(); DS18B20_Presence(); DS18B20_WriteByte(0XCC); /* 跳过 ROM */ } /** * @brief 执行匹配 DS18B20 ROM */ static void DS18B20_MatchRom(void) { DS18B20_Reset(); DS18B20_Presence(); DS18B20_WriteByte(0X55); /* 匹配 ROM */ } /** * 储存温度为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^ | 2^5 | 2^4 |
*
*
* 温度 = 符号位 + 整数 + 小数*0.0625
*/
/**
* @brief 在跳过匹配 ROM 情况下获取 DS18B20 温度值
* @param 无
* @retval 温度值
*/
float DS18B20_GetTemp_SkipRom(void)
{
uint8_t tpmsb, tplsb;
int16_t s_tem;
float f_tem;
DS18B20_SkipRom();
DS18B20_WriteByte(0X44); /* 开始转换 */
DS18B20_SkipRom();
DS18B20_WriteByte(0XBE); /* 读温度值 */
tplsb = DS18B20_ReadByte();
tpmsb = DS18B20_ReadByte();
s_tem = tpmsb << 8;
s_tem = s_tem | tplsb;
if(s_tem < 0) /* 负温度 */
{
f_tem = (~s_tem + 1) * 0.0625f;
}
else
{
f_tem = s_tem * 0.0625f;
}
return f_tem;
}
/**
* @brief 在匹配 ROM 情况下获取 DS18B20 温度值
* @param ds18b20_id:用于存放 DS18B20 序列号的数组的首地址
*/
void DS18B20_ReadId(uint8_t *ds18b20_id)
{
uint8_t uc;
DS18B20_WriteByte(0x33); //读取序列号
for (uc = 0; uc < 8; uc++)
{
ds18b20_id[uc] = DS18B20_ReadByte();
}
}
/**
* @brief 在匹配 ROM 情况下获取 DS18B20 温度值
* @param ds18b20_id:存放 DS18B20 序列号的数组的首地址
* @retval 温度值
*/
float DS18B20_GetTemp_MatchRom(uint8_t * ds18b20_id)
{
uint8_t tpmsb, tplsb, i;
int16_t s_tem;
float f_tem;
DS18B20_MatchRom(); /* 匹配ROM */
for(i = 0;i < 8; i++)
{
DS18B20_WriteByte(ds18b20_id[i]);
}
DS18B20_WriteByte(0X44); /* 开始转换 */
DS18B20_MatchRom(); /* 匹配ROM */
for(i = 0; i < 8; i++)
{
DS18B20_WriteByte(ds18b20_id[i]);
}
DS18B20_WriteByte(0XBE); /* 读温度值 */
tplsb = DS18B20_ReadByte();
tpmsb = DS18B20_ReadByte();
s_tem = tpmsb << 8;
s_tem = s_tem | tplsb;
if (s_tem < 0) /* 负温度 */
{
f_tem = (~s_tem + 1) * 0.0625f;
}
else
{
f_tem = s_tem * 0.0625f;
}
return f_tem;
}
#ifndef __DS18B20_H_
#define __DS18B20_H_
#include "stm32f1xx.h"
#include "core_cm3.h"
#include "stm32f1xx_hal.h"
#include "main.h"
#include "gpio.h"
#include "stm32f1xx_hal_gpio.h"
//#include "stdint.h"
#define BSP_DS18B20_PORT BSP_DS18B20_GPIO_Port
#define BSP_DS18B20_PIN BSP_DS18B20_Pin
#define DS18B20_OUT_1 HAL_GPIO_WritePin(BSP_DS18B20_PORT, BSP_DS18B20_PIN, GPIO_PIN_SET)
#define DS18B20_OUT_0 HAL_GPIO_WritePin(BSP_DS18B20_PORT, BSP_DS18B20_PIN, GPIO_PIN_RESET)
#define DS18B20_IN HAL_GPIO_ReadPin(BSP_DS18B20_PORT, BSP_DS18B20_PIN)
uint8_t DS18B20_Init(void);
void DS18B20_ReadId(uint8_t *ds18b20_id);
float DS18B20_GetTemp_SkipRom(void);
float DS18B20_GetTemp_MatchRom(uint8_t * ds18b20_id);
void Delay_us(uint32_t time);
#endif
在while1中, 这样调用,也可以用串口打印,看数据会更直观
这就是结果啦 欢迎指正 在此附上代码资源