(学习日记)2023.04.24

13 篇文章 0 订阅
文章详细介绍了DS18B20数字温度传感器的工作原理,包括单总线通信协议、ROM指令和功能指令的使用。同时,提供了51单片机与DS18B20交互的初始化、发送和接收函数,以及读取温度的实现方法。文章还包含了一个简单的主函数示例,展示如何实时显示温度数据。
摘要由CSDN通过智能技术生成

写在前面:
由于时间的不足与学习的碎片化,写博客变得有些奢侈。
但是对于记录学习(忘了以后能快速复习)的渴望一天天变得强烈。
既然如此
不如以天为单位,以时间为顺序,仅仅将博客当做一个知识学习的目录,记录笔者认为最通俗、最有帮助的资料,并尽量总结几句话指明本质,以便于日后搜索起来更加容易。


标题的结构如下:“类型”:“知识点”——“简短的解释”
部分内容由于保密协议无法上传。


点击此处进入学习日记的总目录

一、元件:DS18B20——数字温度传感器(单总线)

  1. DS18B20介绍
    在这里插入图片描述

  2. 引脚及应用电路
    在这里插入图片描述

  3. 内部结构框图
    在这里插入图片描述

  4. 存储器结构
    在这里插入图片描述

  5. 单总线介绍
    在这里插入图片描述

  6. 单总线电路规范
    在这里插入图片描述

  7. 单总线时序结构
    在这里插入图片描述
    主机先拉低再拉高,从机接着拉低再拉高,代表初始化。
    在这里插入图片描述
    主机先拉低,如果一直拉低,代表发送0;如果立即抬起来,代表发送1
    从机将会在主机拉低后30us后读取电平
    在这里插入图片描述
    主机在发送时会先拉低15us,在这15us中从机保持低或拉高,主机在15us末尾读取电平
    在这里插入图片描述
    低位在前

  8. DS18B20操作流程
    在这里插入图片描述

ROM指令(ROM Commands):

  • 搜索ROM(Search ROM):该指令用于搜索总线上连接的所有DS18B20设备的唯一ROM代码。通过发送搜索设备指令,可以获取总线上所有DS18B20设备的地址,以便后续与特定设备进行通信。
  • 读取ROM(Read ROM):该指令用于从DS18B20传感器中读取设备的唯一ROM代码。通过发送读取ROM指令,可以获取特定DS18B20设备的地址。
  • 匹配ROM(Match ROM):使用该指令可以将总线上的通信限定为特定的DS18B20设备。发送匹配ROM指令后,只有匹配的设备会对后续的指令做出响应。
  • 跳过ROM(Skip ROM):使用该指令可以忽略总线上所有设备的地址,直接与总线上唯一一个DS18B20设备进行通信。适用于只连接一个DS18B20设备的情况。
  • 使能温度报警搜索(Alarm Search):该指令用于在总线上启动温度报警搜索过程。可以通过发送该指令,识别温度超过设定阈值的DS18B20设备。

功能指令(Function Commands):

  • 读取温度(Convert T):该指令用于启动温度转换过程。在执行该指令后,DS18B20开始测量温度,并将结果存储在内部寄存器中。
  • 写入温度设定值(Write Scratchpad):该指令用于将温度设定值写入DS18B20传感器的内部寄存器。可以使用该指令设置温度报警阈值等参数。
  • 读取温度设定值(Read Scratchpad):该指令用于从DS18B20传感器的内部寄存器中读取温度设定值和其他配置参数。
  • 复制温度设定值(Copy Scratchpad):该指令用于将写入的温度设定值从内部寄存器复制到DS18B20的EEPROM中。通过执行该指令,可以确保温度设定值在掉电后仍然有效。
  • 读取电源供应(Read Power Supply):该指令用于读取DS18B20传感器的电源供应状态,以确定传感器是否正常供电。
  • 写入温度报警阈值(Set Alarm Temp):使用该指令可以将温度报警的上限和下限阈值写入DS18B20的报警寄存器,以便在温度超出设定范围时触发报警。
  1. DS18B20数据帧
    在这里插入图片描述
  2. 温度存储格式
    在这里插入图片描述

二、51:DS18B20温度传感器

1. 单总线函数

  1. 寻找引脚,很明显引脚是P37
    在这里插入图片描述
  2. 编写单总线初始化函数
/**
  * @brief  单总线初始化
  * @param  无
  * @retval 从机响应位,0为响应,1为未响应
  */
unsigned char OneWire_Init(void)
{
	unsigned char i;
	unsigned char AckBit;
	OneWire_DQ=1;
	OneWire_DQ=0;
	i = 247;while (--i);		//Delay 500us
	OneWire_DQ=1;
	i = 32;while (--i);			//Delay 70us
	AckBit=OneWire_DQ;
	i = 247;while (--i);		//Delay 500us
	return AckBit;
}
  • 首先,定义了一个无符号字符型变量 i 和 AckBit。i 用于计数,AckBit 用于存储从机的响应位。
  • 设置单总线引脚 OneWire_DQ 为高电平(逻辑1)。
  • 将单总线引脚 OneWire_DQ 设置为低电平(逻辑0),这个动作用于发出初始化信号。
  • 使用一个循环延时大约 500 微秒,具体延时的时间取决于循环的执行次数。这个延时是为了等待总线上的设备完成初始化过程。
  • 将单总线引脚 OneWire_DQ 设置为高电平,释放总线。
  • 使用一个循环延时大约 70 微秒,等待从机设备的响应。
  • 将从机设备的响应位读取到 AckBit 变量中。
  • 再次使用一个循环延时大约 500 微秒,确保总线上的设备完成响应过程。
  • 返回 AckBit 变量,表示从机的响应状态。如果 AckBit 的值为 0,则表示从机有响应;如果 AckBit 的值为 1,则表示从机无响应。

这个函数的目的是初始化单总线,并检测从机设备是否有响应。根据返回值可以判断单总线上是否存在有效的从机设备。

这里的延时都是软件生成出来的
在这里插入图片描述
由于程序中不需要进入函数,而进入函数需要4us,所以图片中延时54us

  1. 编写单总线发送一位函数
/**
  * @brief  单总线发送一位
  * @param  Bit 要发送的位
  * @retval 无
  */
void OneWire_SendBit(unsigned char Bit)
{
	unsigned char i;
	OneWire_DQ=0;
	i = 4;while (--i);			//Delay 10us
	OneWire_DQ=Bit;
	i = 24;while (--i);			//Delay 50us
	OneWire_DQ=1;
}
  • 首先,定义了一个无符号字符型变量 i。
  • 将单总线引脚 OneWire_DQ 设置为低电平(逻辑0),用于开始发送数据。
  • 使用一个循环延时大约 10 微秒,具体延时的时间取决于循环的执行次数。这个延时是为了保持数据在总线上的稳定时间。
  • 将要发送的位数据 Bit 设置到单总线引脚 OneWire_DQ 上。
  • 使用一个循环延时大约 50 微秒,具体延时的时间取决于循环的执行次数。这个延时是为了保持数据在总线上的稳定时间。
  • 将单总线引脚 OneWire_DQ 设置为高电平(逻辑1),表示数据发送完毕。

该函数用于将一位数据发送到单总线上,具体发送的是逻辑0还是逻辑1由参数 Bit 决定。注意,在发送完数据后,需要等待一段时间以确保数据在总线上被接收。

  1. 编写单总线接收一位函数
/**
  * @brief  单总线接收一位
  * @param  无
  * @retval 读取的位
  */
unsigned char OneWire_ReceiveBit(void)
{
	unsigned char i;
	unsigned char Bit;
	OneWire_DQ=0;
	i = 2;while (--i);			//Delay 5us
	OneWire_DQ=1;
	i = 2;while (--i);			//Delay 5us
	Bit=OneWire_DQ;
	i = 24;while (--i);			//Delay 50us
	return Bit;
}
  • 首先,定义了一个无符号字符型变量 i 和 Bit。i 用于计数,Bit 用于存储接收到的位数据。
  • 将单总线引脚 OneWire_DQ 设置为低电平(逻辑0),用于准备接收数据。
  • 使用一个循环延时大约 5 微秒,具体延时的时间取决于循环的执行次数。这个延时是为了等待数据的稳定时间。
  • 将单总线引脚 OneWire_DQ 设置为高电平(逻辑1),表示准备接收数据。
  • 使用一个循环延时大约 5 微秒,具体延时的时间取决于循环的执行次数。这个延时是为了保持数据在总线上的稳定时间。
  • 将从单总线引脚 OneWire_DQ 上读取的位数据存储到变量 Bit 中。
  • 使用一个循环延时大约 50 微秒,具体延时的时间取决于循环的执行次数。这个延时是为了保持数据在总线上的稳定时间。
  • 返回变量 Bit,表示接收到的位数据。

该函数用于从单总线上接收一位数据,它通过读取单总线引脚上的电平状态来获取数据。在接收完数据后,需要等待一段时间以确保数据在总线上稳定并被正确读取。

  1. 编写单总线发送一个字节
/**
  * @brief  单总线发送一个字节
  * @param  Byte 要发送的字节
  * @retval 无
  */
void OneWire_SendByte(unsigned char Byte)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		OneWire_SendBit(Byte&(0x01<<i));
	}
}

这是一个用于在单总线上发送一个字节数据的函数。下面是对该函数的解释:

  1. 首先,定义了一个无符号字符型变量 i,用于循环计数。

  2. 使用一个循环,循环次数为 8,表示一个字节有 8 位。

  3. 在每次循环中,通过位运算和逻辑与操作,从要发送的字节 Byte 中取出当前位(最低位开始),并将其作为参数传递给函数 OneWire_SendBit() 来发送该位数据。

  4. 循环结束后,表示所有的 8 位数据都已发送完成。

该函数用于将一个字节的数据按位发送到单总线上。它会遍历字节的每一位,从最低位开始发送。在发送每一位数据时,会调用函数 OneWire_SendBit() 来实现单个位的发送。

  1. 编写单总线接收一个字节

/**
  * @brief  单总线接收一个字节
  * @param  无
  * @retval 接收的一个字节
  */
unsigned char OneWire_ReceiveByte(void)
{
	unsigned char i;
	unsigned char Byte=0x00;
	for(i=0;i<8;i++)
	{
		if(OneWire_ReceiveBit()){Byte|=(0x01<<i);}
	}
	return Byte;
}
  • 首先,定义了一个无符号字符型变量 i 和 Byte。i 用于循环计数,Byte 用于存储接收到的字节数据,初始值为 0x00。
  • 使用一个循环,循环次数为 8,表示一个字节有 8 位。
  • 在每次循环中,通过调用函数 OneWire_ReceiveBit() 接收单总线上的一位数据。如果返回值为真(非零),表示接收到的位数据为逻辑1,将该位设置到字节变量 Byte 中,使用位运算和逻辑或操作。
  • 循环结束后,表示所有的 8 位数据都已接收完成。
  • 返回变量 Byte,表示接收到的一个字节数据。

该函数用于从单总线上按位接收一个字节的数据。它会遍历字节的每一位,从最低位开始接收。在接收每一位数据时,会调用函数 OneWire_ReceiveBit() 来实现单个位的接收,并根据接收到的位数据将其设置到字节变量 Byte 中。

2. DS18B20函数

  1. 首先,找到需要使用的指令,宏定义为较为易懂的单词
//DS18B20指令
#define DS18B20_SKIP_ROM			0xCC
#define DS18B20_CONVERT_T			0x44
#define DS18B20_READ_SCRATCHPAD 	0xBE
  1. 编写开始 DS18B20 温度转换的函数
/**
  * @brief  DS18B20开始温度变换
  * @param  无
  * @retval 无
  */
void DS18B20_ConvertT(void)
{
	OneWire_Init();
	OneWire_SendByte(DS18B20_SKIP_ROM);
	OneWire_SendByte(DS18B20_CONVERT_T);
}
  • 首先,调用函数 OneWire_Init() 进行单总线初始化,确保单总线准备就绪。
  • 调用函数 OneWire_SendByte() 发送命令字节 DS18B20_SKIP_ROM。这个命令字节用于跳过对 DS18B20 的 ROM 码操作,直接对所有 DS18B20 进行温度转换。
  • 调用函数 OneWire_SendByte() 发送命令字节 DS18B20_CONVERT_T。这个命令字节用于启动 DS18B20 的温度转换过程。

该函数的目的是通过单总线与 DS18B20 通信,发送相应的命令字节来开始温度转换过程。在函数执行完毕后,DS18B20 将会开始进行温度转换。

  1. 编写读取 DS18B20 温度的函数
/**
  * @brief  DS18B20读取温度(此处用补码判断判断温度正负)
  * @param  无
  * @retval 温度数值
  */
float DS18B20_ReadT(void)
{
	unsigned char TLSB,TMSB;
	int Temp;
	float T;
	OneWire_Init();
	OneWire_SendByte(DS18B20_SKIP_ROM);
	OneWire_SendByte(DS18B20_READ_SCRATCHPAD);
	TLSB=OneWire_ReceiveByte();
	TMSB=OneWire_ReceiveByte();
	Temp=(TMSB<<8)|TLSB;
	T=Temp/16.0;
	return T;
}

  • 首先,定义了无符号字符型变量 TLSB 和 TMSB 用于存储温度的低位字节和高位字节,定义了整型变量 Temp 用于存储合并后的温度值,定义了浮点型变量 T 用于存储最终的温度数值。
  • 调用函数 OneWire_Init() 进行单总线初始化,确保单总线准备就绪。
  • 调用函数 OneWire_SendByte() 发送命令字节 DS18B20_SKIP_ROM,用于跳过对 DS18B20 的 ROM 码操作(因为只有一个从机)。
  • 调用函数 OneWire_SendByte() 发送命令字节 DS18B20_READ_SCRATCHPAD,用于读取 DS18B20 的温度数据。
  • 调用函数 OneWire_ReceiveByte() 两次分别接收温度的低位字节和高位字节,并将其分别存储到变量 TLSB 和 TMSB 中。
  • 将高位字节 TMSB 左移 8 位,并与低位字节 TLSB 进行按位或操作,得到合并后的温度值 Temp。
  • 将温度值 Temp 除以 16.0(等同于右移四位,因为右四位是小数),得到最终的温度数值 T。
  • 返回温度数值 T。

该函数的目的是通过单总线与 DS18B20 通信,发送相应的命令字节来读取 DS18B20 的温度数据,并将其转换为浮点型的温度数值。函数执行过程中,首先进行单总线初始化,然后发送命令字节读取温度数据,并将接收到的字节数据进行合并和转换,最后返回转换后的温度数值。

3. main函数

float T;

void main()
{
	DS18B20_ConvertT();		//上电先转换一次温度,防止第一次读数据错误
	Delay(1000);			//等待转换完成
	LCD_Init();
	LCD_ShowString(1,1,"Temperature:");
	while(1)
	{
		DS18B20_ConvertT();	//转换温度
		T=DS18B20_ReadT();	//读取温度
		if(T<0)				//如果温度小于0
		{
			LCD_ShowChar(2,1,'-');	//显示负号
			T=-T;			//将温度变为正数
		}
		else				//如果温度大于等于0
		{
			LCD_ShowChar(2,1,'+');	//显示正号
		}
		LCD_ShowNum(2,2,T,3);		//显示温度整数部分
		LCD_ShowChar(2,5,'.');		//显示小数点
		LCD_ShowNum(2,6,(unsigned long)(T*10000)%10000,4);//显示温度小数部分
	}
}
  1. 首先,定义了一个浮点型变量 T 用于存储温度值。

  2. main() 函数中,首先调用函数 DS18B20_ConvertT() 进行一次温度转换,这是为了防止第一次读取数据时出现错误。

  3. 然后,通过调用延时函数 Delay() 来等待转换完成,延时时间为 1000 毫秒。

  4. 初始化 LCD 屏幕,通过调用函数 LCD_Init() 实现。

  5. 在 LCD 屏幕上显示字符串 “Temperature:”,通过调用函数 LCD_ShowString() 来实现。

  6. 进入一个无限循环,在循环中进行温度的读取和显示操作。

  7. 在循环中,首先调用函数 DS18B20_ConvertT() 来进行温度转换。

  8. 然后,通过调用函数 DS18B20_ReadT() 来读取温度值,并将其存储到变量 T 中。

  9. 判断温度是否小于 0,如果是,则显示负号,并将温度 T 取负值。

  10. 如果温度大于等于 0,则显示正号。

  11. 使用函数 LCD_ShowNum() 将温度的整数部分显示在 LCD 屏幕上。

  12. 在小数点位置显示小数点符号。

  13. 使用函数 LCD_ShowNum() 将温度的小数部分显示在 LCD 屏幕上。

  14. 无限循环会持续进行温度的读取和显示,实现实时的温度监测。

该主程序的功能是通过 DS18B20 温度传感器读取温度数据,并使用 LCD 屏幕进行显示。在程序开始时,先进行一次温度转换,然后进入循环,循环中不断进行温度转换和读取,并将温度值显示在 LCD 屏幕上。同时,根据温度值的正负显示相应的符号。循环会持续执行,实现实时的温度监测和显示。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YunB西风英

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值