STM32基于HAL库的DS18B20实现

开发板:野火挑战者_V2
GPIO:PE2

创建工程

使能USART1

用来通过串口打印温度值
在这里插入图片描述

配置GPIO

在这里插入图片描述

代码编写

我们先打开 DS18B20 的手册

1、DS18B20 复位与存在脉冲

在这里插入图片描述

复位
/**
 * @brief  DS18B20 复位
 * @param  无
 * @return 无
 * @note 将总线拉低 480us - 960us 启动复位,然后等待 15us 检测存在脉冲
 */
void Ds18b20_Reset(void)
{
	//输出模式下
	DQ_GPIO_OUT();
	
	//拉低总线 750us
	DQ_Write(DQ_LEVEL_LOW);
	Delay_Us(750);
	
	//释放总线,等待存在脉冲
	DQ_Write(DQ_LEVEL_HIGHT);
	Delay_Us(15);
}
检测存在脉冲
/**
 * @brief  检测存在脉冲	
 * @param  无
 * @return   存在脉冲: 0 
 *         不存在脉冲: 1
 */
uint8_t Ds18B20_CheckPulse(void)
{
	/* 超时计数,若设备不存在,需要退出,不能一直等待 */
	uint8_t Time_Count = 0;
	
	//将 GPIO 改成输入模式下
	DQ_GPIO_IN();
	
	/* 对应时序中的 DS18B20 等待 (15 - 60)us */
	while (DQ_Read && Time_Count < 100)
	{
		Time_Count++;
		Delay_Us(1);
	}
	
	/* 已经过去了 100us 存在脉冲还没到来,代表设备不存在 */
	if (Time_Count >= 100)
		return 1;   
	/* 脉冲到来,复位超时计数 */
	else
		Time_Count = 0;
	
	/* 对应时序中的 DS18B20 存在脉冲 (60 - 240)us */
	while (!DQ_Read && Time_Count < 240)
	{
		Time_Count++;
		Delay_Us(1);
	}
	
	/* 由时序图可知,存在脉冲最长不得超过 240us */
	if (Time_Count >= 240)
		return 1;
	else
		return 0;    //检测到存在脉冲
}

2、读取数据

在这里插入图片描述

读取 1Bit
/**
 * @brief  读取1bit数据 
 * @param  无
 * @return 读取到1Bit的数据
 * @note   先将总线拉低 15us 后,读取总线状态
 */ 
uint8_t Ds18b20_Read_Bit(void)
{
	uint8_t dat;
	//输出模式
	DQ_GPIO_OUT();
	
	//先拉低总线 15us 后读取总线状态
	DQ_Write(DQ_LEVEL_LOW);
	Delay_Us(15);
	
	//下面要读取总线值,将引脚设置成输入模式
	DQ_GPIO_IN();
	
	if (DQ_Read == SET)
		dat = 1;
	else
		dat = 0;
	
	//读取周期至少 60us
	Delay_Us(50);
	
	return dat;
}
读取 1Byte
/** 
 * @brief  从 DS18B20 上读取 1Byte
 * @param  无
 * @return 读到的8位数据
 * @note   低位到高位
 */
uint8_t Ds18B20_Read_Byte(void)
{
	uint8_t data = 0x00,mask;
	
	for (mask = 0x01;mask != 0;mask <<= 1)
	{
		if (Ds18b20_Read_Bit() == SET)
			data |= mask;
		else
			data &= ~mask;
	}
	
	return data;
}

3、向 DS18B20 写入数据

在这里插入图片描述

/**
 * @brief  写入一字节数据,低位先行
 * @param  data 写入的数据 
 * @return 无
 * @note  写0: 由时序图可知,拉低总线至少 60us 表示写 0
          写1: 由时序图可知,拉低总线大于 1us 并且小于 15us 后,紧接着拉高总线,总时间超过 60us
          写周期必须有 1us 的恢复时间
 */
void Ds18B20_Write_Byte(uint8_t data)
{
	uint8_t mask;
	
	for (mask = 0x01;mask != 0;mask <<= 1)
	{
		DQ_GPIO_OUT();
		
		//写0
		if ((data & mask) == RESET)
		{
			/* 拉低总线至少 60us */
			DQ_Write(DQ_LEVEL_LOW);
			Delay_Us(70);
			
			//2us 的恢复时间
			DQ_Write(DQ_LEVEL_HIGHT);
			Delay_Us(2);
		}
		else  //写1
		{
			/* 拉低总线大于 1us 并且小于 15us */
			DQ_Write(DQ_LEVEL_LOW);
			Delay_Us(9);
			
			/* 拉高总线,总时间超过 60us */
			DQ_Write(DQ_LEVEL_HIGHT);
			Delay_Us(55);
		}
	}
}

4、获取温度

DS18B20是通过ROM指令进行操作的,下图展示获取温度的一种流程
在这里插入图片描述

/**
 * @brief  获取温度
 * @param  无
 * @return 从DS18B20上读取到的温度值
 * @note   此获取方法为跳过 ROM 读取,适合于总线上只有一个设备
 */
float Ds18b20_Get_Temp(void)
{
	uint8_t tpmsb, tplsb;
	short s_tem;
	float f_tem;
	
	Ds18b20_Reset();	   
	Ds18B20_CheckPulse();	 
	Ds18B20_Write_Byte(SKIP_ROM);				         /* 跳过 ROM */
	Ds18B20_Write_Byte(CONVERT_TEMP);				     /* 开始转换 */
	
	Ds18b20_Reset();	   
	Ds18B20_CheckPulse();	 
	Ds18B20_Write_Byte(SKIP_ROM);				        /* 跳过 ROM */
	Ds18B20_Write_Byte(READ_SCRATCHPAD);				/* 读温度值 */
	
	tplsb = Ds18B20_Read_Byte();		 
	tpmsb = Ds18B20_Read_Byte(); 
	
	s_tem = tpmsb<<8;
	s_tem = s_tem | tplsb;
	
	if( s_tem < 0 )		/* 负温度 */
		f_tem = (~s_tem+1) * 0.0625;	
	else
		f_tem = s_tem * 0.0625;
	
	return f_tem; 	
}

实验现象

在这里插入图片描述

想要完整驱动,查看评论

版权声明:本文为CSDN博主「点灯大师~」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_47329175/article/details/122378100

开发板:野火挑战者_V2
GPIO:PE2

创建工程

使能USART1

用来通过串口打印温度值
在这里插入图片描述

配置GPIO

在这里插入图片描述

代码编写

我们先打开 DS18B20 的手册

1、DS18B20 复位与存在脉冲

在这里插入图片描述

复位
/**
 * @brief  DS18B20 复位
 * @param  无
 * @return 无
 * @note 将总线拉低 480us - 960us 启动复位,然后等待 15us 检测存在脉冲
 */
void Ds18b20_Reset(void)
{
	//输出模式下
	DQ_GPIO_OUT();
	
	//拉低总线 750us
	DQ_Write(DQ_LEVEL_LOW);
	Delay_Us(750);
	
	//释放总线,等待存在脉冲
	DQ_Write(DQ_LEVEL_HIGHT);
	Delay_Us(15);
}
检测存在脉冲
/**
 * @brief  检测存在脉冲	
 * @param  无
 * @return   存在脉冲: 0 
 *         不存在脉冲: 1
 */
uint8_t Ds18B20_CheckPulse(void)
{
	/* 超时计数,若设备不存在,需要退出,不能一直等待 */
	uint8_t Time_Count = 0;
	
	//将 GPIO 改成输入模式下
	DQ_GPIO_IN();
	
	/* 对应时序中的 DS18B20 等待 (15 - 60)us */
	while (DQ_Read && Time_Count < 100)
	{
		Time_Count++;
		Delay_Us(1);
	}
	
	/* 已经过去了 100us 存在脉冲还没到来,代表设备不存在 */
	if (Time_Count >= 100)
		return 1;   
	/* 脉冲到来,复位超时计数 */
	else
		Time_Count = 0;
	
	/* 对应时序中的 DS18B20 存在脉冲 (60 - 240)us */
	while (!DQ_Read && Time_Count < 240)
	{
		Time_Count++;
		Delay_Us(1);
	}
	
	/* 由时序图可知,存在脉冲最长不得超过 240us */
	if (Time_Count >= 240)
		return 1;
	else
		return 0;    //检测到存在脉冲
}

2、读取数据

在这里插入图片描述

读取 1Bit
/**
 * @brief  读取1bit数据 
 * @param  无
 * @return 读取到1Bit的数据
 * @note   先将总线拉低 15us 后,读取总线状态
 */ 
uint8_t Ds18b20_Read_Bit(void)
{
	uint8_t dat;
	//输出模式
	DQ_GPIO_OUT();
	
	//先拉低总线 15us 后读取总线状态
	DQ_Write(DQ_LEVEL_LOW);
	Delay_Us(15);
	
	//下面要读取总线值,将引脚设置成输入模式
	DQ_GPIO_IN();
	
	if (DQ_Read == SET)
		dat = 1;
	else
		dat = 0;
	
	//读取周期至少 60us
	Delay_Us(50);
	
	return dat;
}
读取 1Byte
/** 
 * @brief  从 DS18B20 上读取 1Byte
 * @param  无
 * @return 读到的8位数据
 * @note   低位到高位
 */
uint8_t Ds18B20_Read_Byte(void)
{
	uint8_t data = 0x00,mask;
	
	for (mask = 0x01;mask != 0;mask <<= 1)
	{
		if (Ds18b20_Read_Bit() == SET)
			data |= mask;
		else
			data &= ~mask;
	}
	
	return data;
}

3、向 DS18B20 写入数据

在这里插入图片描述

/**
 * @brief  写入一字节数据,低位先行
 * @param  data 写入的数据 
 * @return 无
 * @note  写0: 由时序图可知,拉低总线至少 60us 表示写 0
          写1: 由时序图可知,拉低总线大于 1us 并且小于 15us 后,紧接着拉高总线,总时间超过 60us
          写周期必须有 1us 的恢复时间
 */
void Ds18B20_Write_Byte(uint8_t data)
{
	uint8_t mask;
	
	for (mask = 0x01;mask != 0;mask <<= 1)
	{
		DQ_GPIO_OUT();
		
		//写0
		if ((data & mask) == RESET)
		{
			/* 拉低总线至少 60us */
			DQ_Write(DQ_LEVEL_LOW);
			Delay_Us(70);
			
			//2us 的恢复时间
			DQ_Write(DQ_LEVEL_HIGHT);
			Delay_Us(2);
		}
		else  //写1
		{
			/* 拉低总线大于 1us 并且小于 15us */
			DQ_Write(DQ_LEVEL_LOW);
			Delay_Us(9);
			
			/* 拉高总线,总时间超过 60us */
			DQ_Write(DQ_LEVEL_HIGHT);
			Delay_Us(55);
		}
	}
}

4、获取温度

DS18B20是通过ROM指令进行操作的,下图展示获取温度的一种流程
在这里插入图片描述

/**
 * @brief  获取温度
 * @param  无
 * @return 从DS18B20上读取到的温度值
 * @note   此获取方法为跳过 ROM 读取,适合于总线上只有一个设备
 */
float Ds18b20_Get_Temp(void)
{
	uint8_t tpmsb, tplsb;
	short s_tem;
	float f_tem;
	
	Ds18b20_Reset();	   
	Ds18B20_CheckPulse();	 
	Ds18B20_Write_Byte(SKIP_ROM);				         /* 跳过 ROM */
	Ds18B20_Write_Byte(CONVERT_TEMP);				     /* 开始转换 */
	
	Ds18b20_Reset();	   
	Ds18B20_CheckPulse();	 
	Ds18B20_Write_Byte(SKIP_ROM);				        /* 跳过 ROM */
	Ds18B20_Write_Byte(READ_SCRATCHPAD);				/* 读温度值 */
	
	tplsb = Ds18B20_Read_Byte();		 
	tpmsb = Ds18B20_Read_Byte(); 
	
	s_tem = tpmsb<<8;
	s_tem = s_tem | tplsb;
	
	if( s_tem < 0 )		/* 负温度 */
		f_tem = (~s_tem+1) * 0.0625;	
	else
		f_tem = s_tem * 0.0625;
	
	return f_tem; 	
}

实验现象

在这里插入图片描述

想要完整驱动,查看评论

版权声明:本文为CSDN博主「点灯大师~」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_47329175/article/details/122378100

生成海报
点赞 0

点灯大师~

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

STM32基于HAL库的DS18B20实现

开发板:野火挑战者_V2 GPIO:PE2 创建工程 使能USART1 用来通过串口打印温度值 配置GPIO 代码编写 我们先打开 DS18B20 的手册 1、DS18B20 复位与存在脉冲 复位 /*

MDK 分散加载文件剖析(一)

1、何为分散加载? 1.1 简介 分散加载就是我们开发者能指定你的 代码 或者 数据变量 到指定的内存空间中运行。通知链接器把程序的某一部分连接在存储器的某个地址空间,我们可以通过编写一个分散加载文件来指定 ARM

stm32——4、中断exti

这里是基于正点原子开发板的学习记录。 首先你要加入固件库 stm32f10x_exti.h 和 stm32f10x_exti.c 1、STM32中每个io口都可以作为外部中断的中断输入口。 2、STM32F103的中断控制器支持19个外部中断/