于LL库以及DS18B20数据手册编写单总线协议读取DS18B20温度传感器数据,使用CUBEMX配置引脚,通过修改系统时基配置设定1us的时基,精准延时实现单总线协议驱动。
<系统时钟配置>

void SystemClock_Config(void)
{
  LL_FLASH_SetLatency(LL_FLASH_LATENCY_2);
  while(LL_FLASH_GetLatency()!= LL_FLASH_LATENCY_2)
  {
  }
  LL_RCC_HSE_Enable();

   /* Wait till HSE is ready */
  while(LL_RCC_HSE_IsReady() != 1)
  {

  }
  LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE_DIV_1, LL_RCC_PLL_MUL_9);
  LL_RCC_PLL_Enable();

   /* Wait till PLL is ready */
  while(LL_RCC_PLL_IsReady() != 1)
  {

  }
  LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
  LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_2);
  LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);
  LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);

   /* Wait till System clock is ready */
  while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
  {

  }
  LL_Init1usTick(72000000);
  LL_SetSystemCoreClock(72000000);
  LL_RCC_ConfigMCO(LL_RCC_MCO1SOURCE_PLLCLK_DIV_2);
}

  由于CUBEMX配置时钟时默认时基是1ms,所以修改时钟配置,定义1us时基函数。

  定义好1us时基后可直接采用LL库提供的延时函数LL_mDelay,为了避免写代码时的误区所以重新命名一个延时函数,函数内容不变,因为此时时基已经被修改为1us所以延时函数也是1us。

  时基确定之后接下来写DS18B20驱动,本文只提供示例代码,具体可以根据个人需求修改GPIO端口,数据手册上的内容在此不在赘述,感兴趣的可以在网上搜索,有很多,本文只实现单DS18B20的驱动,多个DS18B20根据数据手册发送不同指令寻址即可。
<DS18B20.c>

#define DS18B20_Pin_Port		GPIO_Port
#define DS18B20_Pin				GPIO_Pin
#define DS18B20_MTX		GPIOx -> CRL = 0xXX; //配置寄存器的方式修改GPIO模式,查询ST编程手册GPIO部分寄存器
#define DS18B20_MRX		GPIOx -> CRL = 0xXX; //配置寄存器的方式修改GPIO模式,查询ST编程手册GPIO部分寄存器
#define DS18B20_H			    LL_GPIO_SetOutputPin(GPIO_Port , GPIO_Pin);
#define DS18B20_L				LL_GPIO_ResetOutputPin(GPIO_Port , GPIO_Pin);
#define DS18B20_CHECK_EN    LL_GPIO_IsInputPinSet(GPIO_Port ,GPIO_Pin)  //检查单总线是高电平还是低电平
#define DS18B20_RX_DATA		LL_GPIO_IsInputPinSet(GPIO_Port , GPIO_Pin) //检查单总线是高电平还是低电平
#define	DS18B20_EN_FAIL			0    //失能标志,本程序未使用
#define DS18B20_EN_SUESS		1    //使能标志,本程序未使用


uint8_t DS18B20_EN_Flag = 0;
uint8_t	Temperature_L = 0x00;
uint8_t Temperature_H = 0x00;
float Temperature = 0;
uint16_t Temperature_sum = 0;

void DS18B20_Reset(void)                //复位DS18B20
{
		DS18B20_L
		LL_usDelay(1000);
		DS18B20_MRX
		LL_usDelay(60);
		if(DS18B20_CHECK_EN)
		{
				DS18B20_EN_Flag = DS18B20_EN_FAIL;
		}
		else
		{
				DS18B20_EN_Flag = DS18B20_EN_SUESS;
		}
		LL_usDelay(240);
		DS18B20_H
		DS18B20_MTX
}

void DS18B20_W_0(void)              //主机向DS18B20写0
{	
		DS18B20_L
		LL_usDelay(60);
		DS18B20_H
}

void DS18B20_W_1(void)              //主机向DS18B20写1
{
		DS18B20_L
		LL_usDelay(1);
		DS18B20_MRX
		LL_usDelay(59);
		DS18B20_H
		DS18B20_MTX
}

uint8_t DS18B20_Read(uint8_t receive)          //读取DS18B20数据
{
		uint8_t data = 0;
		receive = 0;
		for(int i = 0 ; i < 8 ; i ++)
		{
				DS18B20_L
				LL_usDelay(1);
				DS18B20_MRX
				LL_usDelay(9);
				data = DS18B20_RX_DATA;
				LL_usDelay(5);
				data <<= i;
				receive |= data;
				LL_usDelay(45);
				DS18B20_H
				DS18B20_MTX
		}
		return receive;
}

void DS18B20_TX_COMMAND(uint8_t command)        //发送8位数据
{
		for(int i = 0 ; i < 8 ; i ++)
		{
				if(command & 0x01)
				{
						DS18B20_W_1();
				}
				else
				{
						DS18B20_W_0();
				}
				command >>= 1;
		}
}	

void DS18B20_Temp_Get(void)        //温度数据读取
{
		DS18B20_Reset();
		DS18B20_TX_COMMAND(0xCC);    //跳过ROM
		DS18B20_TX_COMMAND(0x44);    //执行温度转换
		DS18B20_Reset();
		DS18B20_TX_COMMAND(0xCC);    //跳过ROM
		DS18B20_TX_COMMAND(0xBE);    //执行温度转换
		Temperature_L = DS18B20_Read(Temperature_L);
		Temperature_H = DS18B20_Read(Temperature_H);
		
}

void Temperature_cal(void)        //温度高低字节组合并转换计算成实际摄氏度(12位精度×系数0.0625)
{
		Temperature_sum = Temperature_H << 8;
		Temperature_sum |= Temperature_L;
		if(Temperature_sum & 0xF000)
		{
				Temperature_sum = ~(Temperature_sum);
				Temperature = (float)(Temperature_sum) * (- 0.0625);
		}
		else
		{
				Temperature = (float)Temperature_sum * 0.0625;
		}
}

<DS18B20.h>

#ifndef __DS18B20_H
#define __DS18B20_H

#include "main.h"

extern uint16_t Temperature_sum;
extern uint16_t	Temperature_hex;
extern float Temperature;
extern uint8_t	Temperature_L;
extern uint8_t Temperature_H;

void DS18B20_W_0(void);
void DS18B20_W_1(void);
void DS18B20_Reset(void);
uint8_t DS18B20_Read(uint8_t receive);
void DS18B20_Temp_Get(void);
void DS18B20_TX_COMMAND(uint8_t command);
void Temperature_cal(void);

#endif

  读取后的数据保存在Temperature中,使用串口打印或者串口屏的方式显示出来,本文不作赘述。

Author:李家琦

Date:2025/7/26

posted on 2025-08-19 11:25  77&&yr  阅读(16)  评论(0)    收藏  举报