本应用笔记为读者提供如何将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总线上的存在。1-Wire复位时序如图1所示。
当总线主控器将 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 写入和读取时隙如图 2 所示。
软件控制
为了精确控制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文章
7542浏览量
151306 -
Maxim
+关注
关注
8文章
859浏览量
87170 -
电池
+关注
关注
84文章
10559浏览量
129455
发布评论请先 登录
相关推荐
评论