love萍萍 发表于 2015-6-13 13:29:38

DS2438测量电压是比较接近,但电流和剩余容量不准

本帖最后由 love萍萍 于 2015-6-12 23:15 编辑

利用MSP430F5438A和DS2438做一电池监测电路,电路如下图所示:

图中VCC是用MSP430板子的3.3V供电.
数据能够读出,电压基本上准的,但是测量电池电流的时候测出来是4.99A,电池容量是0.0。明显不对了,请问是哪的问题是我硬件有问题吗?
下面是我参考网上例程改写的程序

ds2438.h
#ifndef _DS2438_H_
#define _DS2438_H_

#define CPU_F         ((double)8000000)
#define delay_us(x)   __delay_cycles((long)(CPU_F*(double)x/1000000.0))
#define delay_ms(x)   __delay_cycles((long)(CPU_F*(double)x/1000.0))

#define SKIP_ROM0xCC                   //跳过ROM选择步骤
#define CONVERT_V0xB4                   //启用电压转换功能
#define RECALL   0xB8                        //重调EEPROM
#define READ_SP0xBE                        //读暂存器
#define WRITE_SP0x4E                        //写暂存器
#define COPY_SP   0x48                        //复制暂存器

#define        DQ_PxDIR                        P5DIR
#define        DQ_PxIN                                P5IN
#define        DQ_PxOUT                        P5OUT
#define        DQ                                        BIT5                                       
//高低电平定义
#define        DQ_IN()                                DQ_PxDIR         &=         ~DQ
#define        DQ_OUT()                        DQ_PxDIR        |=        DQ
#define        DQ_OUTH()                        DQ_PxOUT |= DQ
#define        DQ_OUTL()                        DQ_PxOUT &= ~DQ
#define DQ_IN_HL()          DQ_PxIN & DQ

#defineR    0.050

void OWWritebit(unsigned char bit);
unsigned char OWReadbit(void);
void OWWriteByte(unsigned char data);
unsigned char OWReadByte(void);
unsigned char OWReset(void);
void initcommand(void);
float Read_Current(void);
float Read_Temperature(void);
float Read_Voltage(void);
float Read_ICAcurrent(void);
float Read_CCAcurrent(void);
float Read_DCAcurrent(void);

#endif
//ds2438.c
#include "msp430f5438a.h"
#include "math.h"
#include "ds2438.h"
void OWWritebit(unsigned char bit)
{
    if(bit)
    {//write bit 1
      DQ_OUTL();
      delay_us(6);
      DQ_OUTH();
      delay_us(64);
    }   
    else
    {//write bit 0
      DQ_OUTL();
      delay_us(60);
      DQ_OUTH();
      delay_us(10);
    }
}
unsigned char OWReadbit(void)
{
    unsigned char result;
    DQ_OUTL();
    delay_us(6);
    DQ_OUTH();
    DQ_IN();
        delay_us(9);
        result= DQ_PxIN & DQ;
    delay_us(55);
      
    return result;
}
void OWWriteByte(unsigned char data)
{
    unsigned char loop,i;
    DQ_OUT();
    for(loop=0;loop<8;loop++)
    {
      
      i=data&0x01;
      if(i)
      {
            DQ_OUTL();
            delay_us(6);
            DQ_OUTH();
            delay_us(64);            
      }
      else
      {
            DQ_OUTL();
            delay_us(60);
            DQ_OUTH();
            delay_us(10);
      }
      data=data>>1;
    }
}
unsigned char OWReadByte(void)
{
    unsigned char count, temp;
    unsigned char result=0;
    for(count=0;count<8;count++)
    {
      // shift the result to get it ready for the next bit
      DQ_OUT();
      DQ_OUTL();
      delay_us(6);
      DQ_OUTH();
                DQ_IN();
      delay_us(9);
      
      temp= DQ_PxIN & DQ;
                if(temp!=0x00)
                        result |=0x80;
      if(count<7)
                        result=result>>1;
                delay_us(55);
                DQ_OUT();
      //DQ_OUTH();
                //delay_us(10); // Complete the time slot and 10us recovery
    }
    return result;
}
//复位函数
unsigned char OWReset(void)
{
    unsigned char presence;
    DQ_OUT();
    DQ_OUTL();
    delay_us(480);   // leave it low for 480us
    //delay_us(226);
    //DQ_OUTH();
    DQ_IN();
    delay_us(70);   //leave it low for 45us
   
    presence = DQ_PxIN & DQ;
    //presence &= DQ;
    delay_us(410); // wait for end of timeslot240u
    DQ_OUT();
    //delay_us(170);
    return presence;
} // 0=presence, 1 = no part
void initcommand(void)
{   
    unsigned char c;
    unsigned char i,j;
    unsigned char rebit;
    i=OWReset();
    while(i==0x20);
    OWWriteByte(0xCC); // Skip ROM
    OWWriteByte(0x4E); // Write Scratchpad
    OWWriteByte(0x00); // Write Page
    OWWriteByte(0x07); // Write Cortrol
    i=OWReset();
    while(i==0x20);
    OWWriteByte(0xCC); // Skip ROM
    OWWriteByte(0xBE); // Read Scratchpad
    OWWriteByte(0x00); // Read 0th Page
    for(j=0;j<9;j++)
    {
      c=OWReadByte();
    }
    i=OWReset();
    while(i==0x20);
    OWWriteByte(0xCC); // Skip ROM
    OWWriteByte(0x48); // Read Scratch Pad to Memory
    OWWriteByte(0x00); // Copy 0th Page
    rebit=OWReadbit();
    i=OWReset();
    while(i==0x20);
    delay_ms(20);
}
//读当前电流
float Read_Current(void)
{         
    unsigned char c;
    unsigned char i,j;
    float n;
    //initcommand();
    i=OWReset();
    while(i==0x20);
    OWWriteByte(0xCC); // Skip ROM
    OWWriteByte(0xB8); // Read Scratchpad
    OWWriteByte(0x00); // Read 0th Page
    i=OWReset();
    while(i==0x20);
    OWWriteByte(0xCC); // Skip ROM
    OWWriteByte(0xBE); // Read Scratchpad
    OWWriteByte(0x00); // Read 0th Page
    for(j=0;j<9;j++)
    {
      c=OWReadByte();
    }
    n=((c&0x03)*256+c)/(4096*R);
    return (n);
}
//读取当前电池温度
float Read_Temperature(void)
{
    unsigned char g;
    unsigned char i,j;
    float u;
    i=OWReset();
    while(i==0x20);
    OWWriteByte(0xCC); //Skip ROM
    OWWriteByte(0x44); // Start Conversion
    delay_ms(20);
    i=OWReset();
    while(i==0x20);
    OWWriteByte(0xCC); // Skip ROM
    OWWriteByte(0xB8); //READ SCRATCHPAD
    OWWriteByte(0x00); //READ 0TH PAGE
    i=OWReset();
    while(i==0x20);
    OWWriteByte(0xCC); // Skip ROM
    OWWriteByte(0xBE); // Read Scratch Pad
    OWWriteByte(0x00);
    for(j=0;j<9;j++)
    {
      g=OWReadByte();
    }
    u=((g&0x7f)*256+g)*0.03125;
    return (u);
}
//读取电压转换值
float Read_Voltage(void)
{      
    unsigned char b;
    unsigned char i,j,p,q;
    float m;
    i=OWReset();
    while(i==0x20);
    OWWriteByte(0xCC); // Skip ROM
    OWWriteByte(0xB4); //WRITE VOLTAGE CORTROL
    delay_ms(20);
    i=OWReset();
    while(i==0x20);
    OWWriteByte(0xCC); // Skip ROM
    OWWriteByte(0xB8); //READ SCRATCHPAD
    OWWriteByte(0x00); //READ 0TH PAGE
    i=OWReset();
    while(i==0x20);         
    OWWriteByte(0xCC); // Skip ROM
    OWWriteByte(0xBE); //READ SCRATCHPAD
    OWWriteByte(0x00); //READ 0TH PAGE
    for(j=0;j<9;j++)
    {
      b=OWReadByte();
    }
    m=((b&0x03)*256+b)*0.01;
    return (m);
}
//读电池的当前剩余容量
float Read_ICAcurrent(void)
{      
    unsigned char d;
    unsigned char i,j;
    float p;
   
    i=OWReset();
    while(i==0x20);
    OWWriteByte(0xCC); // Skip ROM
    OWWriteByte(0xBE);
    OWWriteByte(0x01);
    for(j=0;j<9;j++)
    {
      d=OWReadByte();
    }
    p=(float)d/(2048*R);
    return (p);
}
//读电池的充电累计容量
float Read_CCAcurrent(void)
{
    unsigned char a;
    unsigned char e;
    unsigned char i,j;
    float q;
   
    i=OWReset();
    while(i==0x20);
    OWWriteByte(0xCC); // Skip ROM
    OWWriteByte(0xB8); //READ SCRATCHPAD
    OWWriteByte(0x07); //READ 07TH PAGE
    i=OWReset();
    while(i==0x20);
    OWWriteByte(0xCC); // Skip ROM
    OWWriteByte(0xBE);
    OWWriteByte(0x07);
    for(j=0;j<9;j++)
    {
      e=OWReadByte();
    }
    q = (e*256+e)*0.015625;
    return (q);
}
//读电池的累计放电容量
float Read_DCAcurrent(void)
{   
    unsigned char a;
    unsigned char f;
    unsigned char i,j;
    float t;
      
    i=OWReset();
    while(i==0x20);
    OWWriteByte(0xCC); // Skip ROM
    OWWriteByte(0xB8); //READ SCRATCHPAD
    OWWriteByte(0x07); //READ 07TH PAGE
    i=OWReset();
    while(i==0x20);
    OWWriteByte(0xCC); // Skip ROM
    OWWriteByte(0xBE);
    OWWriteByte(0x07);
    for(j=0;j<9;j++)
    {
      f=OWReadByte();
    }
    t=(f*256+f)*0.015625;
    return (t);

}
main.c
#include "msp430f5438a.h"
#include "ds2438.h"
void Init_GPIO(void);
void Init_Clock(void);

void main( void )
{
    float A,B,J,D,E,F;
    float H,I;
    // Stop watchdog timer to prevent time out reset
    WDTCTL = WDTPW + WDTHOLD;
    Init_GPIO();
    Init_Clock();
    initcommand();             //初始化函数的一些值
    while(1)
    {
      A=Read_Current();          //读当前电流值   
      A=Read_Current();          //读当前电流值
      A=Read_Current();          //读当前电流值   
      B=Read_Temperature();//读当前电池壳体的表面的温度
      B=Read_Temperature();//读当前电池壳体的表面的温度   
      J=Read_Voltage();          //读当前电池的电压值
      J=Read_Voltage();          //读当前电池的电压值
      J=Read_Voltage();          //读当前电池的电压值         
      D=Read_ICAcurrent();      //读当前电池的容量值
      D=Read_ICAcurrent();      //读当前电池的容量值
      D=Read_ICAcurrent();      //读当前电池的容量值
      E=Read_CCAcurrent();      //读当前充电电流的累计值
      E=Read_CCAcurrent();      //读当前充电电流的累计值
      E=Read_CCAcurrent();      //读当前充电电流的累计值
      F=Read_DCAcurrent();      //读当前电池放电电流的累计值
      F=Read_DCAcurrent();      //读当前电池放电电流的累计值
      F=Read_DCAcurrent();      //读当前电池放电电流的累计值
      H=D/1600;                  //当前电池的容量的百分比
      I=D/A;                     //电池还能使用多常时间   
    }
}
void Init_GPIO(void)
{
        // set all portsto low on all pins
        P1OUT         =         0x00;
        P1DIR         =        0xD7;
        P2OUT        =         0x00;
        P2DIR        &=        0x77;
        P3OUT        =         0x00;
        P3DIR        |=        0xDB;
    P4OUT   =   0X00;
    P4DIR   |=0XFF;
    P5OUT   =   0X00;
    P5DIR   |=0X63;   
    P6OUT   =   0x00;
    P6DIR   |=0xFF;
    P7OUT   =   0x00;
    P7DIR   |=0xFC;
    P8OUT   =   0x00;
    P8DIR   |=0xFF;
    P9OUT   =   0x00;
    P9DIR   |=0xDB;
    P10OUT   =   0x00;
    P10DIR   |=0xDD;
   
    P3OUT   |= BIT0;
    P4OUT   |= BIT0;
    //P5OUT   |= BIT5;
    P6OUT   |= BIT4;
    P9OUT   |= BIT0;   
}
/*系统时钟初始化SMCLK = MCLK = XT2 ACLK=XT1 */
void Init_Clock(void)
{
        //XT1
        P7SEL |= BIT0 + BIT1;        // Select XT1
        UCSCTL6 &= ~(XT1OFF);        // XT1 On
        UCSCTL6 |= XCAP_3;         // Internal load cap
        //XT2
        P5SEL |= BIT2 + BIT3;//select XT2
        UCSCTL6 &= ~XT2OFF;
        UCSCTL3   |= SELREF_2;        // FLLref = REFO
        UCSCTL4   |= SELA_2;        // ACLK=REFO,SMCLK=DCO,MCLK=DCO
        do
        {
                UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG); // 清除 XT2,XT1,DCO 错误标志                                                         
                SFRIFG1 &= ~OFIFG;
       }while(SFRIFG1&OFIFG);        // 检测振荡器错误标志
        UCSCTL6   &= ~XT2DRIVE0;
        UCSCTL4   |= SELA_0+SELS_5 + SELM_5;        // SMCLK = MCLK = XT2 ACLK=XT1
}

liufabing 发表于 2015-6-13 14:09:24

是否需要经过一个学习的过程.
电量是累加的数据.

love萍萍 发表于 2015-6-13 14:13:50

liufabing 发表于 2015-6-13 14:09
是否需要经过一个学习的过程.
电量是累加的数据.

电流为什么会这么大呢?
页: [1]
查看完整版本: DS2438测量电压是比较接近,但电流和剩余容量不准