单总线介绍
单总线(1-Wire BUS)是由Dallas公司开发的一种通用数据总线
一根通信线:DQ
异步、半双工
单总线只需要一根通信线即可实现数据的双向传输,当采用寄生供电时,还可以省去设备的VDD线路,此时,供电加通信只需要DQ和GND两根线
单总线的电路规范
设备的DQ均要配置成开漏输出模式(与I2C总线相似)
DQ添加一个上拉电阻,阻值一般为4.7KΩ左右(与I2C总线相似)
若此总线的从机采取寄生供电,则主机还应配一个强上拉输出电路
单总线时序结构
初始化:
主机将总线拉低至少480us,然后释放总线,等待15 ~ 60us后,存在的从机会拉低总线60 ~ 240us以响应主机,之后从机将释放总线
sbit OneWire_DQ = P3^7; //DS18B20d
/**
* @brief单总线初始化
* @param无
* @retval返回从机应答值,0为应答,1为不应答
*/
unsigned char OneWire_Init()
{
unsigned char i;
unsigned char AckBit;
OneWire_DQ = 1;
OneWire_DQ = 0;
i = 247;while (--i); //使用STC-ISP生成的500us延时
OneWire_DQ = 1;
i = 47;while (--i); //延时100us
AckBit = OneWire_DQ;
i = 247;while (--i); //延时500us
return AckBit;
}
发送一位:
主机将总线拉低60 ~ 120us,然后释放总线,表示发送0;主机将总线拉低1~15us,然后释放总线,表示发送1。从机将在总线拉低30us后(典型值)读取电平,整个时间片应大于60us
想发送0则按左边的时序,想发送1则按右边的时序
/**
* @brief 主机发送一位
* @param 要发送的数据位
* @retval无
*/
void OneWier_SendBit(unsigned char Bit)
{
unsigned char i;
OneWire_DQ = 0;
i = 4;while (--i); //延时10us
OneWire_DQ = Bit;
i = 24;while (--i); //延时50us
OneWire_DQ = 1;
}
接收一位:
主机将总线拉低1~15us,然后释放总线,并在拉低后15us内读取总线电平(尽量贴近15us的末尾),读取为低电平则为接收0,读取为高电平则为接收1 ,整个时间片应大于60us
/**
* @brief主机接收一位
* @param无
* @retval返回接收到的位
*/
unsigned char OneWire_ReceiveBit()
{
unsigned char i;
unsigned char Bit;
OneWire_DQ = 0; //先将总线拉低
i = 2;while (--i); //延时5us
OneWire_DQ = 1; //释放总线
i = 2;while (--i); //延时5us
Bit = OneWire_DQ; //读取总线
i = 24;while (--i); //延时50us
return Bit;
}
解释:
主机接收0:主机拉低总线几us后,释放总线,如果从机立马拉低总线,则表示从机想发送0,主机应该在15us的末尾读取总线状态0
主机接收1:主机拉低总线后,释放总线,从机并没有拉低总线,则表示从机想发送1,主机在15us末尾读取总线状态1
发送一个字节:
连续调用8次发送一位的时序,依次发送一个字节的8位(低位在前)
/**
* @brief 发送一个字节
* @param要发送的数据
* @retval无
*/
void OneWire_SendByte(unsigned char Data)
{
unsigned char i;
for(i = 0; i < 8; i++)
{
OneWier_SendBit(Data & (0x01<<i));
}
}
接收一个字节:
连续调用8次接收一位的时序,依次接收一个字节的8位(低位在前)
/**
* @brief 接收一个字节
* @param无
* @retval返回接收到的数据
*/
unsigned char OneWire_ReceiveByte()
{
unsigned char i;
unsigned char Data = 0x00;
for(i = 0; i < 8; i++)
{
if(OneWire_ReceiveBit()){Data|=(0x01<<i);}
}
return Data;
}