【stm32协议外设篇】- DS18B20 单总线数字温度检测模块

一、适用场景

适用场景:环境温度监测、智能家居温控系统、电子温度计、设备过温保护、机房/电池温度监控、农业温室监测、嵌入式教学中"一线通信协议"实战学习等。

二、器材清单

DS18B20 数字温度传感器×1

stm32f103开发板 ×1

若干杜邦线 ×1组

三、工作原理(要点)

单总线通信(1-Wire):DS18B20 采用1-Wire 单总线协议,数据线 + GND 即可完成通信(正常模式下需外接上拉电阻)。

转换公式=原始数据×0.0625

四、接线示意

GND → GND

VCC→ 5V/3.3V电源

标准库

DQ→ PA0

HAL库

DQ→ PB0

五、示例代码

标准库

cpp 复制代码
#include "stm32f10x.h"
#include "stdio.h"
#include "bsp_SysTick.h"
#include "bsp_usart.h"
 

char show[20];
u16 temp=0;

void gpio_init()
{
	GPIO_InitTypeDef PA;
	
	//使能时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	PA.GPIO_Pin = GPIO_Pin_0;
	PA.GPIO_Mode = GPIO_Mode_Out_PP;
//	PA.GPIO_Mode = GPIO_Mode_IPU;
	PA.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&PA);
		
}
void startup()
{
	GPIO_SetBits(GPIOA,GPIO_Pin_0);
	GPIO_ResetBits(GPIOA,GPIO_Pin_0);
	Delay_us(500);
	GPIO_SetBits(GPIOA,GPIO_Pin_0);
	Delay_us(30);
	while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==RESET);
//	Delay_us(220);
}

void wirte_num(u8 address)
{
	int i;
	for(i=0;i<8;i++)
	{
		
		GPIO_ResetBits(GPIOA,GPIO_Pin_0);
		Delay_us(10);
		
		if(address&0x01)
			GPIO_SetBits(GPIOA,GPIO_Pin_0);
		else
			GPIO_ResetBits(GPIOA,GPIO_Pin_0);
		Delay_us(50);
		GPIO_SetBits(GPIOA,GPIO_Pin_0);
		address>>=1;
	}
}

u8 read_num()
{
	int num=0,i;
	for(i=0;i<8;i++)
	{
		num>>=1;
		GPIO_ResetBits(GPIOA,GPIO_Pin_0);
		Delay_us(10);
		GPIO_SetBits(GPIOA,GPIO_Pin_0);
//		Delay_us(5);		
		if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == SET)
			num|=0x80;

		
		Delay_us(50);
	
	}
	return num;
}

void read()
{
	u8 l_t=0,h_t=0;
	u16 t;
	startup();
	wirte_num(0xcc);
	wirte_num(0x44);
	
	startup();
	wirte_num(0xcc);
	wirte_num(0xbe);
	
	l_t=read_num();
	h_t=read_num();
	t=h_t<<8 | l_t;
	if((t&0xF800) == 0xF800)//判断是否为负数,求出补码并带入到相应的公式中
	{
		temp=(((~t)+0x01)*-0.0625+0.5)*10;
	}else
		temp=(t*0.0625+0.5)*10;
}

int main()
{
	SysTick_Init();	    	 //延时函数初始化
	USART_Config();	
	gpio_init();
	while(1)
	{
		Delay_us(1000000);
		read();
		sprintf(show,"tempture:%d.%d\n",temp/10,temp%10);
		Usart_SendString(USART1,show);
	}
}

HAL库

cpp 复制代码
#include "ds18b20.h"
#include "dht11.h"	
		

void DS18B20_Rst(void)	   
{                 
		DS18B20_Mode(OUT); 	//SET OUTPUT
    DS18B20_Low; 				//拉低DQ
    Tims_delay_us(750);    	//拉低750us
    DS18B20_High; 			//DQ=1 
		Tims_delay_us(15);     	//15US
}
//等待DS18B20的回应
//返回1:未检测到DS18B20的存在
//返回0:存在
u8 DS18B20_Check(void) 	   
{   
	u8 retry=0;
	DS18B20_Mode(IN);	//SET  INPUT	 
  while (HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)&&retry<200)
	{
		retry++;
		Tims_delay_us(1);
	}
	if(retry>=200)return 1;
	else retry=0;
   while (!HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)&&retry<240)
	{
		retry++;
		Tims_delay_us(1);
	}
	if(retry>=240)return 1;	    
	return 0;
}
//从DS18B20读取一个位
//返回值:1/0
u8 DS18B20_Read_Bit(void) 	 
{
    u8 data;
	DS18B20_Mode(OUT);	//SET OUTPUT
    DS18B20_Low; 
	Tims_delay_us(2);
    DS18B20_High; 
	DS18B20_Mode(IN);	//SET INPUT
	Tims_delay_us(12);
	if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0))
		data=1;
   else data=0;	 
    Tims_delay_us(50);           
    return data;
}
//从DS18B20读取一个字节
//返回值:读到的数据
u8 DS18B20_Read_Byte(void)     
{        
    u8 i,j,dat;
    dat=0;
	for (i=1;i<=8;i++) 
	{
        j=DS18B20_Read_Bit();
        dat=(j<<7)|(dat>>1);
    }						    
    return dat;
}
//写一个字节到DS18B20
//dat:要写入的字节
void DS18B20_Write_Byte(u8 dat)     
{             
    u8 j;
    u8 testb;
	DS18B20_Mode(OUT);	//SET OUTPUT;
    for (j=1;j<=8;j++) 
	{
        testb=dat&0x01;
        dat=dat>>1;
        if (testb) 
        {
            DS18B20_Low;	// Write 1
            Tims_delay_us(2);                            
            DS18B20_High;
            Tims_delay_us(60);             
        }
        else 
        {
            DS18B20_Low;	// Write 0
            Tims_delay_us(60);             
            DS18B20_High;
            Tims_delay_us(2);                          
        }
    }
}
//开始温度转换
void DS18B20_Start(void) 
{   						               
    DS18B20_Rst();	   
		DS18B20_Check();	 
    DS18B20_Write_Byte(0xcc);	// skip rom
    DS18B20_Write_Byte(0x44);	// convert
} 

//初始化DS18B20的IO口 DQ 同时检测DS的存在
//返回1:不存在
//返回0:存在    	 
u8 DS18B20_Init(void)
{
	__HAL_RCC_GPIOB_CLK_ENABLE();
	GPIO_InitTypeDef GPIO_InitStruct = {0};
  GPIO_InitStruct.Pin = GPIO_PIN_0;                //  9???
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;      //  Push Pull ??????
  GPIO_InitStruct.Pull = GPIO_NOPULL;              //  ????
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;    //  ??
  HAL_GPIO_Init(GPIOB,&GPIO_InitStruct);
	
	DS18B20_High;    //输出1

	DS18B20_Rst();

	return DS18B20_Check();
}  
//从ds18b20得到温度值
//精度:0.1C
//返回值:温度值 (-550~1250) 
short DS18B20_Get_Temp(void)
{
    u8 temp;
    u8 TL,TH;
	short tem;
    DS18B20_Start ();  			// ds1820 start convert
    DS18B20_Rst();
    DS18B20_Check();	 
    DS18B20_Write_Byte(0xcc);	// skip rom
    DS18B20_Write_Byte(0xbe);	// convert	    
    TL=DS18B20_Read_Byte(); 	// LSB   
    TH=DS18B20_Read_Byte(); 	// MSB  
	    	  
    if(TH>7)
    {
        TH=~TH;
        TL=~TL; 
        temp=0;					//温度为负  
    }else temp=1;				//温度为正	  	  
    tem=TH; 					//获得高八位
    tem<<=8;    
    tem+=TL;					//获得底八位
    tem=(float)tem*0.625;		//转换     
	if(temp)return tem; 		//返回温度值
	else return -tem;    
}

void DS18B20_Mode(u8 mode)
{
	__HAL_RCC_GPIOB_CLK_ENABLE();
	GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(mode)
  {
      /*  ??  */
		  GPIO_InitStruct.Pin = GPIO_PIN_0;                //  9???
      GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;      //  Push Pull ??????
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;    //  ??
  }
  else 
  {
      GPIO_InitStruct.Pin = GPIO_PIN_0;                   //  9???
      GPIO_InitStruct.Mode = GPIO_MODE_INPUT;             //  ????  
  }
	GPIO_InitStruct.Pull = GPIO_NOPULL;                 //  ????
	HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}


 

int main(void)
{
  /* USER CODE BEGIN 1 */
	short temperature = 0;
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_USART1_UART_Init();
	MX_TIM2_Init();
	while(DS18B20_Init())	//DS18B20初始化	
	{
		HAL_UART_Transmit(&huart1,"DS18B20 Error",strlen("DS18B20 Error"),HAL_MAX_DELAY);
		HAL_Delay(200);
		HAL_UART_Transmit(&huart1,"        ",strlen("        "),HAL_MAX_DELAY);
		HAL_Delay(200);
	}
  /* USER CODE END 2 */
	
  /* USER CODE BEGIN 2 */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {           
	  temperature=DS18B20_Get_Temp();
		sprintf((char*)show,"%4.1f\r\n",(float)temperature/10);
		HAL_UART_Transmit(&huart1,show,strlen(show),HAL_MAX_DELAY);
		HAL_Delay(1000);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

六、讲解视频

https://www.bilibili.com/video/BV1wKviBZEWD/?spm_id_from=333.1387.search.video_card.click&vd_source=f7dfe1b14f260b9cc3a146d2dbfd0719

https://www.bilibili.com/video/BV1jivvBEEXh/?spm_id_from=333.1387.search.video_card.click&vd_source=f7dfe1b14f260b9cc3a146d2dbfd0719

https://www.bilibili.com/video/BV1LzvvBjEkW/?spm_id_from=333.1387.search.video_card.click&vd_source=f7dfe1b14f260b9cc3a146d2dbfd0719

相关推荐
羽获飞2 小时前
从零开始学嵌入式之STM32——12.使用STM32普通引脚通过软件模拟实现I2C通讯协议
stm32·单片机·嵌入式硬件
LCG元2 小时前
嵌入式GUI设计:STM32F429+LVGL,智能仪表盘界面开发指南
驱动开发·stm32·嵌入式硬件
姜太公钓鲸2332 小时前
RAM就是运行内存,实际的存储介质是SRAM。上述文字中的运行内存、存储介质是什么意思?
stm32
意法半导体STM322 小时前
【官方原创】使用GPDMA进行SPI LCD整屏传输 LAT1435
网络·stm32·单片机·嵌入式硬件·mcu·网络协议·stm32开发
螺丝钉的扭矩一瞬间产生高能蛋白2 小时前
深入剖析FreeRTOS优先级继承机制:vTaskPriorityInherit与xTaskPriorityDisinherit源码解析
stm32·freertos·嵌入式软件·优先级反转
姜太公钓鲸2333 小时前
时钟周期是什么?
单片机·嵌入式硬件
bepeater12343 小时前
Laravel9.X核心特性全面解析
c语言·c++·c#·php
bing_feilong3 小时前
Jetson Orin Nano(3): Button Header
嵌入式硬件
悠哉悠哉愿意3 小时前
【物联网学习笔记】中断
笔记·单片机·嵌入式硬件·物联网·学习