单总线协议

一、单总线协议(1-wire)

1.定义:主机和从机用一根总线进行通信,是一种半双工的通信方式,单线=时钟线+数据线+控制线( +电源线)。理想状况下一条总线上的从器件数量几乎不受数量限制。

2.特点:这是由达拉斯半导体公司推出的一项通信技术。它采用单根信号线,既可传输时钟,又能传输数据,而且数据传输是双向的。

3.优点:单总线技术具有线路简单,硬件开销少,成本低廉,便于总线扩展和维护等。

二、单总线通信过程

所有的单总线器件要求采用严格的通信协议, 以保证数据的完整性。该协议定义了几种信号类型:复位脉冲、 应答脉冲、 写0、写1、 读0和读1。所有这些信号,除了应答脉冲以外,都由主机发出同步信号。并且发送所有的命令和数据都是字节的低位在前,这一点与多数串行通信格式不同(多数为字节的高位在前)。

(1)初始化序列:复位和应答脉冲

初始化过程 = 复位脉冲 + 从机应答脉冲。

主机通过拉低单总线480 ~ 960 us产生复位脉冲,然后释放总线,进入接收模式。主机释放总线时,会产生低电平跳变为高电平的上升沿,单总线器件检测到上升沿之后,延时15 ~ 60 us,单总线器件拉低总线60 ~ 240 us来产生应答脉冲。主机接收到从机的应答脉冲说明单总线器件就绪,初始化过程完成。

初始化时序图如下所示:
在这里插入图片描述

(2)写间隙

写间隙有两种,包括写0的时间隙和写1的时间隙。

当数据线拉低后,在15 ~ 60 us的时间窗口内对数据线进行采样。如果数据线为低电平,就是写0,如果数据线为高电平,就是写1。主机要产生一个写1时间隙,就必须把数据线拉低,在写时间隙开始后的15 us内允许数据线拉高。主机要产生一个写0时间隙,就必须把数据线拉低并保持60 us。

写时间隙时序图如下所示:
在这里插入图片描述

(3)读时间隙

当主机把总线拉低是,并保持至少1 us后释放总线,必须在15 us内读取数据。

单总线器件仅在主机发出读时隙时,才向主机传输数, 所以, 在主机发出读数据命令后,必须马上产生读时隙,以便从机能够传输数据。所有读时隙至少需要 60us, 且在两次独立的读时隙之间至少需要 1us的恢复时间,每个读时隙都由主机发起, 至少拉低总线 1us (图5 所示)。在主机发起读时隙之后,单总线器件才开始在总线上发送 0 或1。 若从机发送1,则保持总线为高电平;若发送 0, 则拉低总线 。当发送 0 时,从机在该时隙结束后释放总线 。由上拉电阻将总线拉回至空闲高电平状态。从机发出的数据在起始时隙之后,保持有效时间 15us ,因而,主机在读时隙期间必须释放总线 ,并且在时隙起始后的 15 us 之内采样总线状态。

读时间隙时序图如下所示:
在这里插入图片描述

三、单总线实例—DS18B20

当主机对多个DS18B20的某一设备进行操作时,主机首先逐个与挂在总线设备挂接,使用搜索ROM(FOh)指令,读出其序列号(33H),然后发送匹配指令(55h),紧接着提供64位序列号,之后就是操作该DS18B20了。

如果只有一个DS18B20测温,就不需要搜索ROM、读ROM以及匹配ROM操作了,只需要指令跳过ROM(CCh)指令,就可指令温度转换(44h)和读取温度(BEh)操作了。

在这里插入图片描述


#include "ds18b20.h"
#include "delay.h"	

//	 
//实验平台:STM32F103								  
//
  

//复位DS18B20
void DS18B20_Rst(void)	   
{                 
	DS18B20_IO_OUT(); 	//SET PG11 OUTPUT
    DS18B20_DQ_OUT=0; 	//拉低DQ
    delay_us(750);    	//拉低750us
    DS18B20_DQ_OUT=1; 	//DQ=1 
	delay_us(15);     	//15US
}
//等待DS18B20的回应
//返回1:未检测到DS18B20的存在
//返回0:存在
u8 DS18B20_Check(void) 	   
{   
	u8 retry=0;
	DS18B20_IO_IN();	//SET PG11 INPUT	 
    while (DS18B20_DQ_IN&&retry<200)
	{
		retry++;
		delay_us(1);
	};	 
	if(retry>=200)return 1;
	else retry=0;
    while (!DS18B20_DQ_IN&&retry<240)
	{
		retry++;
		delay_us(1);
	};
	if(retry>=240)return 1;	    
	return 0;
}
//从DS18B20读取一个位
//返回值:1/0
u8 DS18B20_Read_Bit(void) 	 
{
    u8 data;
	DS18B20_IO_OUT();	//SET PG11 OUTPUT
    DS18B20_DQ_OUT=0; 
	delay_us(2);
    DS18B20_DQ_OUT=1; 
	DS18B20_IO_IN();	//SET PG11 INPUT
	delay_us(12);
	if(DS18B20_DQ_IN)data=1;
    else data=0;	 
    delay_us(50);           
    return data;
}
//从DS18B20读取一个字节
//返回值:读到的数据
u8 DS18B20_Read_Byte(void)     
{        
    u8 i,j,dat;
    dat=0;
	for (i=1;i<=8;i++) 
	{
        j=DS18B20_Read_Bit();
        dat=(j<<7)|(dat>>1);
    }						    
    return dat;
}
//写一个字节到DS18B20
//dat:要写入的字节
void DS18B20_Write_Byte(u8 dat)     
 {             
    u8 j;
    u8 testb;
	DS18B20_IO_OUT();	//SET PG11 OUTPUT;
    for (j=1;j<=8;j++) 
	{
        testb=dat&0x01;
        dat=dat>>1;
        if (testb) 
        {
            DS18B20_DQ_OUT=0;	// Write 1
            delay_us(2);                            
            DS18B20_DQ_OUT=1;
            delay_us(60);             
        }
        else 
        {
            DS18B20_DQ_OUT=0;	// Write 0
            delay_us(60);             
            DS18B20_DQ_OUT=1;
            delay_us(2);                          
        }
    }
}
//开始温度转换
void DS18B20_Start(void) 
{   						               
    DS18B20_Rst();	   
	DS18B20_Check();	 
    DS18B20_Write_Byte(0xcc);	// skip rom
    DS18B20_Write_Byte(0x44);	// convert
} 

//初始化DS18B20的IO口 DQ 同时检测DS的存在
//返回1:不存在
//返回0:存在    	 
u8 DS18B20_Init(void)
{
 	GPIO_InitTypeDef  GPIO_InitStructure;
 	
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE);	 //使能PORTG口时钟 
	
 	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;				//PORTG.11 推挽输出
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		  
 	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(GPIOG, &GPIO_InitStructure);

 	GPIO_SetBits(GPIOG,GPIO_Pin_11);    //输出1

	DS18B20_Rst();

	return DS18B20_Check();
}  
//从ds18b20得到温度值
//精度:0.1C
//返回值:温度值 (-550~1250) 
short DS18B20_Get_Temp(void)
{
    u8 temp;
    u8 TL,TH;
	short tem;
    DS18B20_Start ();  			// ds1820 start 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;					//获得底八位
    tem=(float)tem*0.625;		//转换
		
		if(temp)return tem; 		//返回温度值
		else return -tem;
    
}


#ifndef __DS18B20_H
#define __DS18B20_H 
#include "sys.h"   
//	 
								  
//

//IO方向设置
#define DS18B20_IO_IN()  {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=8<<12;}
#define DS18B20_IO_OUT() {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=3<<12;}
IO操作函数											   
#define	DS18B20_DQ_OUT PGout(11) //数据端口	PA0 
#define	DS18B20_DQ_IN  PGin(11)  //数据端口	PA0 
   	
u8 DS18B20_Init(void);//初始化DS18B20
short DS18B20_Get_Temp(void);//获取温度
void DS18B20_Start(void);//开始温度转换
void DS18B20_Write_Byte(u8 dat);//写入一个字节
u8 DS18B20_Read_Byte(void);//读出一个字节
u8 DS18B20_Read_Bit(void);//读出一个位
u8 DS18B20_Check(void);//检测是否存在DS18B20
void DS18B20_Rst(void);//复位DS18B20    
#endif

总结

单总线技术以其线路简单、硬件开销少、成本低廉、软件设计简单优势而有着无可比拟的应用前景。基于单总线技术能较好地解决传统识别器普遍存在的携带不便、易损坏、易受腐馈、易受电磁干扰等不足,可应用于高度安全的门禁、身份识别等领域。其通信可靠简单,很容易实现。因此单总线技术有着广阔的应用前景,是值得产注的一个发展领域。

  • 14
    点赞
  • 82
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值