首页 > 其他分享 >训练题——DS18B20部分

训练题——DS18B20部分

时间:2022-11-13 11:44:37浏览次数:76  
标签:gt 训练 temp DS18B20 us delay 部分 DQ

Author:Cherry_Ywj

0. 前言

本文档以 DS18B20 为例,主要介绍如何针对一种传感器编写相应的驱动库,驱动是单片机开发中难度较大的一环。从看别人代码并对照 datasheet 开始,学会调用别人编写的库,然后尝试着自己写。

1. 基础内容

1.1 开漏输出

STM32 的输出模式有推挽输出开漏输出,推挽输出已经使用的很熟练了,也很简单,而开漏输出有一些新的特性。

image

在开漏模式时,上管 P-MOS 始终关断,呈现高阻态,输出控制只控制下管 N-MOS。所以,开漏模式没法主动输出高电平。因此,一般在设置开漏模式时,需要设置上拉模式。当设置输出为高电平时,实际上高电平是上拉电阻提供的,而输出低电平时,导通 N-MOS 即可。

强上拉和弱上拉

弱上拉指的是上拉电阻比较大,想想电阻的串并联,上拉电阻比较大时,如果外接一个比较小的电阻至地,则输出的电压就会比较小。

image

因此,上拉电阻越小,上拉就越强。开漏输出的上拉电阻是比较弱的上拉(上拉电阻约为40kΩ),所以在 DS18B20 的数据线上需要加一个 4.7kΩ 左右的上拉电阻,这个在后面会提到。

上面是开漏输出的一个特性,第二个特性是它还可以读取当前的引脚状态,即当成输入模式使用。这在双向传输数据都在一根数据线上的通信过程中非常有用。

1.2 datasheet

在之后进行代码驱动编写时,需要认真阅读 DS18B20 的数据手册,这里放个中文版手册:

https://zhuanlan.zhihu.com/p/453052826

之后涉及到的手册里面的内容不再过多解释。现在解释几个重要的部分

  • 总线释放

当 STM32 主动控制数据线(DQ)时,称 STM32 控制着总线;而 STM32 释放总线时,则将总线的控制权交给了从机(DS18B20)

如何释放总线?

前面提到了开漏输出的特性,将开漏输出设置为高电平即为释放总线,因为高电平是由上拉电阻给的,并不是 STM32 本身,控制权已经不在 STM32 处。

  • LSB & MSB

DS18B20 的数据传输都是从低位传到高位。

2. 代码编写

2.1 微秒函数

在与 DS18B20 的通信过程中涉及到许多微秒级别的延时,这里嫖了一份代码,直接用就行

#define CPU_FREQUENCY_MHZ    72		// STM32时钟主频
void delay_us(__IO uint32_t delay)
{
    int last, curr, val;
    int temp;

    while (delay != 0)
    {
        temp = delay > 900 ? 900 : delay;
        last = SysTick->VAL;
        curr = last - CPU_FREQUENCY_MHZ * temp;
        if (curr >= 0)
        {
            do
            {
                val = SysTick->VAL;
            }
            while ((val < last) && (val >= curr));
        }
        else
        {
            curr += CPU_FREQUENCY_MHZ * 1000;
            do
            {
                val = SysTick->VAL;
            }
            while ((val <= last) || (val > curr));
        }
        delay -= temp;
    }
}

2.2 宏定义

#define GPIO_PORT GPIOC
#define GPIO_PIN  GPIO_PIN_0

#define DQ_OUT(x) HAL_GPIO_WritePin(GPIO_PORT,GPIO_PIN,x)
#define DQ_IN()	  HAL_GPIO_ReadPin(GPIO_PORT,GPIO_PIN)

前面已经介绍到,开漏输出也可以当作输出,也可以当作输入使用。

2.3 基本时序配置

在与 DS18B20 通信的过程中,主要涉及几个方面

  • 复位(又称初始化)
  • DS18B20 响应
  • 向 DS18B20 写入数据
  • 从 DS18B20 读取数据

这些过程在 datasheet 都以提及,阅读下面代码时请对照 datasheet

2.3.1 复位
void DS18B20_Rst(void)
{
	DQ_OUT(0);
	delay_us(750);
	DQ_OUT(1);		  //释放总线
	delay_us(15);
}
2.3.2 DS18B20响应
//返回0:响应成功
uint8_t DS18B20_Check(void)
{
	uint8_t temp=0;
	while(DQ_IN()&&temp<200)	//等待18B20拉低电平
	{
		temp++;
		delay_us(1);
	}
	if(temp>=200)		//如果超过200us电平还没被拉低,说明没检测到
		return 1;
	
	temp=0;
	while(!DQ_IN()&&temp<240)	//等待18B20拉低电平结束,电平重新为高
	{
		temp++;
		delay_us(1);
	}
	if(temp>=240)
		return 1;
	return 0;
	
}
2.3.3 向 DS18B20 写入数据
void DS18B20_Write_Byte(uint8_t data)
{
	uint8_t i=0;
	uint8_t bit=0;
	for(i=0;i<8;++i)
	{
		bit=data&0x01;
		data=data>>1;
		if(bit)			//写1
		{
			DQ_OUT(0);
			delay_us(2);
			DQ_OUT(1);
			delay_us(60);
		}
		else			//写0
		{
			DQ_OUT(0);
			delay_us(60);
			DQ_OUT(1);
			delay_us(2);
		}
	}
}

这里要说明一下为什么写 0 时最后需要拉高总线 2us,这是为了防止如果写入的数据一直是 0 时,超过 480 us 就会被当成复位信号从而把 DS18B20 复位了!

2.3.4 读取数据

读取数据比较复杂,需要先写好读取单个 bit 的函数,再读取一个 byte

//从18B20读取一个bit
uint8_t DS18B20_Read_Bit(void)
{
	uint8_t bit;
	DQ_OUT(0);
	delay_us(2);
	DQ_OUT(1);
	delay_us(12);
	bit=DQ_IN();
	delay_us(50);
	return bit;
}

//从18B20读取一个byte
uint8_t DS18B20_Read_Byte(void)
{
	uint8_t i=0,bit=0,data=0;
	for(i=0;i<8;++i)
	{
		bit=DS18B20_Read_Bit();
		data=(bit<<7)|(data>>1);
	}
	return data;
}

2.4 温度读取

前面的基础工作都已经做好,现在来实现温度的读取吧

配置 DS18B20 完成指定任务需要三个阶段

  • 初始化(复位)
  • ROM命令
  • DS18B20功能命令

三个步骤需要循环进行才能正常工作,每次只能执行一个 ROM 命令和功能指令

float DS18B20_Get_Temp(void)
{
	uint8_t temp;
	uint8_t TL,TH;
	short tem;
	DS18B20_Rst();	   
	DS18B20_Check();	 
  	DS18B20_Write_Byte(0xcc);	// skip rom
  	DS18B20_Write_Byte(0x44);	// 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;					//获得底八位
	float res=(float)tem*0.0625;		//转换     
	if(temp)return res; 		//返回温度值
	else return -res;    
}

标签:gt,训练,temp,DS18B20,us,delay,部分,DQ
From: https://www.cnblogs.com/SFWR-YOU/p/16885676.html

相关文章

  • 训练题——ADC读取温度
    利用ADC测量单片机内部温度WrittenbyXuanYu废话不多说,直接开搞。科普先科普一下ADC(不是ADcarry!),ADC是模数转化器,就是模拟信号转换成数字信号的东西,通常的模数转换......
  • 第四部分 判断推理第一章 图形推理(5到10题) 第四小节 数量规律
    数量关系是图形推理考查中最多哟的,变化最多的考点每年3到4题 图形特性组成袁术不同而且没有明显的属性规律当组成元素不同,经常考查属性关系,数量关系和奇特......
  • 计算机等级考试二级C语言程序设计专项训练题——多项式求值
        在计算机等级考试二级C语言程序设计试题中,多项式求值是一个重要的考点,有关多项式求值的试题在历年考试试卷的程序填空题和程序设计题中经常出现。一.示例讲解......
  • 代码随想录训练营第三十一天 | 贪心算法
    贪心算法的核心思想是在每一步决策中都找到局部最优解122.买卖股票的最佳时机classSolution{publicintmaxProfit(int[]prices){intn=prices.le......
  • 2022/11/07-13 训练小记
    2022/11/07-13训练小记P7961[NOIP2021]数列显然是一个\(dp\),首先考虑状态应如何设计。看到\(n\)的限制,首先可以想到记一维\(i\)表示当前已被确定的\(a\)序列......
  • 训练题——OLED部分
    训练题OLED部分实现目标通过IIC通信控制OLED屏幕显示出一串字符串名词介绍OLED屏:OLED(OrganicLight-EmittingDiode),又称为有机电激光显示、有机发光半导体(OrganicEle......
  • MX6U系统移植部分笔记
    后面的驱动开发很多需要这边的知识,所以还是要看一遍。u-boot初次编译启动(SD卡启动方式)首先需要安装ncurses库。sudoapt-getinstalllibncurses5-dev解压出厂源码后,需......
  • OOP下半部分-Java与生活
    目录​​面向对象三大特性:封装继承多态​​​​2-1-1需求重定义​​​​2-1-2继承​​​​2-2-2饿狼传说之多层继承​​​​2-2-3方法的重写​​​​2-2-4super啃老......
  • 11:高级部分-MySQL
    目录​​(一)view视图​​​​1.开场​​​​2.view视图创建、使用以及作用​​​​3.显示视图​​​​4.更新和删除视图​​​​5.视图算法:temptable,merge​​​​(......
  • 拓端数据tecdat|R语言代写线性混合效应模型Linear Mixed-Effects Models的部分折叠Gib
    本文介绍了线性混合效应模型的新型贝叶斯分析。该分析基于部分折叠的方法,该方法允许某些组件从模型中部分折叠。得到的部分折叠的Gibbs(PCG)采样器被构造成适合线性混合效应模......