本應用筆記為讀者提供如何將Maxim DS2760電池監視器和保護器IC連接至微控制器的信息。DS5000微控制器模塊用于示例目的。解決了硬件和軟件問題,包括框圖和示例C代碼,以便DS2760和微控制器之間通過Maxim 1-Wire?通信協議進行通信。該器件提供了所有常用1-Wire命令的軟件例程,因此可用于任何采用1-Wire協議進行通信的Maxim器件。此外,還提供常用電池監測功能的例程,可與其它Maxim電池監測器(如DS2761)配合使用。
介紹
將1-Wire器件連接至微控制器的過程非常簡單。本應用說明 將介紹C語言的源代碼,為用戶提供簡單的嵌入式控制器1-Wire解決方案 應用。
在下面的例子中,我們將演示一種從 微控制器向DS1K評估板讀取電壓、電流、累積電流和 溫度寄存器。DS2760K硬件用于簡化通信,因為它是一個 完整的電路,可輕松驗證源代碼。
硬件配置
本例使用DS5000(兼容8051)微控制器,工作頻率為11.059MHz。主持人 微控制器使用單線,上拉至V抄送通過一個4.7K電阻連接到DQ DS2760的輸入/輸出引腳其他微控制器可以很容易地被替換,一旦定時 已考慮到各種因素。對于一些更快的 微處理器。
接口時序
與DS2760的每個通信序列必須以1-Wire復位開始。定義復位脈沖 作為總線主控器將1-Wire總線(或DQ線)從非活動高電平狀態拉低480μs 到960μs,然后釋放它。如果總線上有1-Wire器件,它將通過將DQ線拉低來響應 以指示其在1-Wire總線上的存在。
當總線主控器將 DQ 拉低時,將啟動寫入時隙。所有寫入和讀取時隙都必須 持續時間為 60μs 至 120μs,周期之間的最短恢復時間為 1μs。在寫入“0”時間內 時隙,總線主站將在該時隙的持續時間內將線路拉低。但是,在寫入“1”期間 時隙,總線主站將線路拉低,最長15μs,如果持續<>μs,則釋放 的時間段。
當總線主控器將1-Wire總線拉低時啟動讀取時隙。線路必須保持低電平 1μs,然后釋放,使DS2760能夠控制線路并呈現有效數據。如果“0”是 DS2760放在總線上,當主機釋放數據電平時,它將保持DQ線路為低電平。如果 DS2760放置一個“1”,當總線主控釋放總線時,DQ將被允許走高。這 然后,master 將對 DQ 行進行采樣,以確定是從設備讀取“0”還是“1”。
軟件控制
為了精確控制1-Wire接口的時序要求,某些關鍵功能必須 首先要成立。創建的第一個函數必須是“延遲”函數,它是所有讀取不可或缺的函數 和寫入控制。此功能將完全取決于微控制器的速度。為此 例如,使用了工作頻率為5000.8051MHz的DS11(兼容059)微控制器。示例 下面說明了用于創建時序延遲的 C 原型函數。調用此例程需要 24μs 然后每次計數需要另外 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++); }
復位時隙為480μs,詳見下文C語言。DQ 線被拉低并保持低電平 延遲為“29”,實際上是488μs的延遲。然后,DQ 行被釋放到高狀態。延遲后 “3”,即72μs,主站對DQ線進行采樣,以查看設備是否通過拉動DQ進行響應 行低表示設備“存在”。讀取的每個位都遵循與1-Wire復位類似的順序,但沒有延遲。DQ 生產線 被拉低然后釋放,然后主控對 DQ 線進行采樣,然后返回值。當寫入一個位時,主機將線路拉低1μs(對于寫入“1”)或104μs(在本例中為a 寫“0”。讀取和寫入一個字節只是從最少的開始一個接一個地讀取或寫入 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); }
讀取網絡地址
每個DS2760都有一個唯一的64位凈地址。“讀取網絡地址”命令用于查找 64- 1-Wire總線上只有一個器件時,位網絡地址。多個設備需要使用 此處未顯示的搜索網絡地址功能。DS2760可配置為使用讀取網絡 地址為 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 }讀取實時數據
如果1線總線上有單個器件,則實時讀取電壓、電流、累積 電流和溫度可以直接使用,如下所示。如果存在 1 臺以上的設備,則匹配 必須使用網絡地址例程。所有這些功能都可以通過以下方式組合成一個例程 只需從電壓寄存器地址開始,然后繼續發出 read_byte() 命令 直到讀取所有所需的字節。
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 }讀取用戶內存
DS2760包含32字節的用戶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 }審核編輯:郭婷
-
微控制器
+關注
關注
48文章
7552瀏覽量
151423 -
保護器
+關注
關注
6文章
1022瀏覽量
33457 -
電池
+關注
關注
84文章
10576瀏覽量
129683
發布評論請先 登錄
相關推薦
評論