引言
1-Wire網(wǎng)絡(luò)包括一個(gè)主機(jī)和一個(gè)或多個(gè)從機(jī)器件,1-Wire主機(jī)可以由微處理器的一個(gè)I/O引腳構(gòu)成,手動(dòng)產(chǎn)生定時(shí)脈沖。DS2482 I2C至1-Wire網(wǎng)絡(luò)的橋接器件可以產(chǎn)生詳細(xì)的1-Wire通信時(shí)序,無(wú)需工程師參與設(shè)計(jì)。圖1所示為DS2482配置的簡(jiǎn)化框圖。本文介紹了采用DS2482實(shí)現(xiàn)應(yīng)用程序接口(API)有效方法,支持基本的和擴(kuò)展的1-Wire操作。詳細(xì)介紹了對(duì)應(yīng)于1-Wire操作的I2C通信。這些操作為執(zhí)行當(dāng)前和未來(lái)1-Wire器件的所有功能打下了全面的基礎(chǔ),但基于DS250x系列EPROM的器件編程除外。以這種方式概要介紹1-Wire操作,適合不依賴1-Wire主機(jī)的1-Wire應(yīng)用。本文僅作為DS2482數(shù)據(jù)資料的補(bǔ)充,并不能替代數(shù)據(jù)資料。DS2482可提供兩種配置,單通道1-Wire主控制器(DS2482-100)和帶有低功耗休眠模式的1-Wire主控制器(DS2482-101),以及八通道1-Wire主控制器(DS2482-800)。
圖1. 實(shí)現(xiàn)I2C與1-Wire網(wǎng)絡(luò)通信的DS2482橋接器功能簡(jiǎn)圖
1-Wire接口
下面給出幾個(gè)基本的1-Wire函數(shù),稱之為原函數(shù),也就是為了執(zhí)行所有1-Wire操作,應(yīng)用中必須具備的函數(shù)。第一個(gè)函數(shù)(OWReset)是使網(wǎng)絡(luò)上所有1-Wire從器件復(fù)位,為接收來(lái)自1-Wire主控制器的指令做好準(zhǔn)備。第二個(gè)函數(shù)(OWWriteBit)完成1-Wire主控制器向從器件寫入一位的操作,而第三個(gè)函數(shù)(OWReadBit)完成從1-Wire從器件中讀取一位的操作。由于必須由1-Wire主控制器啟動(dòng)所有的1-Wire位通信,所以“讀取”實(shí)際上是在“寫入”一位后采樣得到的結(jié)果。幾乎所有其他1-Wire操作都可以由這三個(gè)操作構(gòu)成。例如,向1-Wire網(wǎng)絡(luò)寫1個(gè)字節(jié)相當(dāng)于8次寫一位操作。1-Wire搜索算法也可以利用相同的三個(gè)原始函數(shù)構(gòu)成。通1-Wire的三個(gè)命令,DS2482可以執(zhí)行搜索功能,大大降低了搜索操作所需的通信量。同樣,單字節(jié)的1-Wire通信命令要比八次逐位操作效率更高。
表1所示是三個(gè)基本原函數(shù)(OWReset、OWWriteBit/OWReadBit和OWWriteByte/OWReadByte)以及其它三個(gè)非常有用的函數(shù)(OWBlock、OWSearch和msDelay),它們構(gòu)成了一系列主要的基本1-Wire操作。這些操作名稱將在下文中使用。
表1. 基本的1-Wire操作
Operation | Description |
OWReset | Sends the 1-Wire reset stimulus and check for the presence pulse of 1-Wire slave devices. |
OWWriteBit/OWReadBit | Sends to or receives from the 1-Wire network a single bit of data. |
OWWriteByte/OWReadByte | Sends to or receives from the 1-Wire network a single byte of data. |
OWBlock | Sends to and receives from the 1-Wire network multiple bytes of data. |
OWSearch | Performs the 1-Wire Search Algorithm (see application note 187). |
msDelay | Delays at least the specified number of milliseconds. Used for timing strong pullup operations. |
許多1-Wire從器件可以工作在兩種不同的通信速率下:標(biāo)準(zhǔn)速率和高速模式。所有器件都支持標(biāo)準(zhǔn)速率模式。高速速率大約是標(biāo)準(zhǔn)速率的10倍。DS2482同時(shí)支持這兩種1-Wire速率。
1-Wire器件通常從1-Wire總線上獲取部分或全部工作電源。不過(guò)有些器件在協(xié)議的特定操作中需要額外供電。例如,某個(gè)器件可能需要進(jìn)行溫度轉(zhuǎn)換或執(zhí)行SHA-1散列算法。這種操作的電源是通過(guò)使能1-Wire總線的強(qiáng)上拉提供的。這種供電方式下,不能進(jìn)行正常通信。DS2482通過(guò)設(shè)置強(qiáng)上拉標(biāo)志(SPU)位供電,這將在1-Wire的下一個(gè)字節(jié)/位通信完成后啟動(dòng)強(qiáng)上拉。DS2482-100和DS2482-101還具有一個(gè)外部引腳(PCTLZ),可控制大電流強(qiáng)上拉。
表2列出了用于1-Wire速率設(shè)定、供電和編程脈沖的擴(kuò)展1-Wire操作。
表2. 擴(kuò)展的1-Wire操作
Operation | Description |
OWSpeed | Sets the 1-Wire communication speed, either standard or overdrive. Note that this only changes the communication speed of the 1-Wire master; the 1-Wire slave device must be instructed to make the switch when going from normal to overdrive. The 1-Wire slave will always revert to standard speed when it encounters a standard-speed 1-Wire reset. |
OWLevel | Sets the 1-Wire power level (normal or power delivery). |
OWReadBitPower | Reads a single bit of data from the 1-Wire network and optionally applies power delivery immediately after the bit is complete. |
OWWriteBytePower | Sends a single byte of data to the 1-Wire network and applies power delivery immediately after the byte is complete. |
主機(jī)配置
DS2482的主機(jī)應(yīng)具有一個(gè)I2C通信口,本文并沒(méi)有講述主機(jī)的配置。然而,主機(jī)必須提供標(biāo)準(zhǔn)I2C接口操作。需要注意的是,主機(jī)接口具有包含一些I2C接口操作的高級(jí)函數(shù)。所需操作請(qǐng)參考表3。表3. 所需要的I2C主機(jī)操作
Operation | Description |
I2C_start | I2C start command. |
I2C_rep_start | I2C repeated start command. |
I2C_stop | I2C stop command. |
I2C_write | Writes a byte to the I2C bus. The byte to write is passed to the function. |
I2C_read | Reads a byte from the I2C bus. The byte read is returned from the function. |
配置DS2482
在嘗試1-Wire操作之前,主機(jī)必須設(shè)置I2C至1-Wire線驅(qū)動(dòng)器DS2482,并與其同步。要與DS2482通信,主機(jī)必須知道其從地址。圖2所示為DS2482-100、DS2482-101和DS2482-800的從地址。圖2. DS2482的I2C從地址
DS2482的I2C命令
下列符號(hào)說(shuō)明來(lái)自于DS2482數(shù)據(jù)資料,以簡(jiǎn)寫符號(hào)表示,用來(lái)說(shuō)明器件的I2C通信過(guò)程。接下來(lái),我們會(huì)重復(fù)這些通信過(guò)程,并為實(shí)現(xiàn)基本的和擴(kuò)展的1-Wire操作提供附加注釋和C語(yǔ)言例程。I2C通信過(guò)程—符號(hào)說(shuō)明
Symbol | Description |
S | START Condition |
AD, 0 | Select DS2482 for Write Access |
AD, 1 | Select DS2482 for Read Access |
Sr | Repeated START Condition |
P | STOP Condition |
A | Acknowledged |
A\ | Not acknowledged |
(Idle) | Bus not busy |
Transfer of one byte | |
DRST | Command 'Device Reset', F0h |
WCFG | Command 'Write Configuration', D2h |
CHSL | Command 'Channel Select', C3h (DS2482-800 only) |
SRP | Command 'Set Read Pointer', E1h |
1WRS | Command '1-Wire Reset', B4h |
1WWB | Command '1-Wire Write Byte', A5h |
1WRB | Command '1-Wire Read Byte', 96h |
1WSB | Command '1-Wire Single Bit', 87h |
1WT | Command '1-Wire Triplet', 78h |
數(shù)據(jù)方向表示法
Master-to-Slave | Slave-to-Master |
本文中許多圖中的數(shù)據(jù)方向表示方法指出了通信方向是主機(jī)到從機(jī)(灰色),還是從機(jī)到主機(jī)(白色)。
DS2482配置操作
以下操作用于設(shè)置、配置DS2482,有些操作需要調(diào)用1-Wire操作的子程序。DS2482檢測(cè)
例1所示C程序提供檢測(cè)和配置流程,寫入DS2482的默認(rèn)值包括1-Wire速率(標(biāo)準(zhǔn))、強(qiáng)上拉(關(guān)斷)、在線脈沖屏蔽(關(guān)斷)和有源上拉(通)。該狀態(tài)保持為通用變量,如果器件需要復(fù)位到該默認(rèn)狀態(tài)可以進(jìn)行恢復(fù)。針對(duì)不同應(yīng)用可以選擇不同的默認(rèn)值。// DS2482 state unsigned char I2C_address; int c1WS, cSPU, cPPM, cAPU; int short_detected; //-------------------------------------------------------------------------- // DS2428 Detect routine that sets the I2C address and then performs a // device reset followed by writing the configuration byte to default values: // 1-Wire speed (c1WS) = standard (0) // Strong pullup (cSPU) = off (0) // Presence pulse masking (cPPM) = off (0) // Active pullup (cAPU) = on (CONFIG_APU = 0x01) // // Returns: TRUE if device was detected and written // FALSE device not detected or failure to write configuration byte // int DS2482_detect(unsigned char addr) { // set global address I2C_address = addr; // reset the DS2482 ON selected address if (!DS2482_reset()) return FALSE; // default configuration c1WS = FALSE; cSPU = FALSE; cPPM = FALSE; cAPU = CONFIG_APU; // write the default configuration setup if (!DS2482_write_config(c1WS | cSPU | cPPM | cAPU)) return FALSE; return TRUE; }例1. DS2482檢測(cè)
DS2482器件復(fù)位
圖3是DS2482器件復(fù)位I2C通信的流程。例2給出了DS2482復(fù)位命令的C程序,可實(shí)現(xiàn)器件狀態(tài)機(jī)邏輯的完全復(fù)位,并終止所有正在進(jìn)行的1-Wire通信。器件的復(fù)位命令代碼是F0h。圖3. 上電后進(jìn)行器件復(fù)位。該實(shí)例包括可選的讀訪問(wèn),以檢驗(yàn)命令是否成功執(zhí)行。
//-------------------------------------------------------------------------- // Perform a device reset on the DS2482 // // Returns: TRUE if device was reset // FALSE device not detected or failure to perform reset // int DS2482_reset() { unsigned char status; // Device Reset // S AD,0 [A] DRST [A] Sr AD,1 [A] [SS] A\ P // [] indicates from slave // SS status byte to read to verify state I2C_start(); I2C_write(I2C_address | I2C_WRITE, EXPECT_ACK); I2C_write(CMD_DRST, EXPECT_ACK); I2C_rep_start(); I2C_write(I2C_address | I2C_READ, EXPECT_ACK); status = I2C_read(NACK); I2C_stop(); // check for failure due to incorrect read back of status return ((status & 0xF7) == 0x10); }例2. 復(fù)位器件代碼
DS2482寫配置
圖4所示為DS2482寫配置的I2C通信例程;例3所示為實(shí)現(xiàn)DS2482寫配置命令時(shí)序的C程序。寫配置命令代碼為D2h。圖4. 寫配置寄存器,該實(shí)例中包括可選擇的讀操作,用于驗(yàn)證是否成功執(zhí)行命令。
//-------------------------------------------------------------------------- // Write the configuration register in the DS2482. The configuration // options are provided in the lower nibble of the provided config byte. // The uppper nibble in bitwise inverted when written to the DS2482. // // Returns: TRUE: config written and response correct // FALSE: response incorrect // int DS2482_write_config(unsigned char config) { unsigned char read_config; // Write configuration (Case A) // S AD,0 [A] WCFG [A] CF [A] Sr AD,1 [A] [CF] A\ P // [] indicates from slave // CF configuration byte to write I2C_start(); I2C_write(I2C_address | I2C_WRITE, EXPECT_ACK); I2C_write(CMD_WCFG, EXPECT_ACK); I2C_write(config | (~config << 4), EXPECT_ACK); I2C_rep_start(); I2C_write(I2C_address | I2C_READ, EXPECT_ACK); read_config = I2C_read(NACK); I2C_stop(); // check for failure due to incorrect read back if (config != read_config) { // handle error // ... DS2482_reset(); return FALSE; } return TRUE; }例3. DS2482寫配置
DS2482通道選擇
圖5所示為實(shí)現(xiàn)DS2482-800通道選擇的I2C通信實(shí)例,有效通道為0至7。注意,該操作不適合DS2482-100或DS2482-101。例4給出了執(zhí)行DS2482-800通道選擇命令的C程序,通道選擇命令碼為C3h。選擇通道后,選中通道可執(zhí)行所有1-Wire操作。圖5. 寫通道選擇寄存器,該實(shí)例中包括可選擇的讀操作,用于驗(yàn)證是否成功執(zhí)行命令。
//-------------------------------------------------------------------------- // Select the 1-Wire channel on a DS2482-800. // // Returns: TRUE if channel selected // FALSE device not detected or failure to perform select // int DS2482_channel_select(int channel) { unsigned char ch, ch_read, check; // Channel Select (Case A) // S AD,0 [A] CHSL [A] CC [A] Sr AD,1 [A] [RR] A\ P // [] indicates from slave // CC channel value // RR channel read back I2C_start(); I2C_write(I2C_address | I2C_WRITE, EXPECT_ACK); I2C_write(CMD_CHSL, EXPECT_ACK); switch (channel) { default: case 0: ch = 0xF0; ch_read = 0xB8; break; case 1: ch = 0xE1; ch_read = 0xB1; break; case 2: ch = 0xD2; ch_read = 0xAA; break; case 3: ch = 0xC3; ch_read = 0xA3; break; case 4: ch = 0xB4; ch_read = 0x9C; break; case 5: ch = 0xA5; ch_read = 0x95; break; case 6: ch = 0x96; ch_read = 0x8E; break; case 7: ch = 0x87; ch_read = 0x87; break; }; I2C_write(ch, EXPECT_ACK); I2C_rep_start(); I2C_write(I2C_address | I2C_READ, EXPECT_ACK); check = I2C_read(NACK); I2C_stop(); // check for failure due to incorrect read back of channel return (check == ch_read); }例4. DS2482-800通道選擇
DS2482的1-Wire操作
OWReset
1-Wire Reset命令(B4h)在1-Wire總線上執(zhí)行1-Wire復(fù)位和1-Wire器件在線應(yīng)答脈沖檢測(cè)。通過(guò)狀態(tài)寄存器中的在線應(yīng)答脈沖檢測(cè)(PPD)和短路檢測(cè)(SD)字段,可以采樣和報(bào)告1-Wire總線的狀態(tài)。圖6所示為1-Wire復(fù)位命令的I2C通信流程。例5為發(fā)送命令的C程序,將檢查狀態(tài)寄存器以確定在線應(yīng)答脈沖狀態(tài)。圖6. 1-Wire復(fù)位。開(kāi)始或終止1-Wire通信。連續(xù)檢測(cè)1-Wire的空閑(1WB = 0)、忙狀態(tài),直到1-Wire命令完成為止,等到1-Wire命令執(zhí)行完成,然后讀取結(jié)果。
//-------------------------------------------------------------------------- // Reset all of the devices on the 1-Wire Net and return the result. // // Returns: TRUE(1): presence pulse(s) detected, device(s) reset // FALSE(0): no presence pulses detected // int OWReset(void) { unsigned char status; int poll_count = 0; // 1-Wire reset (Case B) // S AD,0 [A] 1WRS [A] Sr AD,1 [A] [Status] A [Status] A\ P // \--------/ // Repeat until 1WB bit has changed to 0 // [] indicates from slave I2C_start(); I2C_write(I2C_address | I2C_WRITE, EXPECT_ACK); I2C_write(CMD_1WRS, EXPECT_ACK); I2C_rep_start(); I2C_write(I2C_address | I2C_READ, EXPECT_ACK); // loop checking 1WB bit for completion of 1-Wire operation // abort if poll limit reached status = I2C_read(ACK); do { status = I2C_read(status & STATUS_1WB); } while ((status & STATUS_1WB) && (poll_count++ < POLL_LIMIT)); I2C_stop(); // check for failure due to poll limit reached if (poll_count >= POLL_LIMIT) { // handle error // ... DS2482_reset(); return FALSE; } // check for short condition if (status & STATUS_SD) short_detected = TRUE; else short_detected = FALSE; // check for presence detect if (status & STATUS_PPD) return TRUE; else return FALSE; }例5. OWReset代碼
OWWriteBit/OWReadBit
1-Wire位命令(0x87)生成一個(gè)1-Wire位時(shí)隙。圖7所示是1-Wire位命令的I2C通信C程序。圖8時(shí)字節(jié)的位分配,V是發(fā)送位。例6給出了OWWriteBit、OWReadBit和OWTouchBit程序。圖7. 1-Wire位,在1-Wire總線上生成一個(gè)時(shí)隙,當(dāng)1WB從1變?yōu)?時(shí),狀態(tài)寄存器保持1-Wire位命令的有效結(jié)果。
圖8. 1-Wire的一個(gè)數(shù)據(jù)字節(jié)
//-------------------------------------------------------------------------- // Send 1 bit of communication to the 1-Wire Net. // The parameter 'sendbit' least significant bit is used. // // 'sendbit' - 1 bit to send (least significant byte) // void OWWriteBit(unsigned char sendbit) { OWTouchBit(sendbit); } //-------------------------------------------------------------------------- // Reads 1 bit of communication from the 1-Wire Net and returns the // result // // Returns: 1 bit read from 1-Wire Net // unsigned char OWReadBit(void) { return OWTouchBit(0x01); } //-------------------------------------------------------------------------- // Send 1 bit of communication to the 1-Wire Net and return the // result 1 bit read from the 1-Wire Net. The parameter 'sendbit' // least significant bit is used and the least significant bit // of the result is the return bit. // // 'sendbit' - the least significant bit is the bit to send // // Returns: 0: 0 bit read from sendbit // 1: 1 bit read from sendbit // unsigned char OWTouchBit(unsigned char sendbit) { unsigned char status; int poll_count = 0; // 1-Wire bit (Case B) // S AD,0 [A] 1WSB [A] BB [A] Sr AD,1 [A] [Status] A [Status] A\ P // \--------/ // Repeat until 1WB bit has changed to 0 // [] indicates from slave // BB indicates byte containing bit value in msbit I2C_start(); I2C_write(I2C_address | I2C_WRITE, EXPECT_ACK); I2C_write(CMD_1WSB, EXPECT_ACK); I2C_write(sendbit ? 0x80 : 0x00, EXPECT_ACK); I2C_rep_start(); I2C_write(I2C_address | I2C_READ, EXPECT_ACK); // loop checking 1WB bit for completion of 1-Wire operation // abort if poll limit reached status = I2C_read(ACK); do { status = I2C_read(status & STATUS_1WB); } while ((status & STATUS_1WB) && (poll_count++ < POLL_LIMIT)); I2C_stop(); // check for failure due to poll limit reached if (poll_count >= POLL_LIMIT) { // handle error // ... DS2482_reset(); return 0; } // return bit state if (status & STATUS_SBR) return 1; else return 0; }例6. 1-Wire位命令
OWWriteByte
1-Wire寫字節(jié)命令(A5h)向1-Wire總線寫入單個(gè)數(shù)據(jù)字節(jié)。在DS2482執(zhí)行該命令之前,必須結(jié)束1-Wire的工作狀態(tài)。圖9所示為通過(guò)I2C寫1-Wire字節(jié)的情況。例7中的程序在從該操作返回前檢查1-Wire是否完成有效的操作。圖9. 1-Wire寫字節(jié)。向1-Wire總線發(fā)送命令代碼。當(dāng)1WB從1變?yōu)?時(shí),完成1-Wire寫字節(jié)命令。
//-------------------------------------------------------------------------- // Send 8 bits of communication to the 1-Wire Net and verify that the // 8 bits read from the 1-Wire Net are the same (write operation). // The parameter 'sendbyte' least significant 8 bits are used. // // 'sendbyte' - 8 bits to send (least significant byte) // // Returns: TRUE: bytes written and echo was the same // FALSE: echo was not the same // void OWWriteByte(unsigned char sendbyte) { unsigned char status; int poll_count = 0; // 1-Wire Write Byte (Case B) // S AD,0 [A] 1WWB [A] DD [A] Sr AD,1 [A] [Status] A [Status] A\ P // \--------/ // Repeat until 1WB bit has changed to 0 // [] indicates from slave // DD data to write I2C_start(); I2C_write(I2C_address | I2C_WRITE, EXPECT_ACK); I2C_write(CMD_1WWB, EXPECT_ACK); I2C_write(sendbyte, EXPECT_ACK); I2C_rep_start(); I2C_write(I2C_address | I2C_READ, EXPECT_ACK); // loop checking 1WB bit for completion of 1-Wire operation // abort if poll limit reached status = I2C_read(ACK); do { status = I2C_read(status & STATUS_1WB); } while ((status & STATUS_1WB) && (poll_count++ < POLL_LIMIT)); I2C_stop(); // check for failure due to poll limit reached if (poll_count >= POLL_LIMIT) { // handle error // ... DS2482_reset(); } }例7. OWWriteByte程序
OWReadByte
1-Wire讀字節(jié)命令(96h)從1-Wire網(wǎng)絡(luò)讀取單個(gè)數(shù)據(jù)字節(jié)。在DS2482執(zhí)行該命令之前,必須等1-Wire的工作狀態(tài)結(jié)束。圖10所示為I2C通信流程,1-Wire讀字節(jié)命令程序如例8。發(fā)送讀字節(jié)命令之前,必須檢查1-Wire的工作狀態(tài)是否結(jié)束。圖10. 1-Wire讀字節(jié)。從1-Wire總線上讀取一個(gè)字節(jié)。連續(xù)檢測(cè)狀態(tài)寄存器直到1WB位從1變?yōu)?。然后設(shè)置讀指針指向讀數(shù)據(jù)寄存器(代碼E1h),并再次訪問(wèn)該器件,讀取從1-Wire總線上得到的數(shù)據(jù)字節(jié)。
//-------------------------------------------------------------------------- // Send 8 bits of read communication to the 1-Wire Net and return the // result 8 bits read from the 1-Wire Net. // // Returns: 8 bits read from 1-Wire Net // unsigned char OWReadByte(void) { unsigned char data, status; int poll_count = 0; // 1-Wire Read Bytes (Case C) // S AD,0 [A] 1WRB [A] Sr AD,1 [A] [Status] A [Status] A\ // \--------/ // Repeat until 1WB bit has changed to 0 // Sr AD,0 [A] SRP [A] E1 [A] Sr AD,1 [A] DD A\ P // // [] indicates from slave // DD data read I2C_start(); I2C_write(I2C_address | I2C_WRITE, EXPECT_ACK); I2C_write(CMD_1WRB, EXPECT_ACK); I2C_rep_start(); I2C_write(I2C_address | I2C_READ, EXPECT_ACK); // loop checking 1WB bit for completion of 1-Wire operation // abort if poll limit reached status = I2C_read(ACK); do { status = I2C_read(status & STATUS_1WB); } while ((status & STATUS_1WB) && (poll_count++ < POLL_LIMIT)); // check for failure due to poll limit reached if (poll_count >= POLL_LIMIT) { // handle error // ... DS2482_reset(); return 0; } I2C_rep_start(); I2C_write(I2C_address | I2C_WRITE, EXPECT_ACK); I2C_write(CMD_SRP, EXPECT_ACK); I2C_write(0xE1, EXPECT_ACK); I2C_rep_start(); I2C_write(I2C_address | I2C_READ, EXPECT_ACK); data = I2C_read(NACK); I2C_stop(); return data; }例8. OWReadByte程序
OWBlock
OWBlock用于執(zhí)行一組1-Wire字節(jié)操作,對(duì)于1-Wire網(wǎng)絡(luò)的數(shù)據(jù)塊傳輸非常有用。例9所示為OWBlock例程。//-------------------------------------------------------------------------- // The 'OWBlock' transfers a block of data to and from the // 1-Wire Net. The result is returned in the same buffer. // // 'tran_buf' - pointer to a block of unsigned // chars of length 'tran_len' that will be sent // to the 1-Wire Net // 'tran_len' - length in bytes to transfer // void OWBlock(unsigned char *tran_buf, int tran_len) { int i; for (i = 0; i < tran_len; i++) tran_buf[i] = OWTouchByte(tran_buf[i]); } //-------------------------------------------------------------------------- // Send 8 bits of communication to the 1-Wire Net and return the // result 8 bits read from the 1-Wire Net. The parameter 'sendbyte' // least significant 8 bits are used and the least significant 8 bits // of the result are the return byte. // // 'sendbyte' - 8 bits to send (least significant byte) // // Returns: 8 bits read from sendbyte // unsigned char OWTouchByte(unsigned char sendbyte) { if (sendbyte == 0xFF) return OWReadByte(); else { OWWriteByte(sendbyte); return sendbyte; } }例9. OWBlock程序
OWSearch/1-Wire的三合一命令
1-Wire搜索命令用于搜索1-Wire網(wǎng)絡(luò)中每個(gè)器件唯一的64位注冊(cè)碼,這個(gè)唯一的注冊(cè)碼通常在數(shù)據(jù)資料中用ROM碼表示,因?yàn)樗鎯?chǔ)在只讀存儲(chǔ)器。搜索從1-Wire復(fù)位開(kāi)始,隨后是搜索命令。所有1-Wire器件應(yīng)答的搜索命令是F0h。搜索命令之后,1-Wire主機(jī)將進(jìn)行二叉樹(shù)搜索,找到一個(gè)器件。二叉樹(shù)搜索通過(guò)以下操作判斷64位的每一位:首先讀一位,讀取該位的補(bǔ)碼,然后寫入一位以確定留在搜索中的器件。這三個(gè)單獨(dú)的位操作時(shí)序稱為三合一操作。DS2482帶有一個(gè)簡(jiǎn)短命令,利用該三合一命令可以更高效地執(zhí)行1-Wire搜索。三合一命令(78h)可在1-Wire總線上產(chǎn)生3個(gè)時(shí)隙,其中包括兩個(gè)讀時(shí)隙和一個(gè)寫時(shí)隙。狀態(tài)寄存器中的方向字節(jié)(DIR)決定了寫時(shí)隙的類型(圖11)。例10介紹了完整的1-Wire搜索過(guò)程,采用1-Wire三合一命令。調(diào)用OWFirst,然后重復(fù)調(diào)用OWNext,可以查找到1-Wire網(wǎng)絡(luò)的所有器件。有關(guān)1-Wire搜索算法的詳細(xì)介紹請(qǐng)參考應(yīng)用筆記187,“1-Wire搜索算法”。
圖11. 1-Wire三合一命令,在1-Wire總線上實(shí)現(xiàn)搜索ROM功能。完成該1-Wire功能需要空閑時(shí)間。然后在讀模式下訪問(wèn)器件,通過(guò)1-Wire三合一命令得到結(jié)果。
// Search state unsigned char ROM_NO[8]; int LastDiscrepancy; int LastFamilyDiscrepancy; int LastDeviceFlag; unsigned char crc8; //-------------------------------------------------------------------------- // Find the 'first' devices on the 1-Wire network // Return TRUE : device found, ROM number in ROM_NO buffer // FALSE : no device present // int OWFirst() { // reset the search state LastDiscrepancy = 0; LastDeviceFlag = FALSE; LastFamilyDiscrepancy = 0; return OWSearch(); } //-------------------------------------------------------------------------- // Find the 'next' devices on the 1-Wire network // Return TRUE : device found, ROM number in ROM_NO buffer // FALSE : device not found, end of search // int OWNext() { // leave the search state alone return OWSearch(); } //-------------------------------------------------------------------------- // The 'OWSearch' function does a general search. This function // continues from the previous search state. The search state // can be reset by using the 'OWFirst' function. // This function contains one parameter 'alarm_only'. // When 'alarm_only' is TRUE (1) the find alarm command // 0xEC is sent instead of the normal search command 0xF0. // Using the find alarm command 0xEC will limit the search to only // 1-Wire devices that are in an 'alarm' state. // // Returns: TRUE (1) : when a 1-Wire device was found and its // Serial Number placed in the global ROM // FALSE (0): when no new device was found. Either the // last search was the last device or there // are no devices on the 1-Wire Net. // int OWSearch() { int id_bit_number; int last_zero, rom_byte_number, search_result; int id_bit, cmp_id_bit; unsigned char rom_byte_mask, search_direction, status; // initialize for search id_bit_number = 1; last_zero = 0; rom_byte_number = 0; rom_byte_mask = 1; search_result = FALSE; crc8 = 0; // if the last call was not the last one if (!LastDeviceFlag) { // 1-Wire reset if (!OWReset()) { // reset the search LastDiscrepancy = 0; LastDeviceFlag = FALSE; LastFamilyDiscrepancy = 0; return FALSE; } // issue the search command OWWriteByte(0xF0); // loop to do the search do { // if this discrepancy if before the Last Discrepancy // on a previous next then pick the same as last time if (id_bit_number < LastDiscrepancy) { if ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0) search_direction = 1; else search_direction = 0; } else { // if equal to last pick 1, if not then pick 0 if (id_bit_number == LastDiscrepancy) search_direction = 1; else search_direction = 0; } // Perform a triple operation on the DS2482 which will perform // 2 read bits and 1 write bit status = DS2482_search_triplet(search_direction); // check bit results in status byte id_bit = ((status & STATUS_SBR) == STATUS_SBR); cmp_id_bit = ((status & STATUS_TSB) == STATUS_TSB); search_direction = ((status & STATUS_DIR) == STATUS_DIR) ? (byte)1 : (byte)0; // check for no devices on 1-Wire if ((id_bit) && (cmp_id_bit)) break; else { if ((!id_bit) && (!cmp_id_bit) && (search_direction == 0)) { last_zero = id_bit_number; // check for Last discrepancy in family if (last_zero < 9) LastFamilyDiscrepancy = last_zero; } // set or clear the bit in the ROM byte rom_byte_number // with mask rom_byte_mask if (search_direction == 1) ROM_NO[rom_byte_number] |= rom_byte_mask; else ROM_NO[rom_byte_number] &= (byte)~rom_byte_mask; // increment the byte counter id_bit_number // and shift the mask rom_byte_mask id_bit_number++; rom_byte_mask <<= 1; // if the mask is 0 then go to new SerialNum byte rom_byte_number // and reset mask if (rom_byte_mask == 0) { calc_crc8(ROM_NO[rom_byte_number]); // accumulate the CRC rom_byte_number++; rom_byte_mask = 1; } } } while(rom_byte_number < 8); // loop until through all ROM bytes 0-7 // if the search was successful then if (!((id_bit_number < 65) || (crc8 != 0))) { // search successful so set LastDiscrepancy,LastDeviceFlag // search_result LastDiscrepancy = last_zero; // check for last device if (LastDiscrepancy == 0) LastDeviceFlag = TRUE; search_result = TRUE; } } // if no device found then reset counters so next // 'search' will be like a first if (!search_result || (ROM_NO[0] == 0)) { LastDiscrepancy = 0; LastDeviceFlag = FALSE; LastFamilyDiscrepancy = 0; search_result = FALSE; } return search_result; } //-------------------------------------------------------------------------- // Use the DS2482 help command '1-Wire triplet' to perform one bit of a //1-Wire search. //This command does two read bits and one write bit. The write bit // is either the default direction (all device have same bit) or in case of // a discrepancy, the 'search_direction' parameter is used. // // Returns – The DS2482 status byte result from the triplet command // unsigned char DS2482_search_triplet(int search_direction) { unsigned char status; int poll_count = 0; // 1-Wire Triplet (Case B) // S AD,0 [A] 1WT [A] SS [A] Sr AD,1 [A] [Status] A [Status] A\ P // \--------/ // Repeat until 1WB bit has changed to 0 // [] indicates from slave // SS indicates byte containing search direction bit value in msbit I2C_start(); I2C_write(I2C_address | I2C_WRITE, EXPECT_ACK); I2C_write(CMD_1WT, EXPECT_ACK); I2C_write(search_direction ? 0x80 : 0x00, EXPECT_ACK); I2C_rep_start(); I2C_write(I2C_address | I2C_READ, EXPECT_ACK); // loop checking 1WB bit for completion of 1-Wire operation // abort if poll limit reached status = I2C_read(ACK); do { status = I2C_read(status & STATUS_1WB); } while ((status & STATUS_1WB) && (poll_count++ < POLL_LIMIT)); I2C_stop(); // check for failure due to poll limit reached if (poll_count >= POLL_LIMIT) { // handle error // ... DS2482_reset(); return 0; } // return status byte return status; }例10. OWSearch程序
擴(kuò)展的1-Wire工作模式
OWSpeed
例11給出了如何用DS2482改變1-Wire總線速率的例程,所有1-Wire器件默認(rèn)工作在標(biāo)準(zhǔn)通信速率,有些器件可以通過(guò)Overdrive-Match-ROM或Overdrive-Skip-ROM命令轉(zhuǎn)移到高速工作模式。一旦器件工作在高速模式,所有1-Wire通信將采用高速時(shí)序。標(biāo)準(zhǔn)速率的1-Wire復(fù)位命令將使所有器件恢復(fù)到標(biāo)準(zhǔn)速率。//-------------------------------------------------------------------------- // Set the 1-Wire Net communication speed. // // 'new_speed' - new speed defined as // MODE_STANDARD 0x00 // MODE_OVERDRIVE 0x01 // // Returns: current 1-Wire Net speed // int OWSpeed(int new_speed) { // set the speed if (new_speed == MODE_OVERDRIVE) c1WS = CONFIG_1WS; else c1WS = FALSE; // write the new config DS2482_write_config(c1WS | cSPU | cPPM | cAPU); return new_speed; }例11. OWSpeed程序
OWLevel
例12給出了如何用DS2482改變1-Wire總線電平的程序,DS2482可以在執(zhí)行一次位或字節(jié)通信后使能強(qiáng)上拉。隨后,OWLevel程序?qū)?-Wire網(wǎng)絡(luò)返回到標(biāo)準(zhǔn)上拉,利用OWWriteBytePower或OWReadBitPower操作使能強(qiáng)上拉。//-------------------------------------------------------------------------- // Set the 1-Wire Net line level pullup to normal. The DS2482 only // allows enabling strong pullup on a bit or byte event. Consequently this // function only allows the MODE_STANDARD argument. To enable strong pullup // use OWWriteBytePower or OWReadBitPower. // // 'new_level' - new level defined as // MODE_STANDARD 0x00 // // Returns: current 1-Wire Net level // int OWLevel(int new_level) { // function only will turn back to non-strong pullup if (new_level != MODE_STANDARD) return MODE_STRONG; // clear the strong pullup bit in the global config state cSPU = FALSE; // write the new config DS2482_write_config(c1WS | cSPU | cPPM | cAPU); return MODE_STANDARD; }例12. OWLevel程序
OWReadBitPower
例13是OWReadBitPower所使用的程序,用于讀取一個(gè)1-Wire位并執(zhí)行供電功能。當(dāng)配置寄存器中的強(qiáng)上拉(SPU)位使能時(shí),在下一位或字節(jié)通信完成后,DS2482將有源拉高1-Wire總線。該操作可通過(guò)是否獲得相應(yīng)的響應(yīng)來(lái)驗(yàn)證讀位的正確性,如果響應(yīng)不正確,1-Wire電平將返回到標(biāo)準(zhǔn)的上拉狀態(tài)。//-------------------------------------------------------------------------- // Send 1 bit of communication to the 1-Wire Net and verify that the // response matches the 'applyPowerResponse' bit and apply power delivery // to the 1-Wire net. Note that some implementations may apply the power // first and then turn it off if the response is incorrect. // // 'applyPowerResponse' - 1 bit response to check, if correct then start // power delivery // // Returns: TRUE: bit written and response correct, strong pullup now on // FALSE: response incorrect // int OWReadBitPower(int applyPowerResponse) { unsigned char rdbit; // set strong pullup enable cSPU = CONFIG_SPU; // write the new config if (!DS2482_write_config(c1WS | cSPU | cPPM | cAPU)) return FALSE; // perform read bit rdbit = OWReadBit(); // check if response was correct, if not then turn off strong pullup if (rdbit != applyPowerResponse) { OWLevel(MODE_STANDARD); return FALSE; } return TRUE; }例13. OWReadBitPower程序
OWWriteBytePower
例14為OWWriteBytePower所采用的程序,用于寫入1-Wire字節(jié)并執(zhí)行強(qiáng)上拉供電功能。當(dāng)配置寄存器中的強(qiáng)上拉(SPU)位使能時(shí),在下一位或字節(jié)通信完成后,DS2482將由源拉高1-Wire總線。//-------------------------------------------------------------------------- // Send 8 bits of communication to the 1-Wire Net and verify that the // 8 bits read from the 1-Wire Net are the same (write operation). // The parameter 'sendbyte' least significant 8 bits are used. After the // 8 bits are sent change the level of the 1-Wire net. // // 'sendbyte' - 8 bits to send (least significant bit) // // Returns: TRUE: bytes written and echo was the same, strong pullup now on // FALSE: echo was not the same // int OWWriteBytePower(int sendbyte) { // set strong pullup enable cSPU = CONFIG_SU; // write the new config if (!DS2482_write_config(c1WS | cSPU | cPPM | cAPU)) return FALSE; // perform write byte OWWriteByte(sendbyte); return TRUE; }例14. OWWriteBytePower程序
評(píng)論
查看更多