DS2760 1-Wire高精度锂离子电池监视和保护IC在微控制器环境中的接口

描述

本应用笔记为读者提供如何将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
}

审核编辑:郭婷


打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分