ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

STC89C52单片机单线通信(DS18B20温度)

2022-02-04 15:30:27  阅读:264  来源: 互联网

标签:Delay OneWire DS18B20 STC89C52 unsigned char 单片机 LCD


目录

DS18B20介绍

DS18B20温度传感器结构图:

 DS18B20温度传感器操作配置:

单总线介绍

单总线规范

单总线时序结构

初始化:

发送一位:(主机到从机)

接收一位:(从机到主机)

发送一个字节:

接收一个字节:

代码示例:

单线通信函数:


DS18B20介绍

DS18B20是一种常见的数字温度传感器,其控制命令和数据都是以数字信号的方式输入输出,相比较于模拟温度传感器,具有功能强大、硬件简单、易扩展、抗干扰性强等特点

测温范围:-55°C 到 +125°C

通信接口:1-Wire(单总线)

其它特征:可形成总线结构、内置温度报警功能、可寄生供电

DS18B20温度传感器结构图:

 DS18B20温度传感器操作配置:

在DS18B20温度传感器进行初始化操作的时候,由于我们这里单线通信的只有DS18B20这一个设备,所以ROM就不需要进行匹配,而且要将DS18B20温度传感器收集到的模拟信号转化为温度值

所以开始进行的是SKIP ROM(0xCC)与CONVERT T(0x44)的操作 

 这里在进行转换的时候有一定的时间限制,也就是说不是一转换就可以进行读数的,这里就一最大的750ms为标准,建议Delay(1000ms)

最后就是读取温度,利用读取温度的操作:READ SCRATCHPAD(0xBE)

在这里LS BYTE(TMSB)表示低位而MS BYTE(TLSB)表示低位,Temp=(TMSB<<8)|TLSB

这里需要将小数部分的4位向右移,得到实际温度的浮点数,左移一位x2,右移一位/2。T=Temp/16.0

单总线介绍

单总线(1-Wire BUS)是由Dallas公司开发的一种通用数据总线

一根通信线:DQ

异步、半双工

单总线只需要一根通信线即可实现数据的双向传输,当采用寄生供电时,还可以省去设备的VDD线路,此时,供电加通信只需要DQ和GND两根线

寄生供电就相当于数据线一样,就是DQ在传输数据的时候同时也用DQ来进行供电,以此节约端口

单总线规范

单总线时序结构

初始化:

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

发送一位:(主机到从机)

主机将总线拉低60~120us,然后释放总线,表示发送0;(这里确认上限是120us是为了避免时间过长,表示成初始化)

主机将总线拉低1~15us,然后释放总线,表示发送1;

从机将在总线拉低30us后(典型值)读取电平,整个时间片应大于60us 

(在设计的时候可以在0us时刻的时候置初值0,10us时刻进行赋值,后延时50us。这样刚刚好是在最后延时50us这段时间里面读取的电平)

接收一位:(从机到主机)

主机将总线拉低1~15us,然后释放总线,并在拉低后15us内读取总线电平(尽量贴近15us的末尾),读取为低电平则为接收0,读取为高电平则为接收1 ,整个时间片应大于60us

(在设计的时候可以在0us时刻先置为0,然后在5us时刻置1,延时5us看从机是否拉低总线,然后读取的电平,最后延时50us结束),这里在第一个5us的时候将总线拉高置1,是为了让效果跟明显,图示中置的是0也是可以的

发送一个字节:

连续调用8次发送一位的时序,依次发送一个字节的8位(低位在前)

一般是用8次循环的“ & ”运算,依次将数据赋给DQ

接收一个字节:

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

一般是用8次循环的“ | ”运算,依次将数据读给中间变量

 代码示例:

main函数:

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

float T;
extern unsigned char TLSB,TMSB;
void main()
{
	DS18B20_ConvertT();		//上电先转换一次温度,防止第一次读数为默认值,而出现闪屏现象
	Delay(1000);			//等待转换完成
	LCD_Init();
	LCD_ShowString(1,1,"BIN:");
	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);//(T*10000)显示温度的整数与小数部分超过65536,所以定义为unsigned long
    LCD_ShowBinNum(1,5,TMSB,4);                       //%10000求的是最后4位
    LCD_ShowBinNum(1,9,TLSB,8);
	}
			
}

单线通信函数:

#include <REGX52.H>

//引脚定义
sbit OneWire_DQ=P3^7;

/**
  * @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调用函数还需要时间us比较小,所以调用函数的话误差比较大
	OneWire_DQ=1;
	i = 32;while (--i);//Delay 70us
	AckBit=OneWire_DQ;
	i = 247;while (--i);//Delay 500us将时序走完
	return AckBit;//应答位
}

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从机在30us时读取电平
	OneWire_DQ=1;
}

unsigned char OneWire_ReceiveBit(void)
{
	unsigned char i;
	unsigned char Bit;
	OneWire_DQ=0;
	i = 2;while (--i);			//延时5us后释放
	OneWire_DQ=1;
	i = 2;while (--i);			//Delay 5us等待总线变化
	Bit=OneWire_DQ;
	i = 24;while (--i);			//Delay 50us确保总时间>60us
	return Bit;
}

void OneWire_SendByte(unsigned char Byte)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		OneWire_SendBit(Byte&(0x01<<i));
	}
}

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;
}

DS18B20温度传感器函数:

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

//DS18B20指令
#define DS18B20_SKIP_ROM			0xCC
#define DS18B20_CONVERT_T			0x44
#define DS18B20_READ_SCRATCHPAD 	0xBE


void DS18B20_ConvertT(void)
{
	OneWire_Init();
	OneWire_SendByte(DS18B20_SKIP_ROM);
	OneWire_SendByte(DS18B20_CONVERT_T);
}

unsigned char TLSB,TMSB;
float DS18B20_ReadT(void)
{
	//unsigned char虽然是无符号的,但是负数储存的时候是以补码的形式储存的,所以将它赋给一个有符号的数字,符号还是会显示的
	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;//将小数部分的4位向右移,得到实际温度,左移一位x2,右移一位/2
	return T;
}

LCD1602函数: 

#include <REGX52.H>

//引脚配置:
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0

void LCD_Delay()
{
	unsigned char i, j;

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

void LCD_WriteCommand(unsigned char Command)
{
	LCD_RS=0;
	LCD_RW=0;
	LCD_DataPort=Command;
	LCD_EN=1;
	LCD_Delay();
	LCD_EN=0;
	LCD_Delay();
}

void LCD_WriteData(unsigned char Data)
{
	LCD_RS=1;
	LCD_RW=0;
	LCD_DataPort=Data;
	LCD_EN=1;
	LCD_Delay();
	LCD_EN=0;
	LCD_Delay();
}

void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
	if(Line==1)
	{
		LCD_WriteCommand(0x80|(Column-1));
	}
	else if(Line==2)
	{
		LCD_WriteCommand(0x80|(Column-1+0x40));
	}
}

void LCD_Init()
{
	LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
	LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
	LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
	LCD_WriteCommand(0x01);//光标复位,清屏
}

void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{
	LCD_SetCursor(Line,Column);
	LCD_WriteData(Char);
}

void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=0;String[i]!='\0';i++)
	{
		LCD_WriteData(String[i]);
	}
}

int LCD_Pow(int X,int Y)
{
	unsigned char i;
	int Result=1;
	for(i=0;i<Y;i++)
	{
		Result*=X;
	}
	return Result;
}

void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
	}
}

Delay函数:

void Delay(unsigned int xms)
{
	unsigned char i, j;
	while(xms--)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
}

标签:Delay,OneWire,DS18B20,STC89C52,unsigned,char,单片机,LCD
来源: https://blog.csdn.net/qq_60521516/article/details/122782914

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有