本應(yīng)用筆記為讀者提供如何將Maxim DS2760電池監(jiān)視器和保護(hù)器IC連接至微控制器的信息。DS5000微控制器模塊用于示例目的。解決了硬件和軟件問(wèn)題,包括框圖和示例C代碼,以便DS2760和微控制器之間通過(guò)Maxim 1-Wire?通信協(xié)議進(jìn)行通信。該器件提供了所有常用1-Wire命令的軟件例程,因此可用于任何采用1-Wire協(xié)議進(jìn)行通信的Maxim器件。此外,還提供常用電池監(jiān)測(cè)功能的例程,可與其它Maxim電池監(jiān)測(cè)器(如DS2761)配合使用。
介紹
將1-Wire器件連接至微控制器的過(guò)程非常簡(jiǎn)單。本應(yīng)用說(shuō)明 將介紹C語(yǔ)言的源代碼,為用戶提供簡(jiǎn)單的嵌入式控制器1-Wire解決方案 應(yīng)用。
在下面的例子中,我們將演示一種從 微控制器向DS1K評(píng)估板讀取電壓、電流、累積電流和 溫度寄存器。DS2760K硬件用于簡(jiǎn)化通信,因?yàn)樗且粋€(gè) 完整的電路,可輕松驗(yàn)證源代碼。
硬件配置
本例使用DS5000(兼容8051)微控制器,工作頻率為11.059MHz。主持人 微控制器使用單線,上拉至V抄送通過(guò)一個(gè)4.7K電阻連接到DQ DS2760的輸入/輸出引腳其他微控制器可以很容易地被替換,一旦定時(shí) 已考慮到各種因素。對(duì)于一些更快的 微處理器。
接口時(shí)序
與DS2760的每個(gè)通信序列必須以1-Wire復(fù)位開(kāi)始。定義復(fù)位脈沖 作為總線主控器將1-Wire總線(或DQ線)從非活動(dòng)高電平狀態(tài)拉低480μs 到960μs,然后釋放它。如果總線上有1-Wire器件,它將通過(guò)將DQ線拉低來(lái)響應(yīng) 以指示其在1-Wire總線上的存在。
當(dāng)總線主控器將 DQ 拉低時(shí),將啟動(dòng)寫入時(shí)隙。所有寫入和讀取時(shí)隙都必須 持續(xù)時(shí)間為 60μs 至 120μs,周期之間的最短恢復(fù)時(shí)間為 1μs。在寫入“0”時(shí)間內(nèi) 時(shí)隙,總線主站將在該時(shí)隙的持續(xù)時(shí)間內(nèi)將線路拉低。但是,在寫入“1”期間 時(shí)隙,總線主站將線路拉低,最長(zhǎng)15μs,如果持續(xù)<>μs,則釋放 的時(shí)間段。
當(dāng)總線主控器將1-Wire總線拉低時(shí)啟動(dòng)讀取時(shí)隙。線路必須保持低電平 1μs,然后釋放,使DS2760能夠控制線路并呈現(xiàn)有效數(shù)據(jù)。如果“0”是 DS2760放在總線上,當(dāng)主機(jī)釋放數(shù)據(jù)電平時(shí),它將保持DQ線路為低電平。如果 DS2760放置一個(gè)“1”,當(dāng)總線主控釋放總線時(shí),DQ將被允許走高。這 然后,master 將對(duì) DQ 行進(jìn)行采樣,以確定是從設(shè)備讀取“0”還是“1”。
軟件控制
為了精確控制1-Wire接口的時(shí)序要求,某些關(guān)鍵功能必須 首先要成立。創(chuàng)建的第一個(gè)函數(shù)必須是“延遲”函數(shù),它是所有讀取不可或缺的函數(shù) 和寫入控制。此功能將完全取決于微控制器的速度。為此 例如,使用了工作頻率為5000.8051MHz的DS11(兼容059)微控制器。示例 下面說(shuō)明了用于創(chuàng)建時(shí)序延遲的 C 原型函數(shù)。調(diào)用此例程需要 24μs 然后每次計(jì)數(shù)需要另外 16μs。
// DELAY - with an 11.059MHz crystal. // Calling the routine takes about 24μs, and then each count takes another 16μs. void delay(int μseconds) { int s; for (s=0; s<μseconds;s++); }
復(fù)位時(shí)隙為480μs,詳見(jiàn)下文C語(yǔ)言。DQ 線被拉低并保持低電平 延遲為“29”,實(shí)際上是488μs的延遲。然后,DQ 行被釋放到高狀態(tài)。延遲后 “3”,即72μs,主站對(duì)DQ線進(jìn)行采樣,以查看設(shè)備是否通過(guò)拉動(dòng)DQ進(jìn)行響應(yīng) 行低表示設(shè)備“存在”。讀取的每個(gè)位都遵循與1-Wire復(fù)位類似的順序,但沒(méi)有延遲。DQ 生產(chǎn)線 被拉低然后釋放,然后主控對(duì) DQ 線進(jìn)行采樣,然后返回值。當(dāng)寫入一個(gè)位時(shí),主機(jī)將線路拉低1μs(對(duì)于寫入“1”)或104μs(在本例中為a 寫“0”。讀取和寫入一個(gè)字節(jié)只是從最少的開(kāi)始一個(gè)接一個(gè)地讀取或?qū)懭?8 位 重要的位。
// OW_RESET - performs a reset on the one-wire bus and returns the presence detect. // Reset is 480μs, so delay value is (480-24)/16 = 28.5 - we use 29. // Presence checked another 70μs 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 low delay(29); // leave it low for 480μs DQ = 1; // allow line to return high delay(3); // wait for presence presence = DQ; // get presence signal delay(25); // wait for end of timeslot return(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 15μs, 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 timeslot DQ = 1; // then return high for (i=0; i<3; i++); // delay 15μs from start of timeslot return(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 timeslot if(bitval==1) DQ =1; // return DQ high if write 1 delay(5); // hold value for remainder of timeslot DQ = 1; }// Delay provides 16μs per loop, plus 24μs. Therefore delay(5) = 104μs
////////////////////////////////////////////////////////////////////////////// // 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<////////////////////////////////////////////////////////////////////////////// // WRITE_BYTE - writes a byte to the one-wire bus. // void write_byte(char val) { unsigned char i; unsigned char temp; for (i=0; i<8; i++) // writes byte, one bit at a time { temp = val>>i; // shifts val right 'i' spaces temp &= 0x01; // copy that bit to temp write_bit(temp); // write bit in temp into } delay(5); }
讀取網(wǎng)絡(luò)地址
每個(gè)DS2760都有一個(gè)唯一的64位凈地址?!白x取網(wǎng)絡(luò)地址”命令用于查找 64- 1-Wire總線上只有一個(gè)器件時(shí),位網(wǎng)絡(luò)地址。多個(gè)設(shè)備需要使用 此處未顯示的搜索網(wǎng)絡(luò)地址功能。DS2760可配置為使用讀取網(wǎng)絡(luò) 地址為 0x33h 或 0x39h。
unsigned char Read_NetAddress(void) { int n; char dat[9]; if(ow_reset()==0) //If a presence is detected, continue to read { write_byte(0x33); //Read Net Address Command (0x33h) for (n=0;n<8;n++) dat[n]=read_byte(); //Read 8 bytes of Net Address printf("\n Net Address Code %X%X%X%X\n",dat[7],dat[6],dat[5],dat[4],dat[3],dat[2],dat[1],dat[0]); return(0); //Return 0 if no error } return(1); //Return 1 if no presence detected }讀取實(shí)時(shí)數(shù)據(jù)
如果1線總線上有單個(gè)器件,則實(shí)時(shí)讀取電壓、電流、累積 電流和溫度可以直接使用,如下所示。如果存在 1 臺(tái)以上的設(shè)備,則匹配 必須使用網(wǎng)絡(luò)地址例程。所有這些功能都可以通過(guò)以下方式組合成一個(gè)例程 只需從電壓寄存器地址開(kāi)始,然后繼續(xù)發(fā)出 read_byte() 命令 直到讀取所有所需的字節(jié)。
unsigned char Read_ Voltage (void) { int lsb, msb, temp; float Voltage; //This value may be declared globally if(ow_reset()==0) //If a presence is detected, continue to read { write_byte(0xCC); // Skip Net Address Command write_byte(0x69); // Read Registers Command write_byte(0x0C); // Voltage Register Address msb = read_byte(); // Read msb lsb = read_byte() & 0xE0; // Read lsb and mask off lower 5 bits if((msb & 0x80) == 0x80) //if sign bit is set temp = (msb<<8 + lsb) - 65536; else temp = msb<<8 + lsb; Voltage = (temp>>5) * 0.00488; //Voltage in Volts printf("\nVoltage = &d", Voltage); return(0); //Return 0 if no error } return(1); //Return 1 if no presence detected } unsigned char Read_NetAddress(void) { int n; char dat[9]; if(ow_reset()==0) //If a presence is detected, continue to read { write_byte(0x33); //Read Net Address Command (0x33h) for (n=0;n<8;n++) dat[n]=read_byte(); //Read 8 bytes of Net Address printf("\n Net Address Code %X%X%X%X\n",dat[7],dat[6],dat[5],dat[4],dat[3],dat[2],dat[1],dat[0]); return(0); //Return 0 if no error } return(1); //Return 1 if no presence detected }unsigned char Read_Current (void) { int lsb, msb, temp; float Current; //This value may be declared globally if(ow_reset()==0) //If a presence is detected, continue to read { write_byte(0xCC); // Skip Net Address Command write_byte(0x69); // Read Registers Command write_byte(0x0E); //Current Register Address msb = read_byte(); // Read msb lsb = read_byte() & 0xF8; // Read lsb and mask off lower 3 bits if((msb & 0x80) == 0x80) //if sign bit is set temp = (msb<<8 + lsb) - 65536; else temp = msb<<8 + lsb; Current = (temp>>3) * 0.000015625 / .025; //Current in mAmps //assuming a 25mOhm Sense Resistor printf("\nCurrent = &d", Current); return(0); //Return 0 if no error } return(1); //Return 1 if no presence detected }unsigned char Read_ACR(void) { int lsb, msb, temp; float ACR; //This value may be declared globally if(ow_reset()==0) //If a presence is detected, continue to read { write_byte(0xCC); // Skip Net Address Command write_byte(0x69); // Read Registers Command write_byte(0x10); //ACR Register Address msb = read_byte(); // Read msb lsb = read_byte(); // Read lsb if((msb & 0x80) == 0x80) //if sign bit is set temp = (msb<<8 + lsb) - 65536; else temp = msb<<8 + lsb; ACR = temp * 0.00625 / .025; //Capacity in mAhrs //assuming a 25mOhm Sense Resistor printf("\nACR = &d", ACR); return(0); //Return 0 if no error } return(1); //Return 1 if no presence detected }unsigned char Read_Temperature(void) { int lsb, msb,temp; float temp_f,temp_c; //These values may be declared globally if(ow_reset()==0) //If a presence is detected, continue to read { write_byte(0xCC); // Skip Net Address Command write_byte(0x69); // Read Registers Command write_byte(0x18); //Temperature Register Address msb = read_byte(); // Read msb lsb = (read_byte() & 0xE0); // Read lsb, mask off lower 5 bits if((msb & 0x80) == 0x80) //if sign bit is set temp = (msb<<8 + lsb) - 65536; else temp = msb<<8 + lsb; temp_c = (temp>>5) * 0.125; //temperature in Degrees C temp_f = ((temp_c)* 9)/5 + 32; //temperature in Degrees F printf("\nTemp C = &d", temp_c); printf("\nTemp F = &d", temp_f); return(0); //Return 0 if no error } return(1); //Return 1 if no presence detected } unsigned char Read_UserMemory(void) { int j; int Memory[32]; //This value may be declared globally if(ow_reset()==0) //If a presence is detected, continue to read { write_byte(0xCC); // Skip Net Address Command write_byte(0x69); // Read Registers Command write_byte(0x20); // Block 0 Address for (j=0;j<32;j++) //Read all 32 Bytes { Memory[j]=read_byte(); printf("\n%X , " , Memory[j]); } return(0); //Return 0 if no error } return(1); //Return 1 if no presence detected }讀取用戶內(nèi)存
DS2760包含32字節(jié)的用戶EEPROM,可以使用以下代碼讀取。
unsigned char Read_UserMemory(void) { int j; int Memory[32]; //This value may be declared globally if(ow_reset()==0) //If a presence is detected, continue to read { write_byte(0xCC); // Skip Net Address Command write_byte(0x69); // Read Registers Command write_byte(0x20); // Block 0 Address for (j=0;j<32;j++) //Read all 32 Bytes { Memory[j]=read_byte(); printf("\n%X , " , Memory[j]); } return(0); //Return 0 if no error } return(1); //Return 1 if no presence detected }審核編輯:郭婷
-
微控制器
+關(guān)注
關(guān)注
48文章
7574瀏覽量
151713 -
保護(hù)器
+關(guān)注
關(guān)注
6文章
1026瀏覽量
33516 -
電池
+關(guān)注
關(guān)注
84文章
10644瀏覽量
130481
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論