DS18X20/DS1822 1-Wire温度传感器在微控制器环境中的接口

本应用向用户介绍简单的1-wire软件,用于将微控制器连接至ds18b20、ds18s20和ds1822 1-wire温度传感器。本文举例使用ds5000(兼容8051)微控制器。给出了软件示例,说明了延迟、复位、读位、写位、读字节、写字节、rom搜索、crc、读温度和读暂存本例程的实现。
介绍
ds1b18、ds20s18或ds20等1822-wire器件与微控制器的接口有多种方法可供选择。这些方法包括简单的软件解决方案,使用串行接口芯片(如ds2480b),以及将maxim的vhdl 1-wire主控制器集成到定制asic中。本文向用户介绍最简单的软件方案,用于微控制器与任意数量的ds1x18或ds20温度传感器之间的基本1822-wire通信。
ds18b20、ds18s20和ds1822的详细时序和工作原理信息可在各自的数据资料中找到,可从maxim网站获取。
硬件配置
图1中的框图说明了使用多个1-wire温度传感器时硬件配置的简单性。单线总线为所有设备提供通信访问和电源。总线电源通过 4.7kω 上拉电阻从 3v 至 5.5v 电源轨提供。总线上可以连接几乎无限数量的1-wire器件,因为每个器件都有一个唯一的64位rom码标识符。
图1.主机微控制器接口。
接口时序
与ds18x20/ds1822的通信通过使用“时隙”实现,允许数据通过1-wire总线传输。每个通信周期从微控制器的复位脉冲开始,然后是来自ds18x20/ds1822的存在脉冲,如图2所示。
当总线主控将1-wire总线从逻辑高电平(非活动)拉至逻辑低电平时,将启动写入时隙。所有写入时隙的持续时间必须为60μs至120μs,周期之间的最小恢复时间为1μs。写“0”和写“1”时隙如图3所示。在写入“0”时隙期间,主机微控制器在该时隙的持续时间内将线路拉低。但是,在写入“1”时隙期间,微控制器将线路拉低,然后在时隙开始后15μs内释放线路。
当微控制器将总线拉低1μs,然后释放时隙时启动,ds18x20/ds1822可以控制线路并提供有效数据(高电平或低电平)。所有读取时隙的持续时间必须为60μs至120μs,周期之间的恢复时间至少为1μs(见图3)。
图2.复位脉冲和存在脉冲。
图3.写入和读取时间段。
软件控制
为了精确控制1-wire接口的特殊定时要求,必须首先建立某些关键功能。创建的第一个函数必须是“延迟”函数,它是所有读写控制的组成部分。此功能完全取决于微控制器的速度。本文使用ds5000(兼容8051)微控制器,其工作频率为11.059mhz。右边的示例说明了用于创建时序延迟的“c”原型函数。
延迟示例
// delay - with an 11.059mhz crystal.// calling the routine takes about 24us, and then// each count takes another 16us.//void delay(int useconds){int s;for (s=0; s 重置示例
//////////////////////////////////////////////////////////////////////////////// ow_reset - performs a reset on the one-wire bus and// returns the presence detect. reset is 480us, so delay// value is (480-24)/16 = 28.5 - we use 29. presence checked// another 70us later, so delay is (70-24)/16 = 2.875 - we use 3.//unsigned char ow_reset(void){unsigned char presence;dq = 0; //pull dq line lowdelay(29); // leave it low for 480usdq = 1; // allow line to return highdelay(3); // wait for presencepresence = dq; // get presence signaldelay(25); // wait for end of timeslotreturn(presence); // presence signal returned} // 0=presence, 1 = no part 以下四个示例中显示的读写函数代码段提供了所有数据位和数据字节读写操作所需的基本结构。
读取位示例
//////////////////////////////////////////////////////////////////////////////// read_bit - reads a bit from the one-wire bus. the delay// required for a read is 15us, so the delay routine won't work.// we put our own delay function in this routine in the form of a// for() loop.//unsigned char read_bit(void){unsigned char i;dq = 0; // pull dq low to start timeslotdq = 1; // then return highfor (i=0; i<3; i++); // delay 15us from start of timeslotreturn(dq); // return value of dq line} 写入位示例
//////////////////////////////////////////////////////////////////////////////// write_bit - writes a bit to the one-wire bus, passed in bitval.//void write_bit(char bitval){dq = 0; // pull dq low to start timeslotif(bitval==1) dq =1; // return dq high if write 1delay(5); // hold value for remainder of timeslotdq = 1;}// delay provides 16us per loop, plus 24us. therefore delay(5) = 104us 读取字节示例
//////////////////////////////////////////////////////////////////////////////// read_byte - reads a byte from the one-wire bus.//unsigned char read_byte(void){unsigned char i;unsigned char value = 0;for (i=0;i<8;i++){if(read_bit()) value|=0x01 为了充分利用1-wire网络概念,微控制器必须能够与连接到网络的任意数量的器件进行通信。为此,微控制器必须使用图64所示的“search rom”算法学习总线上每个器件的唯一4位rom识别码。图 4 以下示例解释了具有四个从设备的总线的搜索 rom 例程。还显示了搜索 rom 例程的示例代码。一旦识别出所有rom代码,“匹配rom”命令可用于与网络上的任何特定设备进行通信。
图4.搜索 rom 算法。
rom 搜索示例
在rom搜索过程中,总线主站必须重复一个简单的三步例程:1)从从设备读取rom码位,2)读取位的补码,3)写入该位的选定值。总线主机必须执行此三步例程 64 次,每个 rom 代码位执行一次。完成一次通过后,总线主站将知道总线上一个从设备的rom代码。其余设备及其rom代码可以通过额外的通道来识别。
以下示例说明了rom搜索过程,该示例假设四个不同的器件连接到同一1-wire总线。四个设备的rom代码如下所示:
rom1 00110101...
rom2 10101010...
rom3 11110101...
rom4 00010001...
搜索过程如下:
总线主站通过发出复位脉冲来开始初始化序列。从设备响应方式 同时发出存在脉冲。
然后,总线主控器在1-wire总线上发出搜索rom命令。
每个器件将响应搜索rom命令,将各自rom码的第一位值放到1-wire总线上。然后,主站将读取总线值。在这种情况下,rom1和rom4将在0-wire总线上放置一个1,即它们将其拉低。rom2和rom3将在1-wire总线上放置一个1,允许线路保持高电平。结果是线路上所有设备的逻辑 and;因此,总线主站将读取 0。1-wire总线上的所有器件都将响应此读取,方法是将其rom码的第一位补码放到1-wire总线上:rom1和rom4在1-wire总线上放置一个1,使线路保持高电平,rom2和rom3将在总线上放置一个0。 把它拉低。总线主控服务器现在将再次读取总线,并将再次读取 0。
根据从设备rom代码,总线主站可以从两次读取中获得四种可能的数据组合。这些组合可以解释如下:
00 有些连接到总线的设备在当前rom代码位位置具有冲突位。
01 连接到总线的所有设备在此位位置都有一个 0。
10 连接到总线的所有设备在此位位置都有一个 1。
11 没有器件连接到1-wire总线。
在本例中,总线主控器在每次读取时都读取0,这告诉它1-wire总线上有一些器件在第一个rom代码位置为0,而其他器件则为1。
为了响应前面的数据,总线主控服务器将 0 写入总线。这将取消选择此搜索通道其余部分的rom2和rom3,仅保留rom1和rom4“连接”到1-wire总线。
总线主站再执行两次读取,并收到 0,后跟 1。这表示仍连接到总线的所有设备都将 0 作为其第二个 rom 数据位。
然后,总线主站写入 0 以保持 rom1 和 rom4 连接到总线。
总线主站再次执行两次读取并接收两个 0。这向主机表明,1-wire总线上的一个器件在第三个rom码位置为0,另一个器件为1。
总线主站将 0 写入总线,总线取消选择 rom1,并将 rom4 保留为唯一仍连接的设备。
总线主站从 rom4 读取 rom 位的其余部分,并根据需要继续访问 rom4 设备。这样就完成了第一个 rom 搜索传递;总线主站现在通过学习4-wire总线上的rom码,唯一地识别了1-wire总线上的一个从机(rom)。
总线主站通过重复步骤 1 到 7 来启动新的 rom 搜索序列。
总线主站现在将 1 写入总线(而不是步骤 0 中所做的 8)。这会解耦 rom4,只留下 rom1 仍处于连接状态。
总线主站现在从rom1读取rom位的其余部分,并可以根据需要与rom1设备通信。这样就完成了第二个rom搜索过程,主设备现在已经识别了另一个从设备(rom1)。
总线主站通过重复步骤 1 到 3 开始新的 rom 搜索。
总线主控服务器现在将 1 写入总线(而不是步骤 0 中所做的 4)。这将取消选择此搜索传递的其余部分的 rom1 和 rom4,只留下耦合到总线的 rom2 和 rom3。
总线主站执行两次读取并接收两个 0。
总线主站将 0 写入总线,使 rom3 去耦,只留下 rom2 连接到总线。
总线主站从 rom2 读取 rom 位的其余部分,并在需要时与 rom2 设备通信。这样就完成了第三次rom搜索,主设备现在已经识别了rom2从设备。
总线主站通过重复步骤 13 到 15 开始第四次也是最后一次 rom 搜索。
总线主站将 1 写入总线(而不是步骤 0 中所做的 16),这会解耦 rom2,只留下 rom3 连接到总线。
总线主站从 rom3 读取 rom 位的其余部分,并在需要时与 rom3 设备通信。这样就完成了第四次rom搜索传递,在此期间,主设备识别了rom3设备。此时,主站已经识别了总线上的所有从设备,从这一点开始,总线主站可以使用其rom代码单独寻址任何设备。
注意:总线主控在每次rom搜索过程中学习一个1-wire器件的唯一rom代码。学习一个rom代码所需的时间是:
960μs + (8 + 3 × 64) 61μs = 13.16m
因此,总线主站每秒能够识别75个不同的1-wire从器件。
搜索 rom 代码示例
如下面的原型功能所示,“查找器件”功能以1-wire复位开始,以确定网络上是否有任何器件,如果有,则唤醒它们。然后调用“first”函数,以跟踪差异位并返回“next”,该函数在网络上找到每个唯一的设备。
“next”功能非常广泛,并且大部分工作都是为网络上的每个设备查找每个唯一的64位rom代码标识符。
// find devicesvoid finddevices(void){unsigned char m;if(!ow_reset()) //begins when a presence is detected{if(first()) //begins when at least one part is found{numroms=0;do{numroms++;for(m=0;m<8;m++){foundrom[numroms][m]=rom[m]; //identifies rom\\number on found device} printf(\nrom code =%02x%02x%02x%02x\n,foundrom[5][7],foundrom[5][6],foundrom[5][5],foundrom[5][4],foundrom[5][3],foundrom[5][2],foundrom[5][1],foundrom[5][0]);}while (next()&&(numroms return false{lastdiscrep = 0; // reset the searchreturn false;}write_byte(0xf0); // send searchrom commanddo// for all eight bytes{x = 0;if(read_bit()==1) x = 2;delay(6);if(read_bit()==1) x |= 1; // and its complementif(x ==3) // there are no devices on the 1-wirebreak;else{if(x>0) // all devices coupled have 0 or 1g = x>>1; // bit write value for searchelse{// if this discrepancy is before the last// discrepancy on a previous next then pick// the same as last timeif(m0);else // if equal to last pick 1g = (m==lastdiscrep); // if not then pick 0// if 0 was picked then record// position with mask kif (g==0) discrepmarker = m;}if(g==1) // isolate bit in rom[n] with mask krom[n] |= k;elserom[n] &= ~k;write_bit(g); // rom search writem++; // increment bit counter mk = k<<1; // and shift the bit mask kif(k==0) // if the mask is 0 then go to new rom{ // byte n and reset maskow_crc(rom[n]); // accumulate the crcn++; k++;}}}while(n<8); //loop until through all rom bytes 0-7if(m<65||dowcrc) // if search was unsuccessful thenlastdiscrep=0; // reset the last discrepancy to 0else{// search was successful, so set lastdiscrep,// lastone, nxtlastdiscrep = discrepmarker;doneflag = (lastdiscrep==0);nxt = true; // indicates search is not complete yet, more// parts remain}return nxt;} 执行循环冗余校验
循环冗余校验(crc)可以使用下面显示的功能完成,在执行搜索rom功能时应包括循环冗余校验。
//////////////////////////////////////////////////////////////////////////////// one wire crc//unsigned char ow_crc( unsigned char x){dowcrc = dscrc_table[dowcrc^x];return dowcrc;}#define false 0#define true 1////////////////////////////////////////////////////////////////////////////// global variables//unsigned char rom[8]; // rom bitunsigned char lastdiscrep = 0; // last discrepancyunsigned char doneflag = 0; // done flagunsigned char foundrom[5][8]; // table of found rom codesunsigned char numroms;unsigned char dowcrc;unsigned char code dscrc_table[] = {0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220,35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98,190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7,219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154,101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36,248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185,140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139,87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53}; 读取设备温度
如果网络上只有一个设备,则可以直接使用“读取温度”功能,如下所示。但是,如果网络上有多个设备,为了避免数据冲突,必须使用“匹配rom”功能来选择特定的设备。
下面的代码示例是专门为ds18s20温度传感器编写的。当此代码与ds18b20或ds1822配合使用时,由于温度寄存器格式的差异,必须稍作修改。有关温度寄存器格式信息,请参阅相应的数据表。
void read_temperature(void){char get[10];char temp_lsb,temp_msb;int k;char temp_f,temp_c;ow_reset();write_byte(0xcc); //skip romwrite_byte(0x44); // start conversiondelay(5);ow_reset();write_byte(0xcc); // skip romwrite_byte(0xbe); // read scratch padfor (k=0;k= 0x80) {temp_lsb = (temp_lsb/2);}// shift to get whole degreeif (temp_msb >= 0x80) {temp_lsb = ((-1)*temp_lsb);} // add sign bitprintf( \ntempc= %d degrees c\n, (int)temp_lsb ); // print temp. ctemp_c = temp_lsb; // ready for conversion to fahrenheittemp_f = (((int)temp_c)* 9)/5 + 32;printf( \ntempf= %d degrees f\n, (int)temp_f ); // print temp. f} 读取暂存器内存
暂存盘存储器为用户提供所有必要的设备数据,包括温度、th 和 tl 可编程温度计设置,以及分数温度测量中使用的计数剩余和每 c 计数数据。crc字节也包含在暂存器存储器中。
void read_scratchpad(void){int j;char pad[10];printf(\nreading scratchpad data\n);write_byte(0xbe);for (j=0;j<9;j++){pad[j]=read_byte();}printf(\n scratchpad data =%x%x%x%x%x%x\n,pad[8],pad[7],pad[6],pad[5],pad[4],pad[3],pad[2],pad[1],pad[0]);} “读取rom”命令用于在网络上只有一个设备时查找64位rom代码。多个设备需要使用“搜索rom”功能。
void read_romcode(void){int n;char dat[9];printf(\nreading rom code\n);ow_reset();write_byte(0x33);for (n=0;n<8;n++){dat[n]=read_byte();}printf(\n rom code = %x%x%x%x\n,dat[7],dat[6],dat[5],dat[4],dat[3],dat[2],dat[1],dat[0]);} “匹配rom”功能必须提供64位rom-id才能选择网络上的单个设备。


未来两到三年北京公交将试点无人驾驶公交线路
泰捷WE30C电视盒子的性能如何,老用户深度评测来袭
iPhone8将于13日凌晨1点正式发布,首次采用全面屏的苹果手机,双玻璃回归iPhone4设计
Zeux将为法币和加密货币提供安全的移动支付保障
模拟集成电路设计的一般过程
DS18X20/DS1822 1-Wire温度传感器在微控制器环境中的接口
smt自动锡膏印刷机的工作过程是怎样的
控制器厂家奥柯员工提升规划会---让勤奋常在
OLED拼接屏有哪些常用尺寸?原理、厂商、技术
工业物联网存在的意义到底是什么?
多层感知机(MLP)的设计与实现
获得可靠的传感器数据:电子、光学和机械设计之间的相互作用
更新IoT设备OTA的方法
全球最快电池摩托车
Linux驱动高精度定时器hrtimer
德州仪器针对HDMI与DisplayPort推出高灵活、八通
远程控制通讯--基于Arduino + ESP8266控制LED灯
纳米材料及纳米技术在各领域的发展趋势介绍
Mark Levinson No.33XL後級
液晶面板为什么下滑_液晶面板行业前景如何