【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

相关推荐
芯联智造18 小时前
【stm32简单外设篇】- WS2812单线地址式 RGB 灯带
c语言·stm32·单片机·嵌入式硬件
7yewh21 小时前
jetson_yolo_deployment 02_linux_dev_skills
linux·python·嵌入式硬件·yolo·嵌入式
djarmy21 小时前
ubuntu20.04搭建openharmony6.0的master分支。构建编译环境报错解决记录
c语言·ubuntu
竹烟淮雨1 天前
C语言指针概念详解:数组指针与二级指针的本质区别
c语言
senijusene1 天前
用C语言制作一个简易HTTP服务器:实现手机商城用户认证与搜索
服务器·c语言·http
Aaswk1 天前
蓝桥杯2025年第十六届省赛真题(更新中)
c语言·数据结构·c++·算法·职场和发展·蓝桥杯
香水5只用六神1 天前
【DMA】存储器到外设模式实验2
c语言·git·stm32·单片机·嵌入式硬件·github·visual studio
Yupureki1 天前
《C++实战项目-高并发内存池》4.CentralCache构造
c语言·开发语言·c++·单例模式·github
forAllforMe1 天前
用STM32+LAN9252实现etherCAT 从站IO控制
stm32·单片机·嵌入式硬件
AnalogElectronic1 天前
RP2040学习4,LED点亮,OLED显示,DHT11温湿度传感器数据读取
单片机·嵌入式硬件·学习