普中STM32-PZ6806L开发板(HAL库函数实现-温度传感器DS18B20)

2024-01-08 10:46:55

简介

主芯片STM32F103ZET6, 通过引脚PG11 连接DS18B20, 读取DS18B20采集的温度数据;

电路原理图

DS18B20电路图
在这里插入图片描述
DS18B20 与 主芯片连接引脚
在这里插入图片描述

其他知识

DS18B20资料

DS18B20数据手册

DS18B20 简介

单线通讯的温度传感器,
测量温度在-55℃ 到 +125℃,
在-10°C 到 +85°C精度±0.5°C,
9~12bit 可设定分辨率,
默认12bit分辨率,
12bit分辨率下温度转化时间在最长是750ms,
温度值存在DS18B20 ROM中是补码的形式存储, 负值需要 取反 + 1才能得到原码

实现步骤

时序图中设计到的采集数据时有进行us级别的延时, 需要将系统改成us级别或者定义一个TIMER作为us级别的延时器

创建项目

参考 普中STM32-PZ6806L开发板(STM32CubeMX创建项目并点亮LED灯)

TIM2 实现us级别延时

参考 普中STM32-PZ6806L开发板(HAL库函数实现-TIM2实现us延时)

引脚初始化

默认初始化为输出
在这里插入图片描述

添加用户代码

引脚输入输出变动代码

引脚涉及到 输入 和 输出, 所以我们需要在代码里面实现输入和输出可以切换的方式, 代码如下

	static void SENSOR_DS18B20_SetPinInput(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	
	GPIO_InitStruct.Pin = GPIO_Pin;
	GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	HAL_GPIO_Init(GPIOx, &GPIO_InitStruct);
}

static void SENSOR_DS18B20_SetPinOutput(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
	GPIO_InitTypeDef  GPIO_InitStruct;
	
	GPIO_InitStruct.Pin = GPIO_Pin;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	HAL_GPIO_Init(GPIOx, &GPIO_InitStruct);
}

初始化时序代码

在这里插入图片描述

/*
	SENSOR_DS18B20_Reset :
	初始化,也是复位, 每次发送指令前的动作
		0 : 初始化失败
		1 : 初始化成功
*/
static uint8_t SENSOR_DS18B20_Reset(void)
{
	uint8_t res = 0;
	SENSOR_DS18B20_SetPinOutput(DS18B20_PORT, DS18B20_PIN);   // 引脚输出模式
	HAL_GPIO_WritePin (DS18B20_PORT, DS18B20_PIN, 0);  // 拉低引脚
	delay_us (480);   // 参考初始化时序图, 延时480us

	SENSOR_DS18B20_SetPinInput(DS18B20_PORT, DS18B20_PIN);    // set the pin as input
	delay_us (60);    // 15~60us等待DS18B20回复信息, 多等20us避免检测不到

	if ( !HAL_GPIO_ReadPin(DS18B20_PORT, DS18B20_PIN) )
		res = 1;  // 检测到低电平,  DS18B20有响应
	else 
		res = 0;

	delay_us (420); // 等待DS18B20结束响应

	return res;
}

读写时序代码

在这里插入图片描述

void SENSOR_DS18B20_Write(uint8_t data)
{
	/*
		按位写, 根据时序图, 按照写的 高电平的时序 和 低电平的时序进行延时
	*/
	for (int i = 0; i < 8; ++i)
	{

		if ((data & (1<<i))!=0) // 写1
		{
			SENSOR_DS18B20_SetPinOutput(DS18B20_PORT, DS18B20_PIN);  
			HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, 0);  // 拉低
			delay_us (2);  // 低电平保持时间

			SENSOR_DS18B20_SetPinInput(DS18B20_PORT, DS18B20_PIN);  // 输入
			delay_us (60);  // 等待
		}
		else // 写0
		{
			SENSOR_DS18B20_SetPinOutput(DS18B20_PORT, DS18B20_PIN);
			HAL_GPIO_WritePin (DS18B20_PORT, DS18B20_PIN, 0);  // 拉低
			delay_us (60);  // 等待60us

			SENSOR_DS18B20_SetPinInput(DS18B20_PORT, DS18B20_PIN); // 输入
		}
	}
}

uint8_t SENSOR_DS18B20_Read (void)
{
	uint8_t value = 0;

	for (int i=0;i<8;i++)
	{
		SENSOR_DS18B20_SetPinOutput(DS18B20_PORT, DS18B20_PIN);

		HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, 0);  // 拉低
		delay_us(2);  // 拉低电平等待时间

		SENSOR_DS18B20_SetPinInput(DS18B20_PORT, DS18B20_PIN);
		if (HAL_GPIO_ReadPin (DS18B20_PORT, DS18B20_PIN))  
		{
			value |= 1<<i;  
		}
		delay_us (60);  // DS18B20数据响应时间
	}
	return value;
}

获取温度值
float SENSOR_DS18B20_GetTemperature(void)
{
	
	uint8_t lsb_byte, msb_byte;
	uint16_t temp = 0;
	float value = 0.0;
	
	
	SENSOR_DS18B20_Reset ();
	HAL_Delay (1);
	SENSOR_DS18B20_Write (0xCC);  // skip ROM
	SENSOR_DS18B20_Write (0x44);  // convert t
	HAL_Delay (800); // 12bit分辨率最长转换时间750ms

	SENSOR_DS18B20_Reset ();
	HAL_Delay (1);
	SENSOR_DS18B20_Write (0xCC);  // skip ROM
	SENSOR_DS18B20_Write (0xBE);  // 读值指令
	
	lsb_byte = SENSOR_DS18B20_Read(); // LSB
	msb_byte = SENSOR_DS18B20_Read(); // MSB
	temp = msb_byte;
	temp = (temp<<8) + lsb_byte; // 合并
	
	if((temp&0xf800)==0xf800) // 符号位判定是否负数
	{
		temp=(~temp)+1; // 补码转原码
		value=temp*(-0.0625); //12bit 增量值
	}
	else
	{
		value=temp*0.0625;	//12bit 增量值
	}
	
	return value;
}

main.c

int main()
{
...
	while (1)
	{
		printf("sensors temp: %f\r\n", SENSOR_DS18B20_GetTemperature());
		HAL_Delay(2000);
	}
...
}

共赏

在这里插入图片描述

代码

不需要下载, 基本代码上面都提供了

参考

普中STM32-PZ6806L开发板(HAL库函数实现-批量操作GPIO引脚实现跑马灯)

结语

在网上看到一种利用串口单线半双工原理读取数据 的, 也是很有意思(未试验过)。。。

文章来源:https://blog.csdn.net/halo_hsuh/article/details/135369882
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。