DS18B20时序
(整理自网络)
本文档参照Maxim公司DS18B20的Datasheet而完成。其中,加了灰框的部分为原文档内容,其中英文部分为官方文档内容,中文部分为本人的翻译。限于本人水平,本文档可能存在错误或者让人误解的内容,对于因此引起的一切问题作者(exploer,CIEE-CAU)概不负责。
INITIALIZATION PROCEDURE—RESET AND PRESENCEPULSES
初始化序列——复位和存在脉冲
All communication with theDS18B20 begins with an initialization sequence that consists of areset pulse from the master followed by a presence pulse from theDS18B20. This is illustrated in Figure 13. When the DS18B20 sendsthe presence pulse in response to the reset, it is indicating tothe master that it is on the bus and ready to operate.
DS18B20的所有通信都由由复位脉冲组成的初始化序列开始。该初始化序列由主机发出,后跟由DS18B20发出的存在脉冲(presence pulse)。下图(即如下截图)阐述了这一点。当发出应答复位脉冲的存在脉冲后,DS18B20通知主机它在总线上并且准备好操作了。
During theinitialization sequence the bus master transmits (TX) the resetpulse by pulling the 1-Wire bus low for a minimum of 480μs. The bus master then releasesthe bus and goes into receive mode (RX).
在初始化步骤中,总线上的主机通过拉低单总线至少480μs来产生复位脉冲。然后总线主机释放总线并进入接收模式。
When the bus is released, the5kΩ pullup resistor pulls the 1-Wire bus high. When the DS18B20detects this rising edge, it waits 15μs to 60μs and then transmitsa presence pulse by pulling the 1-Wire bus low for 60μs to240μs.
当总线释放后,5kΩ的上拉电阻把单总线上的电平拉回高电平。当DS18B20检测到上升沿后等待15到60us,然后以拉低总线60-240us的方式发出存在脉冲。
如文档所述,主机将总线拉低最短480us,之后释放总线。由于5kΩ上拉电阻的作用,总线恢复到高电平。DS18B20检测到上升沿后等待15到60us,发出存在脉冲:拉低总线60-240us。至此,初始化和存在时序完毕。
根据上述要求编写的复位函数为:
首先是延时函数:(由于DS18B20延时均以15us为单位,故编写了延时单位为15us的延时函数,注意:以下延时函数晶振为12MHz)
voidDelayxus_DS18B20(unsigned int t)
{
for(t;t>0;t--)
{
_nop_();_nop_();_nop_();_nop_();
}
_nop_();_nop_();
}
延时函数反汇编代码(方便分析延时公式)
C:0x00317F01 MOVR7,#0x01
C:0x00337E00 MOVR6,#0x00
C:0x00351206A6LCALLdelayxus(C:06A6)
38: void Delayxus_DS18B20(unsigned int t)
39: {
40:for(t;t>0;t--)
C:0x06A6D3SETB C
C:0x06A7EFMOVA,R7
C:0x06A89400 SUBB A,#0x00
C:0x06AAEEMOVA,R6
C:0x06AB9400 SUBB A,#0x00
C:0x06AD400B JC C:06BA
41:{
42: _nop_();_nop_();_nop_();_nop_();
C:0x06AF00NOP
C:0x06B000NOP
C:0x06B100NOP
C:0x06B200NOP
43:}
C:0x06B3EFMOVA,R7
C:0x06B41FDECR7
C:0x06B570EF JNZDelayxus_DS18B20(C:06A6)
C:0x06B71EDECR6
C:0x06B880EC SJMP Delayxus_DS18B20(C:06A6)
44:_nop_();_nop_();
C:0x06BA00NOP
C:0x06BB00NOP
45: }
C:0x06BC22RET
分析上述反汇编代码,可知延时公式为15*(t+1)
bit RST_DS18B20()
{
bitret="1";
DQ=0;
Delayxus_DS18B20(32);
DQ=1;
Delayxus_DS18B20(4);
ret=DQ;
Delayxus_DS18B20(14);
DQ=1;
return(~ret);
}
写时序:
READ/WRITE TIME SLOTS
读写时隙
The bus master writes data tothe DS18B20 during write time slots and reads data from the DS18B20during read time slots. One bit of data is transmitted over the1-Wire bus per time slot.
主机在写时隙向DS18B20写入数据,并在读时隙从DS18B20读入数据。在单总线上每个时隙只传送一位数据。
WRITE TIME SLOTS
写时间隙
There are two types of writetime slots: “Write 1” time slots and “Write 0” time slots. The busmaster uses a Write 1 time slot to write a logic 1 to the DS18B20and a Write 0 time slot to write a logic 0 to the DS18B20. Allwrite time slots must be a minimum of 60μs in duration with aminimum of a 1μs recovery
time between individual write slots. Both types of write time slotsare initiated by the master pulling the 1-Wire bus low (see Figure14).
有两种写时隙:写“0”时间隙和写“1”时间隙。总线主机使用写“1”时间隙向DS18B20写入逻辑1,使用写“0”时间隙向DS18B20写入逻辑0.所有的写时隙必须有最少60us的持续时间,相邻两个写时隙必须要有最少1us的恢复时间。两种写时隙都通过主机拉低总线产生。
To generatea Write 1 time slot, after pulling the 1-Wire bus low, the busmaster must release the 1-Wire bus within 15μs. When the bus isreleased, the 5kΩ pullup resistor will pull the bus high. Togenerate a Write 0 time slot, after pulling the 1-Wire bus low, thebus master must continue to hold the bus low for the duration ofthe time slot (at least 60μs).
为产生写1时隙,在拉低总线后主机必须在15μs内释放总线。在总线被释放后,由于5kΩ上拉电阻的作用,总线恢复为高电平。为产生写0时隙,在拉低总线后主机必须继续拉低总线以满足时隙持续时间的要求(至少60μs)。
The DS18B20 samples the1-Wire bus during a window that lasts from 15μs to 60μs after themaster initiates the write time slot. If the bus is high during thesampling window, a 1 is written to the DS18B20. If the line is low,a 0 is written to the DS18B20.
在主机产生写时隙后,DS18B20会在其后的15到60us的一个时间窗口内采样单总线。在采样的时间窗口内,如果总线为高电平,主机会向DS18B20写入1;如果总线为低电平,主机会向DS18B20写入0。
如文档所述,所有的写时隙必须至少有60us的持续时间。相邻两个写时隙必须要有最少1us的恢复时间。所有的写时隙(写0和写1)都由拉低总线产生。
为产生写1时隙,在拉低总线后主机必须在15us内释放总线(拉低的电平要持续至少1us)。由于上拉电阻的作用,总线电平恢复为高电平,直到完成写时隙。
为产生写0时隙,在拉低总线后主机持续拉低总线即可,直到写时隙完成后释放总线(持续时间60-120us)。
写时隙产生后,DS18B20会在产生后的15到60us的时间内采样总线,以此来确定写0还是写1。
满足上述要求的写函数为:
void WR_Bit(bit i)
{
DQ=0;//产生写时序
_nop_();
_nop_();//总线拉低持续时间要大于1us
DQ=i;//写数据,0和1均可
Delayxus_DS18B20(3);//延时60us,等待ds18b20采样读取
DQ=1;//释放总线
}
void WR_Byte(unsigned chardat)
{
unsignedchar i="0";
while(i++<8)
{
WR_Bit(dat&0x01);//从最低位写起
dat>>=1;//注意不要写成dat>>1
}
}读时序:
READ TIME SLOTS
读时间隙
The DS18B20 can only transmitdata to the master when the master issues read time slots.Therefore, the master must generate read time slots immediatelyafter issuing a Read Scratchpad [BEh] or Read Power Supply [B4h]command, so that the DS18B20 can provide the requested data. Inaddition, the master can generate read time slots after issuingConvert T [44h] or Recall
E 2[B8h] commands to find out the status of the operation asexplained in the DS18B20 Function Commands section.
DS18B20只有在主机发出读时隙后才会向主机发送数据。因此,在发出读暂存器命令[BEh]或读电源命令[B4h]后,主机必须立即产生读时隙以便DS18B20提供所需数据。另外,主机可在发出温度转换命令T [44h]或Recall命令E 2[B8h]后产生读时隙,以便了解操作的状态(在DS18B20操作指令这一节会详细解释)。
All read time slots must be aminimum of 60μs in duration with a minimum of a 1μs recovery timebetween slots. A read time slot is initiated by the master devicepulling the 1-Wire bus low for a minimum of 1μs and then releasingthe bus (see Figure 14). After the master initiates the read timeslot, the DS18B20 will begin transmitting a 1 or 0 on bus. TheDS18B20 transmits a 1 by leaving the bus high and transmits a 0 bypulling the bus low. When transmitting a 0, the DS18B20 willrelease the bus by the end of the time slot, and the bus will bepulled back to its high idle state by thepullup resister. Output data from the DS18B20 is valid for 15μsafter the falling edge that initiated the read time slot.Therefore, the master must release the bus and then sample the busstate within 15μs from the start of the slot.
所有的读时隙必须至少有60us的持续时间。相邻两个读时隙必须要有最少1us的恢复时间。所有的读时隙都由拉低总线,持续至少1us后再释放总线(由于上拉电阻的作用,总线恢复为高电平)产生。在主机产生读时隙后,DS18B20开始发送0或1到总线上。DS18B20让总线保持高电平的方式发送1,以拉低总线的方式表示发送0.当发送0的时候,DS18B20在读时隙的末期将会释放总线,总线将会被上拉电阻拉回高电平(也是总线空闲的状态)。DS18B20输出的数据在下降沿(下降沿产生读时隙)产生后15us后有效。因此,主机释放总线和采样总线等动作要在15μs内完成。
Figure 15 illustrates thatthe sum of TINIT, TRC, and TSAMPLE must be less than 15μs for aread time slot.
插图15表明了对于读时隙,TINIT(下降沿后低电平持续时间), TRC(上升沿)和TSAMPLE(主机采样总线)的时间和要在15μs以内。
Figure 16 shows that systemtiming margin is maximized by keeping TINIT and TRC as short aspossible and by locating the master sample time during read timeslots towards the end of the 15μs period.
下图显示了最大化系统时间宽限的方法:让TINIT 和TRC尽可能的短,把主机采样总线放到15μs这一时间段的尾部。
由文档可知,DS18B20只有在主机发出读时隙时才能发送数据到主机。因此,主机必须在BE命令,B4命令后立即产生读时隙以使DS18B20提供相应的数据。另外,在44命令,B8命令后也要产生读时隙。
所有的读时隙必须至少有60us的持续时间。相邻两个读时隙必须要有最少1us的恢复时间。所有的读时隙都由拉低总线,持续至少1us后再释放总线(由于上拉电阻的作用,总线恢复为高电平)产生。DS18B20输出的数据在下降沿产生后15us后有效。因此,释放总线和主机采样总线等动作要在15us内完成。
满足以上要求的函数为:
unsigned charRead_Bit()
{
unsignedchar ret;
DQ=0;//拉低总线
_nop_();_nop_();
DQ=1;//释放总线
_nop_();_nop_();
_nop_();_nop_();
ret=DQ;//读时隙产生7 us后读取总线数据。把总线的读取动作放在15us时间限制的后面是为了保证数据读取的有效性
Delayxus_DS18B20(3);//延时60us,满足读时隙的时间长度要求
DQ=1;//释放总线
return ret;//返回读取到的数据
}
unsigned charRead_Byte()
{
unsignedchar i;
unsignedchar dat="0";
for(i=0;i<8;i++)
{
dat>>=1;//先读最低位
if(Read_Bit())
dat|=0x80;
}
return(dat);
}
void Start_DS18B20()
{
DQ=1;
RST_DS18B20();
WR_Byte(0xcc);// skip
WR_Byte(0x44);//启动温度转换
}
int Read_Tem()
{
inttem="0";
RST_DS18B20();
WR_Byte(0xcc);// skip
WR_Byte(0xbe);//发出读取命令
tem=Read_Byte();//读出温度低八位
tem|=(((int)Read_Byte())<<8);//读出温度高八位
returntem;
}
注: DS18B20官方文档中没有说明读写数据位的顺序,查了下资料,DS18B20读写数据都是从最低位读写的。
*共阳极4位数码管显示,请根据自己的电路图再定义端口*/
#include<reg52.H>
sbitwarmer=P1^4;
sbitled_run=P1^0;
//sbitk_power=P3^3;
sbitzf=P2^0;
sbitbai=P2^1;
sbitshi=P2^2;
sbitge=P2^3;
sbitdots=P2^4;
sbitxs=P2^5;
sbitDQ=P3^3;//定义通信端口
//延时函数
unsignedchartab[]={0xc0,0xf9,0xa4,0xb0,//0,1,2,3
0x99,0x92,0x82,0xf8,0x80,0x90,0xff};
//456789
unsignedintt=0;
unsignedchartflag;
unsignedchardatadisdata[4];
voiddelay(unsignedchari)
{
while(i--);
}
//初始化函数
Init_DS18B20(void)
{
unsignedcharx=0;
DQ=1;//DQ复位
delay(8);//稍做延时
DQ=0;//单片机将DQ拉低
delay(80);//精确延时大于480us
DQ=1;//拉高总线
delay(14);
x=DQ;//稍做延时后如果x=0则初始化成功x=1则初始化失败
delay(20);
}
//读一个字节
ReadOneChar(void)
{
unsignedchari=0;
unsignedchardat=0;
for(i=8;i>0;i--)
{
DQ=0;//给脉冲信号
dat>>=1;
DQ=1;//给脉冲信号
if(DQ)
dat|=0x80;
delay(4);
}
return(dat);
}
//写一个字节
WriteOneChar(unsignedchardat)
{
unsignedchari=0;
for(i=8;i>0;i--)
{
DQ=0;
DQ=dat&0x01;
delay(5);
DQ=1;
dat>>=1;
}
delay(4);
}
//读取温度
ReadTemperature(void)
{
unsignedchara=0;
unsignedcharb=0;
Init_DS18B20();
WriteOneChar(0xCC);//跳过读序号列号的操作发送指令0xcc
WriteOneChar(0x44);//启动温度转换发送指令0x44
Init_DS18B20();
WriteOneChar(0xCC);//跳过读序号列号的操作
WriteOneChar(0xBE);//读取温度寄存器等(共可读9个寄存器)前两个就是温度发送指令0xbe
a=ReadOneChar();//读取温度值低位
b=ReadOneChar();//读取温度值高位
t=b;
t<<=8;//值左移8位
//a=a>>4;//低位右移4位,舍弃小数部分
//t=b<<4;//高位左移4位,舍弃符号位
//t=t|a;
t=t|a;//合并高低位数值
if(t<0xfff)
tflag=1;
else
{
tflag=0;
t=~t+1;//负值换算
}
t=t*(0.625);//温度扩大10倍,精确到1位小数
return(t);
}
voiddisplay_temper(unsignedinti)
{
disdata[0]=i/1000;//百位数
disdata[1]=i00/100;//十位数
disdata[2]=i0/10;//个位数
disdata[3]=i;//小数位
if(tflag==1)
tflag=0xff;//正号,不显示
else
tflag=0xbf;//负号,显示-
P2=0xff;
zf=0;
P0=tflag;
delay(150);
P0=0xff;
zf=1;
bai=0;
if(disdata[0]>0)P0=tab[disdata[0]];
delay(150);
bai=1;
shi=0;
P0=tab[disdata[1]];
delay(150);
shi=1;
ge=0;
P0=tab[disdata[2]];
delay(100);
ge=1;
dots=0;
P0=0x7f;
delay(150);
dots=1;
xs=0;
P0=tab[disdata[3]];
delay(150);
P0=0xff;
P2=0xff;
}
voidmain(void)
{unsignedinttemp;
while(1)//主循环
{temp=ReadTemperature();
display_temper(temp);
}
}