单总线协议详细时序理解 包含c源码(基于普中51单片机DS18B20)

前言  

这篇文章是本人通过学习51单片机中DS18B20模块中用到的单总线通讯协议做出的对单总线通信的理解,主要是针对单总线通信协议的详细理解,我们主要理解它的时序结构,就完全够写代码了,源码来自B站51单片机教学up主江协科技。

一、概述

        单总线是Maxim全资子公司Dallas的一项专有技术。它采用单根信号线,既传输时钟,又传输数据,而且数据传输是双向的。它具有节省I/O口线资源、结构简单、成本低廉、便于总线扩展和维护等诸多优点。

二、单总线通信电路

        单总线通信电路是一种较为简单的通讯电路,它只有一根线就能实现主机和从机的双向通信(也就是图中的1-Wire BUS),VDD和GND给DS18B20供电,DQ线就是连接单总线和DS18B20唯一的通信线,我们需要给DQ一个4.7KΩ上拉电阻并且将其配置成开漏模式。

三、单总线的时序结构

1.单总线初始化

        主机将总线拉低至少480us,然后释放总线,等待15~60us后,存在的从机会拉低总线60~240us来响应主机,之后从机会释放总线 。(初始化这里的主机我们默认我们的单片机,从机就是DS18B20)(每句话都是对应下面的每句代码的)

//引脚定义
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
	OneWire_DQ=1;
	i = 32;while (--i);			//Delay 70us
	AckBit=OneWire_DQ;
	i = 247;while (--i);		//Delay 500us
	return AckBit;
}

2.发送一个比特位

我们要发送一个字节的话,就需要一个比特位一个比特位这样发8次,并且全都采用2进制,这样我们只需要发“0”和“1” 

主机将总线拉低60~120us,然后释放总线,表示发送0;主机将总线拉低1~15us,然后释放总线,表示发送1。从机将在总线拉低30us后读取电平(因为30us的电平不可能处于变化状态,不是高就是低,所以说30us是一个典型值),整个时序为60us。

/**
  * @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;
}

 3.接收一个比特位

        整个时序也是60us,我们分为三步。第一步,拉低总线(1~5us),第二步,释放总线(这里释放总线是一个时刻,我们在5us的时刻释放总线,然后再等5us),第三步,读取数据(我们等的第二个5us就是在等待从机是否会在这5us之内把总线拉下来,如果拉下来了就是0,没拉下来,因为我们主机已经释放了总线,那总线在这一时间段内也足够它恢复到高电平,所以在这10us末我们读取数据是很准确的,低电平就是0,高电平就是1,这样还有剩下的50us我们直接延时过去,一个时序就结束了)。需要注意的是,主机释放总线不一定就会变成高电平,主机释放总线后,从机如果发送的是0,他会继续拉下总线让总线保持低电平(这样即使主机释放了总线,总线也不会立刻回到高电平,而是被从机拉下来,继续保持低电平),如果发送的是1,我们可以认为从机没有做出任何动作响应,总线会随着主机的释放自动回到高电平。15us后如果发送的是0,从机会自动释放总线,这时主机和从机都释放了总线,总线才会回到高电平,至此一个时序结束。 

/**
  * @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;
}

 4.发送或接收一个字节

        实际上我们的函数参数基本上都是一个字节,所以我们用一个函数嵌套,定义一个变量i,for循环,将发送和接收的一个比特位&(0x01<<i)循环八次就OK了。

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

/**
  * @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;
}

 *以上仅个人对于但总线通信协议的理解,有疑问或者错误欢迎指出

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值