STM32基于HAL库的DS18B20实现

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

创建工程

使能USART1

用来通过串口打印温度值
STM32基于HAL库的DS18B20实现_第1张图片

配置GPIO

STM32基于HAL库的DS18B20实现_第2张图片

代码编写

我们先打开 DS18B20 的手册

1、DS18B20 复位与存在脉冲

STM32基于HAL库的DS18B20实现_第3张图片

复位
/**
 * @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、读取数据

STM32基于HAL库的DS18B20实现_第4张图片

读取 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 写入数据

STM32基于HAL库的DS18B20实现_第5张图片

/**
 * @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指令进行操作的,下图展示获取温度的一种流程
STM32基于HAL库的DS18B20实现_第6张图片

/**
 * @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; 	
}

实验现象

STM32基于HAL库的DS18B20实现_第7张图片

想要完整驱动,查看评论

你可能感兴趣的:(STM32CubeMx,STM32HAL库,stm32,单片机,arm,嵌入式硬件,嵌入式)