C51 - 单总线时序分析 基于DS18B20

本文详细介绍了1-Wire通信协议,包括其单总线特性、传输速率以及在DS18B20温度传感器中的应用。通过解析DS18B20的ROM码、初始化时序、写读时序,展示了如何进行单总线的基本操作。此外,还讨论了DS18B20的主要性能和指令,以及其实现温度转换和读取的步骤。示例代码展示了如何启动和读取DS18B20的数据。
摘要由CSDN通过智能技术生成

一.概述

采用单根信号线,既传递时钟又传输数据,而且数据传输是双向的。
1-Wire适用于单个主机,能够控制一个或多个从机设备。

1.单总线的ROM码

每个单总线的ROM 中的 64 位序列号是出厂前被光刻好的,以表示其ID号。
地址序列号。64 位光刻 ROM 的排列是:开始 8 位(28H)是产品类型标号,接着的 48 位是唯一的序列号,最后 8 位是前面 56 位的循环冗余校
验码(CRC)。
在这里插入图片描述

2.传输速率

通常为16.3kb/s
超速时142kb/s
速度要求不高的场合

3.以DS18B20为例

在这里插入图片描述

二.单总线基本操作

在这里插入图片描述

(1)初始化时序图

在这里插入图片描述

总线控制器低电平:主机发出
DS1820:从机发出l

单总线上的所有通信都是以初始化序列开始。(由于上拉电阻,总线上为高电平
主机输出低电平,保持低电平时间至少 480us(该时间的时间范围可以从 480 到 960us),以产生复位脉冲。
接着主机释放总线,外部的上拉电阻将单总线拉高,延时 15~60 us,并进入接收模式。
接着 DS18B20 拉低总线 60~240 us,以产生低电平应答脉冲,
若为低电平,还要做延时,其延时的时间从外部上拉电阻将单总线拉高算起最少要 480us。

/*******************************************************************************
Function:  Driver_1WireRst
Description: DS18B20 初始化时序
Input:  无
Output: 无
Return: 无
*******************************************************************************/
bit Driver_1WireRst()
{
    bit ack;
	  DS18B20 = 0;                //拉低总线,总机发送复位脉冲。480us - 960us,这里取600us
	  Delay600us();
	  DS18B20 = 1;                //主机释放总线,外部的上拉电阻将单总线拉高,15 -60 us
	  Delay60us();
	  ack = DS18B20;              //读取DS18B20的ack
	  while(!DS18B20);            //等待脉冲结束,DS18B20释放的是低电平。
	  return ack;
}
(3)写时序

在这里插入图片描述

写时序包括写 0 时序和写 1 时序。所有写时序至少需要 60us,且在 2 次独立的写时序之间至少需要 1us 的恢复时间, 最长没限制。
写 0时序:主机拉低总线(单片机将引脚拉低),持续时间60us-120us。单片机拉低15us后,DS18B20会从15us-60us之间读取这一位数据。(最早在15us读取,典型值在30us读取,最多60us),这里延时超过60us即可。
写 1 时序:主机输出低电平,拉低时间至少1us,马上释放总线(即拉高引脚),延时 60us,然后释放总线,DS18B20会从15us-60us之间读取这个1。

nop(); //库函数_NOP_指令,一个机器周期就是一个us

/*******************************************************************************
Function: Driver_1Wire_Write
Description: DS18B20 写操作
Output: unsigned char date:写一字节
Return: 无
*******************************************************************************/
void Driver_1Wire_Write(unsigned char date)
{
    EA = 0;
    unsigned char tmp;
	  for (temp = 0x01; temp != 0;temp <<= 1)   //第一位与第一位与操作,循环第二位与第二位与操作。
	  {
          DS18B20 = 0;                          //首先拉低到低电平
	      _nop_();                              //库函数_NOP_指令,一个机器周期就是一个us
	      _nop_();                              //先拉低两个us,当作写1操作。
	      if((date & temp) == 0)                // 0x01和date 与操作(全1为1),如果还为0,说明输入的这一位是0
		  {
		      DS18B20 = 0;                      //拉低到低电平,说明是写0的时序
		  }
		 else
		 { 
              DS18B20 = 1;                     //置位高电平,说明是写1的时序	
		 }
    Delay60us();
    DS18B20 = 1;
    EA =1; 
}  

if((date & temp) == 0) ,temp:0x01(0000 0001)&date(0000 0000) ==0000 0000
temp:0x01(0000 0001)&date(0000 0001) ==0000 0001

(3)读时序

在这里插入图片描述

单总线器件仅在主机发出读时序时,才向主机传输数据,所以,在主机发出读数据命令后,必须马上产生读时序,以便从机能够传输数据。
所有读时序至少需要 60us,且在 2 次独立的读时序之间至少需要 1us 的恢复时间。
每个读时序都由单片机发起,单片机首先拉低这个引脚(至少拉低总线 )1us。主机在读时序期间必须释放总线,并从拉低引脚到读取引脚状态,不能超过15us。
总的读时序时间应该在60us。

>读数据时,一定把中断关闭。单总线程序一定防止中断破坏时序,导致读出的数字不正确。

/*******************************************************************************
Function: Driver_1Wire_Read
Description: DS18B20 读操作
Output: unsigned char date:读一字节
Return: 无
*******************************************************************************/
unsigned char  Driver_1Wire_Read()		
{
      EA = 0;
  	  unsigned char date;
	  unsigned char tmp;
	  for (temp = 0x01; temp != 0;temp <<= 1)
	  {
          DS18B20 = 0;  
	      _nop_();  
	      _nop_();  
	      DS18B20 = 1;
          _nop_();  
	      _nop_(); 	
		  if(!DS18B20)           //如果返回是0;取反为1。
		  { 
		     date &= ~temp      // temp =0x00.取反为0xfe(1111 1111)。与返回的date 0(0000 0000)与操作,为0000 0000
		  }
          else
          {
		       date |= temp       // temp =0x01(0000 0001)。与返回的date 0(0000 0000)或操作,为0000 0001
	      }	
		  elay60us();				
	  }
	  EA = 1;
	  return date
}

三.DS18B20的主要性能

1.上电默认12位的分辨率,转换为750ms。
2.DS18B20典型电路连接

在这里插入图片描述
在这里插入图片描述

2.DS18B20内部结构

在这里插入图片描述

byte 1 byte 2 是为了在多机模式,响应报警搜索指令。是否达到某个DS18B20的高低温触发值

在这里插入图片描述
使用拷贝指令将RAM的命令拷贝到EEPROM中,防止掉电不丢失。
在这里插入图片描述

当温度为正时,符号位为0,把温度寄存器中的数据乘以0.0625即可得到温度值。
当温度为负时,符号位为1,把温度寄存器中的数据取反加1,乘以0.0625即可得到温度值,最后再加上个负号。

三.DS18B20指令

1.ROM指令

命令均为8位,用来搜索,甄别从器件

1.器件操作的功能指令

存储器操作,转换启动

3.单总线的操作流程

(1)初始化
(2)ROM指令
(3)功能指令

在这里插入图片描述

/*******************************************************************************
Function: BSP_DS18B20_Start()
Description:启动DS18B20
Input:  无
Output: 无
Return: 无
*******************************************************************************/
bit BSP_DS18B20_Start()
 {
     bit ack; 
	   ack =  Driver_1WireRst();                      //初始化
     if(ack == 0)
		 {
		     Driver_1Wire_Write(BSP_SKIP_ROM);        //ROM指令的
		     Driver_1Wire_Write(Convert);             //功能指令,启动温度转换
		 }
		 return ~ack;
 }
 /*******************************************************************************
Function: BSP_DS18B20_Start()
Description:启动DS18B20
Input:  无
Output: 无
Return: 无
*******************************************************************************/
bit BSP_DS18B20_Read(int *temp)                  //这里以指针地址方式传递,如果想获取数据则使用&取地址符
{
   bit ack;
	 unsigned char MSB,LSB;
	 ack =  Driver_1WireRst();                //初始化
	 if(ack == 0)
	 {
	     Driver_1Wire_Write (Read_Register); 
       LSB = Driver_1Wire_Read()		            //低位字节保存LSB
	     MSB = Driver_1Wire_Read()		            //高位字节保存MSB
	     *temp =((int)MSB<<8)+LSB;                //8位的MSB强制转为16位
	 }
	 return ~ack;
}

main.c

oid Timer0Init(void);		//10微秒@12.000MHz

unsigned char flag;        //定义一个标志
/*******************************************************************************
* 函 数 名       : main
* 函数功能		 : 主函数
* 输    入       : 无
* 输    出    	 : 无
*******************************************************************************/

void main()
{   
    unsigned char ack;
	  int temp;                   //保存温度数据
	  int itemp;                  //分离温度数据整数
	  int dtemp;                  //分离温度数据小数
	  unsigned char str[12];      //使用1602显示,定义一个数组,保存数据转换成的字符串
	  unsigned char len;
	  BSP_DS18B20_Start();
	  LCD_Init();
	  Timer0Init;
    while(1)
    {	  
			
    } 
}

void Timer0Init(void) 	//10微秒@12.000MHz
{
    //AUXR &= 0x7F;	//定时器时钟12T模式
    TMOD &= 0xF0;   //设置定时器模式
    TMOD |= 0x01;   //设置定时器模式
	TL0 = 0xF6;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	ET0 = 1;
    EA = 1;
	TR0 = 1;		//定时器0开始计时
}
dtemp =(dtemp * 100) *0.0625;
str[len++] = dtemp / 10 + ' 0';15/10=1
str[len++] = dtemp % 10 + ' 0';15%10=5
str[len] = '\0'; 
  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值