一、单总线简介
1.定义:主机和从机通过1根线进行通信,在一条总线上可挂接的从器件数量几乎不受限制。
2.特点:这是由达拉斯半导体公司推出的一项通信技术。它采用单根信号线,既可传输时钟,又能传输数据,而且数据传输是双向的。
3.优点:单总线技术具有线路简单,硬件开销少,成本低廉,便于总线扩展和维护等。
单总线各种详细介绍网上很多,此处不再赘述,直接进入正题(本文档以常用的DS18B20温度传感器为例)
二、单总线协议
单总线初始化
初始化过程 = 复位脉冲 + 从机应答脉冲。
主机通过拉低单总线480 ~ 960 us产生复位脉冲,然后释放总线,进入接收模式。主机释放总线时,会产生低电平跳变为高电平的上升沿,单总线器件检测到上升沿之后,延时15 ~ 60 us,单总线器件拉低总线60 ~ 240 us来产生应答脉冲。主机接收到从机的应答脉冲说明单总线器件就绪,初始化过程完成。
初始化时序图如下所示:
bit Ds18b20_Init(void)
{
bit ack_flg =0;
DQ = 1;//--保证总线是高电平
Delay_x_us(100);//--稍微演示一下,保证电平稳定
DQ = 0;//--主机拉总线
Delay_x_us(500);//--延时480us-960us
DQ = 1; //--释放总线,进入接收模式
Delay_x_us(60);//--延时15-60us 此处延时最大的,保证接收正确
ack_flg = DQ; //--读取总线应答电平 0:应答成功 1:应答失败
return ack_flg;
}
单总线写入
写间隙有两种,包括写0的时间隙和写1的时间隙。
当数据线拉低后,在15 ~ 60 us的时间窗口内对数据线进行采样。如果数据线为低电平,就是写0,如果数据线为高电平,就是写1。主机要产生一个写1时间隙,就必须把数据线拉低,在写时间隙开始后的15 us内允许数据线拉高。主机要产生一个写0时间隙,就必须把数据线拉低并保持60 us。
写时间隙时序图如下所示:
void Write_To_Ds18b20(uchar data)
{
uchar i;
for(i=0;i<8;i++)
{
DQ = 0;//--数据线拉
DQ = data&0x01; //--从字节低位开始写入 //--写入间隙大概15us
Delay_x_us(30);//--进入采样阶段,过了15us写入间隙以后,如果是低电平,就是写入0,如果是高电平就是写入1
DQ = 1; //--写入结束,将总线回复为高电平
data>>=1;开始写入下一位
}
Delay_x_us(30);
}
单总线读取
当主机把总线拉低是,并保持至少1 us后释放总线,必须在15 us内读取数据。
uchar Read_form_Ds18b20(void)
{
uchar i;
uchar data;
for(i=0;i<8;i++)
{
DQ = 0;//--把总线拉,,必须在15us内读完数据
data >>= 1;
DQ = 1;//保持1us后释放
if(DQ) //--采样
data |= 0x80;
Delay_x_us(30);
}
return data;
}
DS18B20用法
ds18b20内部的64位的rom存储其独一无二的序列号。暂存存储器包含了存储有数字温度结果的2个字节宽度的温度寄存器。
器件上电后默认为85摄氏度
另外,暂存存储器还提供了一个字节的过温和低温温度报警寄存器和一个字节的配置寄存器
字节3和字节4分别为设置过温和低温警告
当只有一个设备的时候,直接跳过ROM寻址,ROM寻址用于多个设备公用,用于判断具体是哪一个芯片
读取温度(仅仅包含整数部分)
unsigned char temperature()
{
char temp;
uchar HI_temp, LOW_temp;
Ds18b20_Init(); //DS18B20重置
Write_To_Ds18b20(0xcc); //跳过ROM寻址
Write_To_Ds18b20(0x44); //设置为温度读取模式 (跳过了对暂存寄存器的写取)
Delay_x_us(600); //等待温度读取模式的转换
Ds18b20_Init(); //DS18B20重置
Write_To_Ds18b20(0xcc); //跳过ROM寻址
Write_To_Ds18b20(0xbe); //读取暂存寄存器的内容(先低位,再高位)
LOW_temp = Read_form_Ds18b20();
HI_temp = Read_form_Ds18b20();
temp=high<<4;
temp|=(low>>4);
return temp;
}
读取温度(含小数部分)
float rd_temperature(void)
{
unsigned char MSH,MSL;
unsigned int temp;
float temperature;
Ds18b20_Init();
Write_To_Ds18b20(0xCC);
Write_To_Ds18b20(0x44);
Delay_x_us(600);
while(!DQ);
Ds18b20_Init();
Write_To_Ds18b20(0xCC);
Write_To_Ds18b20(0xBE);
MSL=Read_form_Ds18b20();
MSH=Read_form_Ds18b20();
temp=(MSH&0x0f);
temp<<=8;
temp|= MSL;
temperature=0.0625*temp;
return temperature*10; //返回值为真实温度*10;
}