当前位置: 首页 > article >正文

51单片机 - DS18B20实验1-读取温度

上来一张图,明确思路,程序整体裤架如下,通过单总线,单独封装一个.c文件用于单总线的操作,其实,我们可以把点c文件看成一个类操作,其属性就是我们面向对象的函数,也叫方法,操作起来方便,通过DS18B20调用封装好的单总线,实现温度的读取(用LCD1602显示出读取的温度  ),总后通过主函数调用这些模块,这就是模块化的编程,两个模块,主函数直接调用,也方便移植。

作者:Whappy

时间:2024.9.14

DS18B20实验-温度测试

第一步:模块化单总线 :OneWire.c

一共五个函数

看时序写代码

unsigned char OneWire_Init(void)
{
	unsigned char AckBit;
	
	OneWire_DQ = 1; //保证拉低之前是高电平
	OneWire_DQ = 0; //拉低
	Delay1ms();//延时1ms ,至少480us
	OneWire_DQ = 1;  //释放
	Delay70us();
	AckBit = OneWire_DQ; //应答位:存在的从机会拉低总线60~240us以响应主机
	Delay1ms();//延时1ms ,至少480us
	
	
	return AckBit;
	
}

void OneWire_SendBit(unsigned char Bit)
{
	OneWire_DQ = 0; //拉低
	Delay10us();
	OneWire_DQ = Bit; //10us 将数据放到总线上
	Delay50us();
	OneWire_DQ = 1;  //释放
}

//接收一位:即主机51读取一位:主机将总线拉低1~15us,然后释放总线,并在拉低后15us内读取总线电平(尽量贴近15us的末尾),
//读取为低电平则为接收0,读取为高电平则为接收1 ,整个时间片应大于60us
unsigned char OneWire_ReadBit(void)
{
	unsigned char Bit;
	OneWire_DQ = 0; //拉低
	Delay5us();
	OneWire_DQ = 1;  //释放
	Delay5us();
	Bit = OneWire_DQ;  //数据放到总线上,主机读
	Delay50us();
	
	return Bit;
		
}

//发送一个字节:连续调用8次发送一位的时序,依次发送一个字节的8位(低位在前)
void OneWire_SendByte(unsigned char Byte)
{
	unsigned char i;
	for(i=0; i<8; i++)
	{
		OneWire_SendBit(Byte & (0X01 << i));
	}
}

//接收一个字节:连续调用8次接收一位的时序,依次接收一个字节的8位(低位在前)

unsigned char OneWire_ReceiveByte(void)
{
	unsigned char i, Byte = 0X00;
	
	for(i=0; i<8; i++)
	{
		if(OneWire_ReadBit())
		{
			Byte |= (0x01);
		}
	}
	
	
	return Byte;
}

第二步:模块化 DS18B20.c:DS18B20.c  :两个函数


//温度转换函数 :初始化→跳过ROM →开始温度变换

void DS18B20_ConvertTemperature(void)
{
	OneWire_Init();
	OneWire_SendByte(SKIP_ROM); //跳过ROM,写入一个字节数据,说我要读取温度
	OneWire_SendByte(CONVERT_T); //发送一个字节,让DS18B20开始温度转化
	
}


//温度读取:初始化→跳过ROM →读暂存器→连续的读操作
float DS18B20_ReadTemperature(void)
{
	unsigned char TLSB, TMSB;
	int Temp;
	float T;
	OneWire_Init();//初始化
	OneWire_SendByte(READ_SCRATCHPAD); //跳过ROM,写入一个字节数据,说我要读取温度
	TLSB = OneWire_ReceiveByte();
	TMSB = OneWire_ReceiveByte();
	
	Temp = (TMSB<<8)| TLSB;
	
	T = Temp/16.0;
	return T;


}

第三步:主函数调用 :main.c

#include <REGX52.H>
#include "LCD1602.h"
#include "DS18B20.h"
#include "Delay.h"


float T;

void main(void)
{
	DS18B20_ConvertTemperature();	//上电先转换一次温度,防止第一次读数据错误
	Delay_Any(1000);			//等待转换完成
	//初始化
	LCD_Init();

	
	
	LCD_ShowString(1,1,"Temperature:");
	
	
	while(1)
	{	
		DS18B20_ConvertTemperature();
		T = DS18B20_ReadTemperature();
		if(T < 0)
		{
			LCD_ShowChar(2,1,'-');
			T = -T;
		}
		else
			LCD_ShowChar(2,1,'+');
		
		LCD_ShowNum(2,2,T,3);
		LCD_ShowChar(2,5,'.');
		LCD_ShowNum(2,6,(unsigned long)(T*10000)%10000,4);
	}
}






//#include <REGX52.H>
//#include "LCD1602.h"
//#include "DS18B20.h"
//#include "Delay.h"

//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);//显示温度小数部分
//	}
//}






总代码:

OneWire.c

#include <REGX52.H>
#include "Delay.h"


sbit OneWire_DQ = P3^7; //单总线的管脚定义

//编写5个函数 初始化、写一位、读一位、写一个字节、读一个字节



//初始化:主机将总线拉低至少480us,然后释放总线,等待15~60us后,存在的从机会拉低总线60~240us以响应主机,之后从机将释放总线

unsigned char OneWire_Init(void)
{
	unsigned char AckBit;
	
	OneWire_DQ = 1; //保证拉低之前是高电平
	OneWire_DQ = 0; //拉低
	Delay1ms();//延时1ms ,至少480us
	OneWire_DQ = 1;  //释放
	Delay70us();
	AckBit = OneWire_DQ; //应答位:存在的从机会拉低总线60~240us以响应主机
	Delay1ms();//延时1ms ,至少480us
	
	
	return AckBit;
	
}


//写一位数据,即主机51发送一位:主机将总线拉低60~120us,然后释放总线,表示发送0;主机将总线拉低1~15us,
//然后释放总线,表示发送1。从机将在总线拉低30us后(典型值)读取电平,整个时间片应大于60us

void OneWire_SendBit(unsigned char Bit)
{
	OneWire_DQ = 0; //拉低
	Delay10us();
	OneWire_DQ = Bit; //10us 将数据放到总线上,主机写,
	Delay50us();
	OneWire_DQ = 1;  //释放
}


//接收一位:即主机51读取一位:主机将总线拉低1~15us,然后释放总线,并在拉低后15us内读取总线电平(尽量贴近15us的末尾),
//读取为低电平则为接收0,读取为高电平则为接收1 ,整个时间片应大于60us
unsigned char OneWire_ReadBit(void)
{
	unsigned char Bit;
	OneWire_DQ = 0; //拉低
	Delay5us();
	OneWire_DQ = 1;  //释放
	Delay5us();
	Bit = OneWire_DQ;  //数据放到总线上,主机读
	Delay50us();
	
	return Bit;
		
}

//发送一个字节:连续调用8次发送一位的时序,依次发送一个字节的8位(低位在前)
void OneWire_SendByte(unsigned char Byte)
{
	unsigned char i;
	for(i=0; i<8; i++)
	{
		OneWire_SendBit(Byte & (0X01 << i));
	}
}

//接收一个字节:连续调用8次接收一位的时序,依次接收一个字节的8位(低位在前)

unsigned char OneWire_ReceiveByte(void)
{
	unsigned char i, Byte = 0X00;
	
	for(i=0; i<8; i++)
	{
		if(OneWire_ReadBit())
		{
			Byte |= (0x01);
		}
	}
	
	
	return Byte;
}

















DS18B20.c

#include <REGX52.H>
#include "OneWire.h"

//DS18B20 程序使用的寄存器进行红宏定义
#define SKIP_ROM			0XCC	//ROM指令 跳过ROM ,相当于直接访问DS18B20
#define CONVERT_T			0X44   //功能指令 温度转换
#define READ_SCRATCHPAD		0XBE  //功能指令  暂存器


//温度转换函数 :初始化→跳过ROM →开始温度变换

void DS18B20_ConvertTemperature(void)
{
	OneWire_Init();
	OneWire_SendByte(SKIP_ROM); //跳过ROM,写入一个字节数据,说我要读取温度
	OneWire_SendByte(CONVERT_T); //发送一个字节,让DS18B20开始温度转化
	
}


//温度读取:初始化→跳过ROM →读暂存器→连续的读操作
float DS18B20_ReadTemperature(void)
{
	unsigned char TLSB, TMSB;
	int Temp;
	float T;
	OneWire_Init();//初始化
	OneWire_SendByte(SKIP_ROM);
	OneWire_SendByte(READ_SCRATCHPAD); //跳过ROM,写入一个字节数据,说我要读取温度
	TLSB = OneWire_ReceiveByte();
	TMSB = OneWire_ReceiveByte();
	
	Temp = (TMSB<<8) | TLSB;
	
	T = Temp/16.0;
	return T;


}

Delay.c

#include <REGX52.H>
#include "intrins.h"



void Delay1ms()		//@11.0592MHz
{
	unsigned char i, j;

	_nop_();
	i = 2;
	j = 199;
	do
	{
		while (--j);
	} while (--i);
}





void Delay70us()		//@11.0592MHz
{
	unsigned char i;

	_nop_();
	i = 29;
	while (--i);
}


void Delay_Any(unsigned int xms)		//@11.0592MHz
{
	unsigned char i, j;
	
	while(xms--)
	{
		_nop_();
		i = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--i);
	}
}


void Delay10us()		//@11.0592MHz
{
	unsigned char i;

	i = 2;
	while (--i);
}


void Delay50us()		//@11.0592MHz
{
	unsigned char i;

	_nop_();
	i = 20;
	while (--i);
}


void Delay5us()		//@11.0592MHz
{
}








其余代码可参考(主页51单片机内容)


http://www.kler.cn/news/309217.html

相关文章:

  • 硬件工程师笔试面试——变压器
  • 二.Oracle每周运维操作
  • 在Android中如何进行多渠道打包
  • Linux基础---07文件传输及解决yum安装失效的方法
  • 【Linux】探索文件I/O奥秘,解锁软硬链接与生成动静态库知识
  • 编译成功!QT/6.7.2/Creator编译Windows64 MySQL驱动(MinGW版)
  • 剧本杀小程序开发,探索互联网剧本杀游戏体验
  • 【C++】虚函数
  • 多速率信号处理-CIC滤波器
  • Go第三方框架--gin框架(三)
  • SpringBoot 消息队列RabbitMQ死信交换机
  • 2025年最新大数据毕业设计选题-基于Spark分析相关
  • NC反弹shell
  • 微服务中间件之Nacos
  • Android 系统开发人员的权限说明文档
  • 解锁全球机遇:澳大利亚服务器租用市场的独特魅力
  • [C#学习笔记]Newtonsoft.Json
  • 中秋节特别游戏:给玉兔投喂月饼
  • MinIO - macOS上配置、Python调用
  • Delphi Web和Web服务开发目前有哪些选择
  • ASP.NET Core 中的 CRUD 操作
  • 游戏录屏不清楚怎么办?这些录屏技巧让画质飙升!
  • 标准的高防服务器是什么样的呢?
  • VSCode扩展连接虚拟机MySQL数据库
  • 【JavaScript】数据结构之堆
  • Python 数学建模——ARMA 时间序列分析
  • Unite Shanghai 2024 技术专场 | Unity 6及未来规划:Unity引擎和服务路线图
  • docker_持久化存储
  • 如何在Linux云服务器上解决网站截图问题
  • 【PyQt5】QWidget子类所有子类