STM32基於HAL庫的DS18B20實現

2022-01-09 18:00:01

開發板:野火挑戰者_V2
GPIO:PE2

建立工程

使能USART1

用來通過串列埠列印溫度值
在這裡插入圖片描述

設定GPIO

在這裡插入圖片描述

程式碼編寫

我們先開啟 DS18B20 的手冊

1、DS18B20 復位與存在脈衝

在這裡插入圖片描述

復位
/*
	DS18B20 復位
	將匯流排拉低 480us - 960us 啟動復位,然後等待 15us 檢測存在脈衝
*/
void Ds18b20_Reset(void)
{
	//輸出模式下
	DQ_GPIO_OUT();
	
	//拉低匯流排 750us
	DQ_Write(DQ_LEVEL_LOW);
	HAL_Delay_Us(750);
	
	//釋放匯流排,等待存在脈衝
	DQ_Write(DQ_LEVEL_HIGHT);
	HAL_Delay_Us(15);
}
檢測存在脈衝
/*
	檢測存在脈衝	
	  存在: 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++;
		HAL_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++;
		HAL_Delay_Us(1);
	}
	
	/* 由時序圖可知,存在脈衝最長不得超過 240us */
	if (Time_Count >= 240)
		return 1;
	else
		return 0;    //檢測到存在脈衝
}

2、讀取資料

在這裡插入圖片描述

讀取 1Bit
/*
	讀取 1bit 
	先將匯流排拉低 15us 後,讀取匯流排狀態
*/ 
uint8_t Ds18b20_Read_Bit(void)
{
	uint8_t dat;
	//輸出模式
	DQ_GPIO_OUT();
	
	//先拉低匯流排 15us 後讀取匯流排狀態
	DQ_Write(DQ_LEVEL_LOW);
	HAL_Delay_Us(15);
	
	//下面要讀取匯流排值,將引腳設定成輸入模式
	DQ_GPIO_IN();
	
	if (DQ_Read == SET)
		dat = 1;
	else
		dat = 0;
	
	//讀取週期至少 60us
	HAL_Delay_Us(50);
	
	return dat;
}
讀取 1Byte
/* 
	從 DS18B20 上讀取 1Byte
  低位到高位
*/
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 寫入資料

在這裡插入圖片描述

/*
	寫位元組,低位先行
  
  寫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);
			HAL_Delay_Us(70);
			
			//2us 的恢復時間
			DQ_Write(DQ_LEVEL_HIGHT);
			HAL_Delay_Us(2);
		}
		else  //寫1
		{
			/* 拉低匯流排大於 1us 並且小於 15us */
			DQ_Write(DQ_LEVEL_LOW);
			HAL_Delay_Us(9);
			
			/* 拉高匯流排,總時間超過 60us */
			DQ_Write(DQ_LEVEL_HIGHT);
			HAL_Delay_Us(55);
		}
	}
}

4、獲取溫度

DS18B20是通過ROM指令進行操作的,下圖展示獲取溫度的一種流程
在這裡插入圖片描述

/*
	獲取溫度
	此獲取方法為跳過 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; 	
}

實驗現象

在這裡插入圖片描述

想要完整工程,點選評論