This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

bq7693003DBT +PIC18F单片机 读取SYS_STAT状态位出错问题请教,ALERT引脚一直为高电平?

Other Parts Discussed in Thread: BQ76930

大家好,第一次使用BQ76930芯片有些问题请教下,我是参照官方提供的工程实例移植到PIC单片机上,可以正常读取I2C数据。

1、不能读取相应的电池电压、总压、温度数据问题为状态寄存器(DEVICE_XREADY)为高,读取SYS_STAT 值为0X20。

2、ALERT引脚如何使用,我现在单片机配置为输入模式是否正确?

下面是原理图

在线期待大家回复!

  • You mention VC1 to VC10 voltages present, be sure the power filters components are present and power pins connected (VSS, VC5X, BAT).
    Be sure TS2 has a pull down resistance to VC5X. Normally these are the thermistors, but a resistor can be substituted. If the pull downs are to VSS the part will do exactly as you describe.
    Also be sure there is a nominal 3.3V voltage across the CAP2 and across CAP3. If the TSn pull downs are incorrect one or both will be 0. Since all ADC readings are 0 probably CAP2 voltage is missing. Also check for assembly issues such as a solder short across the capacitor or incorrect component (resistor instead of capacitor).
    Also check for solder bridges at the IC pinsfrom CAP2 to VC10X or CAP3 to BAT which would leave the part hot and likely damaged.
    If all is connected and voltage are present but the part does not reply it may have been damaged in assembly or test.
  • DEVICE_XREADY在芯片唤醒时有可能是为1,可以往该bit写入1来把它清掉
  • 上次的问题,是电池欠压保护导致的。

    系统状态配置250MS读取一次库仑计数据 ,

    现在问题

    1、芯片本身的库仑计部分不能正常运行,一直进不了

    2、电池采集位置不对,是不是需要重新配置相应的地址位?

    屏蔽判断库仑计标志函数段后,能读取电池总压,电池单体4不正常?现在配置的是7串电池系统

    BQ76930寄存器映射地址:

    查看电池4读取数据就是47MV

    我是按照手册提供方法配置的端口配置

    请各位老师指点下!

  • 芯片使能已经配置,BQ_EN 接到TS1引脚。

  • 问题2,采集单体电压值不对现象找到原因了

    是单体电压计算时读取寄存器位置问题,利用查表方法对应单体电池寄存器位置,

     int16_t BqGetCellVoltage(uint8_t cell)          //BQ读取单体电压值
    {
        uint16_t vCell;
        if((cell == 0)||(cell > NUMBER_OF_CELLS))
        {
            return 0;
        }
        else
        {
            switch(cell)                         // 
            {  
                case 1:     
                if(I2CReadRegisterWordWithCRC(BQMAXIMO, (VC1_HI_BYTE), &vCell) < 0)
                {
                    //i2c error
                    bqI2CError = TRUE;
                    return 0;
                }
                else
                {
                    bqI2CError = FALSE;
                    return(BqCellVoltageConversion((vCell&0x3FFF),bqAdcGain,bqAdcOffset));   //return value in mV
                } break;
                case 2:     
                if(I2CReadRegisterWordWithCRC(BQMAXIMO, (VC2_HI_BYTE), &vCell) < 0)
                {
                    //i2c error
                    bqI2CError = TRUE;
                    return 0;
                }
                else
                {
                    bqI2CError = FALSE;
                    return(BqCellVoltageConversion((vCell&0x3FFF),bqAdcGain,bqAdcOffset));   //return value in mV
                } break;
                case 3:     
                if(I2CReadRegisterWordWithCRC(BQMAXIMO, (VC3_HI_BYTE), &vCell) < 0)
                {
                    //i2c error
                    bqI2CError = TRUE;
                    return 0;
                }
                else
                {
                    bqI2CError = FALSE;
                    return(BqCellVoltageConversion((vCell&0x3FFF),bqAdcGain,bqAdcOffset));   //return value in mV
                } break;
                case 4:     
                if(I2CReadRegisterWordWithCRC(BQMAXIMO, (VC5_HI_BYTE), &vCell) < 0)
                {
                    //i2c error
                    bqI2CError = TRUE;
                    return 0;
                }
                else
                {
                    bqI2CError = FALSE;
                    return(BqCellVoltageConversion((vCell&0x3FFF),bqAdcGain,bqAdcOffset));   //return value in mV
                } break;
                case 5:     
                if(I2CReadRegisterWordWithCRC(BQMAXIMO, (VC6_HI_BYTE), &vCell) < 0)
                {
                    //i2c error
                    bqI2CError = TRUE;
                    return 0;
                }
                else
                {
                    bqI2CError = FALSE;
                    return(BqCellVoltageConversion((vCell&0x3FFF),bqAdcGain,bqAdcOffset));   //return value in mV
                } break;
                
                case 6:     
                if(I2CReadRegisterWordWithCRC(BQMAXIMO, (VC7_HI_BYTE), &vCell) < 0)
                {
                    //i2c error
                    bqI2CError = TRUE;
                    return 0;
                }
                else
                {
                    bqI2CError = FALSE;
                    return(BqCellVoltageConversion((vCell&0x3FFF),bqAdcGain,bqAdcOffset));   //return value in mV
                } break;
                case 7:     
                if(I2CReadRegisterWordWithCRC(BQMAXIMO, (VC10_HI_BYTE), &vCell) < 0)
                {
                    //i2c error
                    bqI2CError = TRUE;
                    return 0;
                }
                else
                {
                    bqI2CError = FALSE;
                    return(BqCellVoltageConversion((vCell&0x3FFF),bqAdcGain,bqAdcOffset));   //return value in mV
                } break;
                default:    break;
            }
    读取7串电压,能正常读取了,
    但是方法有些笨,如何优化这部分代码
  • 为什么库仑计一直不能正常运行!一直没有数据,在线期待老师指导
  • 你有没有使能CC_EN bit?库伦计默认是不打开的,需要MCU去配置打开。
  • 库仑计默认情况下是没有打开,之前库仑计不能运行的问题是DSG_ON ,GHG_ON 两个标志位没有置1 导致的问题

    现在库仑计可以工作了,为什么 芯片ALERT 引脚始终不能触发置1 ?

    一直困惑中,期待回复!

  • 请问我的i2c收到全是ff什么问题

    #define CHG_H GPIOB->BSRR = GPIO_Pin_0 //high
    #define CHG_L GPIOB->BRR = GPIO_Pin_0 //low
    //#define DSG_H GPIOA->BSRR = GPIO_Pin_7
    //#define DSG_L GPIOA->BRR = GPIO_Pin_7
    //#define CHG_H CHG_ON = 1
    //#define DSG_L DSG_ON = 1
    ////#define CHG_L CHG_ON = 0
    //#define DSG_H DSG_ON = 0
    extern unsigned char DSG_H;
    extern unsigned char DSG_L;
    //
    //
    ///*control cell open or close*/
    //extern void all_open(void);
    //extern void sign_out(void);
    //extern void sign_int(void);
    //extern void all_close(void);
    //
    //void all_open(void)
    //{
    //
    // CHG_H ;
    // DSG_H ;
    //}
    //
    //void sign_out(void)
    //{
    // CHG_H ;
    // DSG_L ;
    //}
    //
    //void sign_int(void)
    //{
    // CHG_L ;
    // DSG_H ;
    //}
    //
    //void all_close(void)
    //{
    // CHG_L ;
    // DSG_L ;
    //}
    //
    //typedef struct SSS1{
    //CHG_H ;
    //DSG_H ;
    //}S1;
    //
    //typedef struct SSS2{
    //CHG_H ;
    //DSG_L ;
    //}S2;
    //
    //typedef struct SSS3{
    //CHG_L ;
    //DSG_H ;
    //}S3;
    //
    //typedef struct SSS4{
    //CHG_L ;
    //DSG_L ;
    //}S4;
    extern unsigned char CHG_ON;
    extern unsigned char DSG_ON;
    extern void intput(void) ;
    extern void output(void) ;
    void output(void)
    {
    // unsigned char CHG_ON = 0;
    unsigned char DSG_ON = 0;
    unsigned char a[2] = {3}; //DSGÀ­¸ß
    // unsigned char a[2] = {0};
    CHG_L ;

    I2C_FRAM_BufferWrite(&a[0],0x05,1);
    DSG_ON = (a[0] >> 1) & 0X01 ;

    printf("a[0]=%x",a[0]);
    printf("OUTCHG_ON=%d",DSG_ON);
    if(DSG_ON==1)
    {
    printf("output ok \n");
    }
    else
    {
    printf("OUT2222DSG_ON=%d",DSG_ON);
    }
    }

    void intput(void)
    {

    unsigned char DSG_ON = 0;
    unsigned char a[2] ={1};
    // I2C_FRAM_BufferWrite(&a[0],0x05,1);
    I2C_FRAM_BufferWrite(&a[0],0x05,1);
    DSG_ON = (a[0]>> 1) & 0x01 ;

    // CHG_H;
    printf("INTCHG_ON=%d",DSG_ON);
    if(DSG_ON==0)
    {
    printf("input ok \n");
    }
    else
    {
    printf("INTDSG_ON=%d",DSG_ON);
    }

    }

    int main(void)
    {
    u8 yang;
    u8 i = 0;
    u8 j = 0;
    u8 huan[1]={0};
    u8 BQ769_INITAdd[11] ={0x00,0x01,0x02,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b};
    // [36] ={0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x1F,0x3c,0x3d};
    u8 BQ769_INITdata[11]={0x08,0x00,0x00,0x18,0x43,0x00,0x00,0x00,0xAC,0x97,0x19};
    uint16_t BQ769_RegAdd[12] ={0x0c,0x0d,0x0e,0x0f,0x51};

    u8 a[30]={0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x1F,0x3c,0x3d};
    uint8_t BQ769_Voltage[20] ={0};
    // u8 readbuf1[20] = {0};
    u8 readbuf2[20] = {0};
    u8 aabuf[30] = {0};

    Triode_On();
    delay_init(); //ÑÓʱº¯Êý³õʼ»¯
    BEEP_Init(); //³õʼ»¯·äÃùÆ÷¶Ë¿Ú
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //ÉèÖÃNVICÖжϷÖ×é2:2λÇÀÕ¼ÓÅÏȼ¶£¬2λÏìÓ¦ÓÅÏȼ¶
    uart_init(9600); //´®¿Ú³õʼ»¯Îª9600
    I2CInit();
    Adc_Init();
    // HalBq769x0Init();
    // HalBq769x0IIC_Init();
    BEEP1();
    // HalBq769x0IIC_Init();
    delay_ms(1000);
    // intput();
    output();

    /******************************************/
    I2C_FRAM_BufferWrite(BQ769_INITdata,BQ769_INITAdd[0],12);

    for(i=0;i<12;i++)
    {
    // IIC_Write_nByte(BQ76930_ADDR, BQ769_INITAdd[i], 1,&BQ769_INITdata[i]);
    // mxt_i2c_read_reg(BQ76930_ADDR, BQ769_INITAdd[i],1,&BQ769_INITdata[i]);
    //HalBQ_WriteRegisterByte(BQ769_INITAdd[i],BQ769_INITdata[i]);
    I2C_FRAM_BufferRead(BQ769_INITdata,BQ769_INITAdd[0],12);
    //I2C_FRAM_BufferWrite(BQ769_INITdata,BQ769_INITAdd[0],12);
    }
    //
    // I2C_FRAM_BufferWrite(BQ769_INITdata, BQ769_INITAdd[0],12);
    // for(i = 0;i<10;i++){
    // I2C_FRAM_BufferRead(BQ769_Voltage,BQ769_RegAdd[0],10);
    // printf("BQ769_Voltage");
    // for(j = 0;j<10;j++){
    // printf(": %x ",BQ769_Voltage[j]);
    // }
    // }
    printf("***********************************************µÚÒ»´Î");
    delay_ms(1000);
    for(i=0;i<11;i++)
    {
    // HalBQ_ReadBlock(BQ769_INITAdd[i],&aabuf[i],1);
    // HalBQ_ReadRegisterByte(BQ769_INITAdd[i], BQ769_INITdata[i]);
    }

    // printf("BQ769--%x--",BQ769_INITdata);
    // HalBQ_WriteBlock();

    // HalBQ_ReadRegisterByte(a[i],aabuf[i]);

    /*

    // I2C_FRAM_BufferWrite(0x01,0x05,1); //
    // I2C_FRAM_BufferWrite(0x02,0x05,1); //

    // HalBq769x0I2CSendBytes(BQ769_INITAdd ,12);
    // HalBq769x0I2CReadBytes();
    // printf(" INITAdd[3]--%x--",BQ769_INITdata[3]);
    // printf(" INITAdd[0]--%x--",BQ769_INITdata); */
    /*****************************************************************************/
    while(1)
    {
    Adc_Init();


    Triode_On();
    //intput();
    output( ) ;
    DSGInitH();
    //DSGOUTH();
    I2C_FRAM_BufferRead(BQ769_Voltage,BQ769_RegAdd[0],5);
    BQ76930_red_vcc();
    get_offset();
    get_voldata();

    IIC_Write_nByte(BQ76930_ADDR,0x04,1,BQ769_INITdata[3]);
    mxt_i2c_read_reg(BQ76930_ADDR,0x04,1,&huan[0]);
    printf("huan = %x",huan[0]);
    red_vcc();
    //printf("yang = %x",yang);
    IIC_read_one_byte(0x10,0x32);
    IIC_read_one_byte(0x10,0x33);
    IIC_read_one_byte(0x10,0x0c);
    IIC_read_one_byte(0x10,0x0d);
    IIC_read_one_byte(0x10,0x0c);
    IIC_read_one_byte(0x10,0x0d);
    IIC_read_one_byte(0x10,0x0e);
    IIC_read_one_byte(0x10,0x0f);
    IIC_read_one_byte(0x10,0x10);
    IIC_read_one_byte(0x10,0x11);
    // for(i=0;i<16;i++)
    {
    // HalBQ_ReadRegisterByte(&0x01,aabuf[i]);
    // printf("-%d ",aabuf[i]);
    }
    delay_ms(3000);
    printf("\n ***************** \n ");
    }

    #include "I2C.h"
    #include "stm32f10x.h"
    #include "stm32f10x_it.h"
    #include "delay.h"
    u8 FRAM_ADDRESS;
    /* function ------------------------------------------------------------------*/

    //void I2CInit(void)
    //{
    // GPIO_InitTypeDef GPIO_InitStructure;
    // RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    // GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
    ////SDA
    // GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
    // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    // GPIO_Init(GPIOB, &GPIO_InitStructure);
    ////SCL
    // GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    // GPIO_Init(GPIOB, &GPIO_InitStructure);
    // SCL_H;
    // SDA_H;
    //}
    //³õʼ»¯pb.10ºÍpb.11ΪÊä³ö¶Ë¿Ú£¬²¢Ê¹ÄÜÕâÁ½¸öʱÖÓ
    //I2C³õʼ»¯
    void Triode_On(void){
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //ÍÆÍìÊä³ö
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    Triode_H;
    }
    void DSGInitH(void){
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //ÍÆÍìÊä³ö
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    DSG_H1;
    }
    void DSGInitL(void){
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //ÍÆÍìÊä³ö
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    DSG_L1;
    }
    void DSGOUTH(void){
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //ÍÆÍìÊä³ö
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    DSG_H2;
    }
    void DSGOUTL(void){
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //ÍÆÍìÊä³ö
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    DSG_L2;
    }
    void I2CInit(void)
    {
    GPIO_InitTypeDef GPIO_InitStructure;
    //I2C_InitTypeDef I2C_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // ʹÄÜGPIOB¶Ë¿ÚʱÖÓ
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //ËÙ¶ÈΪ50MHZ
    //SDA
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 ; //I2C-->pb.11¶Ë¿ÚÅäÖÃ
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //ÍÆÍìÊä³ö
    GPIO_Init(GPIOB, &GPIO_InitStructure); //³õʼ»¯GPIOB.11
    //SCL
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //I2C-->pb.10¶Ë¿ÚÅäÖÃ
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //ÍÆÍìÊä³ö
    GPIO_Init(GPIOB, &GPIO_InitStructure); //³õʼ»¯GPIOB.10

    // I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; //ÉèÖÃi2cΪi2cģʽ
    // I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; //Öƶ¨Ê±ÖÓ¿ÕÕ¼±È
    // I2C_InitStructure.I2C_OwnAddress1 = I2C_Mode_SMBusHost; //Öƶ¨×ÔÉíµÄI2CÉ豸µØÖ·
    // I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; //ʹÄÜ
    // I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // ÆßλµØÖ·³¤¶È
    // I2C_InitStructure.I2C_ClockSpeed = I2C_Speed; //ÉèÖÃʱÖÓƵÂÊ
    // I2C_Cmd(I2C1,ENABLE);
    // I2C_Init(I2C1,&I2C_InitStructure);
    SCL_H;
    SDA_H;

    }
    /*******************************************************************************/

    void I2C_delay(void)
    {
    //u8 i=200;
    //while(i)
    //{
    // i--;
    //}
    delay_us(10);
    }

    /*******************************************************************************/

    u8 I2C_Start(void)
    {
    SDA_H;
    SCL_H;
    I2C_delay();
    if(!SDA_read)return FALSE; //SDAÏßΪµÍµçƽ×ÜÏßæÍ˳ö
    SDA_L;
    I2C_delay();
    if(SDA_read) return FALSE; //SDAÏßΪ¸ßµçƽ×ÜÏß³ö´íÍ˳ö
    SCL_L;
    I2C_delay();
    return TRUE;
    }

    /*******************************************************************************/

    void I2C_Stop(void)
    {
    SCL_L;
    I2C_delay();
    SDA_L;
    I2C_delay();
    SCL_H;
    I2C_delay();
    SDA_H;
    I2C_delay();
    }

    /*******************************************************************************/

    /*******************************************************************************/

    void I2C_NoAck(void)
    {
    SCL_L;
    I2C_delay();
    SDA_H;
    I2C_delay();
    SCL_H;
    I2C_delay();
    SCL_L;
    I2C_delay();

    }




    void I2C_Ack(void)
    {
    SCL_L;
    I2C_delay();
    SDA_L;
    I2C_delay();
    SCL_H;
    I2C_delay();
    SCL_L;
    I2C_delay();
    }

    /*******************************************************************************/

    u8 I2C_WaitAck(void)
    {
    SCL_L;
    I2C_delay();
    SDA_H;
    I2C_delay();
    SCL_H;
    I2C_delay();
    if(SDA_read)
    {
    SCL_L;
    return FALSE;
    }
    SCL_L;
    return TRUE;
    }

    /*******************************************************************************/

    void I2C_SendByte(u8 SendByte) //Êý¾Ý·¢ËÍ´Ó¸ßλµ½µÍλ
    {
    u8 i=8;
    while(i--)
    {
    SCL_L;
    I2C_delay();
    if(SendByte&0x80)
    SDA_H;
    else
    SDA_L;
    SendByte<<=1;
    I2C_delay();
    SCL_H;
    I2C_delay();
    }
    SCL_L;
    }

    /*******************************************************************************/

    u8 I2C_ReceiveByte(void) //Êý¾Ý´Ó¸ßλµ½µÍλ
    {
    u8 i=8;
    u8 ReceiveByte=0;
    SDA_H;
    while(i--)
    {
    ReceiveByte<<=1;
    SCL_L;
    I2C_delay();
    SCL_H;
    I2C_delay();
    if(SDA_read)
    {
    ReceiveByte|=0x01;
    }
    }
    SCL_L;
    return ReceiveByte;
    }


    void IIC_single_byte_write(unsigned char Daddr,unsigned char Waddr,unsigned char Data)
    {
    I2C_Start();
    I2C_SendByte(Daddr<<1);
    if (!I2C_WaitAck())
    {
    I2C_Stop(); //
    //return FALSE;
    }
    //I2C_Ack();
    I2C_SendByte(Waddr);
    I2C_WaitAck();
    I2C_SendByte(Data) ;
    I2C_WaitAck();
    //printf("write ok!");
    I2C_Stop();
    }

    unsigned char IIC_read_one_byte(unsigned char Daddr,unsigned char Waddr) //É豸µØÖ· Òª²Ù×÷µÄµØÖ·
    {
    unsigned char Data;

    I2C_Start();
    I2C_SendByte(Daddr<<1);
    // printf("Daddr=%x \n",Daddr);
    if (!I2C_WaitAck())
    {
    I2C_Stop(); //
    return FALSE;
    }
    // I2C_Ack();
    I2C_SendByte(Waddr);
    I2C_WaitAck();
    //printf("Waddr=%x \n",Waddr);
    I2C_Start();
    I2C_SendByte(Daddr<<1|0x1);
    // I2C_SendByte(Daddr );
    I2C_WaitAck();
    Data = I2C_ReceiveByte();
    //printf("Data=%s \n",Data);
    I2C_NoAck();

    I2C_Stop();
    return Data;
    }


    /*******************************************************************************/

    u8 I2C_FRAM_BufferWrite(u8* pBuffer, u16 WriteAddr, u16 NumByteToWrite)
    {
    u8 Addr = 0, count = 0;
    Addr = (WriteAddr) / I2C_PageSize;
    // printf("Addr=%x \n",Addr) ;
    count = (WriteAddr) % I2C_PageSize;
    // printf("count=%x \n", count) ;
    Addr = Addr << 1;
    Addr = Addr & 0x0F;
    FRAM_ADDRESS = I2C1_SLAVE_ADDRESS7_W | Addr;
    if (!I2C_Start())
    return FALSE;
    I2C_SendByte(FRAM_ADDRESS);
    printf("FRAM_ADDRESS=%x \n",FRAM_ADDRESS) ;
    if (!I2C_WaitAck())
    {
    I2C_Stop(); //
    return FALSE;
    }
    I2C_SendByte(count);
    I2C_WaitAck();
    while(NumByteToWrite--)
    {
    I2C_SendByte(* pBuffer);
    // printf("%x \n", * pBuffer) ;
    printf("pBuffer1=%x \n",pBuffer) ;
    I2C_WaitAck();
    pBuffer++;
    }
    I2C_Stop();
    return TRUE;
    //return * pBuffer;
    }

    /*******************************************************************************/
    u8 I2C_FRAM_BufferRead(u8* pBuffer, u16 WriteAddr, u16 NumByteToRead)
    {
    u8 Addr = 0, count = 0;
    Addr = WriteAddr / I2C_PageSize ;
    count = WriteAddr % I2C_PageSize ;
    Addr = Addr << 1 ;
    Addr = Addr & 0x0F ;
    // printf("addr = %d \n",Addr);
    FRAM_ADDRESS = I2C1_SLAVE_ADDRESS7_R | Addr ;
    if (!I2C_Start()) return FALSE;
    I2C_SendByte(FRAM_ADDRESS);
    //printf("111111");
    if (!I2C_WaitAck())
    {
    I2C_Stop();

    return FALSE;

    }

    I2C_SendByte(count);
    printf("count=%d",count);
    I2C_WaitAck();
    I2C_Start();
    I2C_SendByte(FRAM_ADDRESS | 0x01);
    I2C_WaitAck();
    while(NumByteToRead)
    {
    *pBuffer = I2C_ReceiveByte();

    printf(" * pBuffer2=%x \n", * pBuffer) ;
    printf("pBuffer2=%p \n",pBuffer) ;
    printf("FRAM_ADDRESS=%x \n",FRAM_ADDRESS) ;

    if(NumByteToRead == 1)I2C_NoAck();
    else I2C_Ack();
    pBuffer++;
    NumByteToRead--;
    }
    I2C_Stop();
    return TRUE;
    }
    u8 IIC_Write_nByte(u8 SlaveAddress, u8 REG_Address, u8 len, u8 *buf)
    {
    I2C_Start();
    I2C_SendByte(SlaveAddress<<1);
    if( !I2C_WaitAck())
    {

    I2C_Stop();
    return 1;
    }
    I2C_SendByte(REG_Address);
    I2C_WaitAck();
    while(len--)
    {
    I2C_SendByte(*buf++);
    I2C_WaitAck();
    }
    I2C_Stop();
    return 0;
    }


    ///////////////////////////////////////////////////////////////
    unsigned char mxt_i2c_read_reg(u8 ADDR,u8 reg, u8 length, u8* buf)
    {
    //printf("µÚ1");
    I2C_Start();
    I2C_SendByte(ADDR<<1);
    I2C_WaitAck();
    I2C_SendByte(reg);
    I2C_WaitAck();
    I2C_Stop();

    I2C_Start();
    I2C_SendByte((ADDR<<1) | 0x01);
    I2C_WaitAck();
    while(length)
    {
    if(length == 1)
    {

    *buf = I2C_ReceiveByte();
    //printf("µÚ2");
    // I2C_ReceiveByte();
    // *buf =Get_Adc(3);

    I2C_NoAck();
    }
    else
    {
    *buf++ = I2C_ReceiveByte();
    // I2C_ReceiveByte();
    // *buf++ = Get_Adc(3);
    I2C_Ack();
    }
    length--;
    }
    I2C_Stop();

    return 1;
    }
    //
    //////////////////////////////////////////////////////////////////////////////////
    void BQ76930_red_vcc(void)
    {
    u8 pBuffer[40];
    u8 buf[30] ={0};
    u8 a[30]={0};
    int i;

    I2C_FRAM_BufferRead(&pBuffer[0],pBuffer[0],1);
    I2C_FRAM_BufferRead(&pBuffer[1],pBuffer[1],1);

    I2C_FRAM_BufferRead(&pBuffer[2],pBuffer[2],1);
    I2C_FRAM_BufferRead(&pBuffer[3],pBuffer[3],1);

    I2C_FRAM_BufferRead(&pBuffer[4],pBuffer[4],1);
    I2C_FRAM_BufferRead(&pBuffer[5],pBuffer[5],1);

    I2C_FRAM_BufferRead(&pBuffer[6],pBuffer[6],1);
    I2C_FRAM_BufferRead(&pBuffer[7],pBuffer[7],1);

    I2C_FRAM_BufferRead(&pBuffer[8],pBuffer[8],1);
    I2C_FRAM_BufferRead(&pBuffer[9],pBuffer[9],1);

    for(i=0;i<30;i++)
    {
    I2C_FRAM_BufferRead(&a[i],a[i],1);
    I2C_FRAM_BufferRead(&pBuffer[i],pBuffer[i],1);
    printf(" %x \n",&pBuffer[i]);
    printf("-%d-\n",pBuffer[i]);
    }

    }


    void get_offset(void)
    {
    unsigned char gain[3];
    unsigned char Gain;
    unsigned char ADCoffset ;
    int ADGain ;
    // static unsigned char ADC_offset = 0;
    // static unsigned char AD_Gain = 0;
    I2C_FRAM_BufferRead(&gain[0],0x50,1);
    I2C_FRAM_BufferRead(&gain[1],0x59,1);
    printf("gain[0]=%x",gain[0]);
    printf("gain[1]=%x",gain[1]);
    Gain = ((gain[0]&0x0c)<<1)+((gain[1]&0xe0)>>5);
    // printf(" Gain=%x", Gain);
    I2C_FRAM_BufferRead(&gain[2],0x51,1);
    ADCoffset= gain[2] ;
    ADGain = 365+Gain;
    printf("ADCoffset=%x",ADCoffset); // =1
    printf("ADGain=%x",ADGain); // =374
    }

    unsigned char CRC8(unsigned char *ptr, unsigned char len,unsigned char key) //Êý¾Ý Êý¾Ý³¤¶È УÑéÊý
    {
    unsigned char i;
    unsigned char crc=0;
    while(len--!=0)
    {
    for(i=0x80; i!=0; i/=2)
    {
    if((crc & 0x80) != 0)
    {
    crc *= 2;
    crc ^= key;
    }
    else
    crc *= 2;

    if((*ptr & i)!=0)
    crc ^= key;
    }
    ptr++;
    }
    return(crc);
    }

    int I2CReadRegisterByteWithCRC(unsigned char I2CSlaveAddress, unsigned char Register, unsigned char *Data)
    {
    // unsigned char TargetRegister = Register;
    // unsigned int SentByte = 0;
    // unsigned char ReadData[2];
    // unsigned int ReadDataCount = 0;
    // unsigned char CRCInput[2];
    // unsigned char CRC = 0;
    // int ReadStatus = 0;
    // int WriteStatus = 0;
    //
    // WriteStatus = I2CSendBytes(I2CSlaveAddress, &TargetRegister, 1, &SentByte);
    //
    // ReadStatus = I2CReadBytes(I2CSlaveAddress, ReadData, 2, &ReadDataCount);
    //
    // if (ReadStatus != 0 || WriteStatus != 0)
    // {
    // return -1;
    // }
    //
    // CRCInput[0] = (I2CSlaveAddress << 1) + 1;
    // CRCInput[1] = ReadData[0];
    //
    // CRC = CRC8(CRCInput, 2, CRC_KEY);
    //
    // if (CRC != ReadData[1])
    // return -1;
    //
    // *Data = ReadData[0];
    return 0;
    }

    /*unsigned char i2c_read_reg(u8 ADDR,u8 reg, u8 length, u8* buf)
    {
    I2C_Start();
    I2C_SendByte((ADDR<<1) | 0X00);
    I2C_SendByte(reg);
    I2C_Stop();

    I2C_Start();
    I2C_SendByte((ADDR<<1) | 0X01);
    while(length)
    {
    if(length == 1)
    {
    *buf = I2C_ReceiveByte(NOACK);
    }
    else
    {
    *buf++ = I2C_ReceiveByte(ACK);
    }
    length--;
    }
    I2C_Stop();

    return 1;
    }
    */


    void red_vcc(void)
    {
    //DSGInit();
    u8 buf[100]={0};
    u8 i=0;




    mxt_i2c_read_reg(BQ76930_ADDR,0x0C,30,&buf[0]);
    mxt_i2c_read_reg(BQ76930_ADDR,0x0C,1,&buf[0]);
    mxt_i2c_read_reg(BQ76930_ADDR,0x0D,1,&buf[1]);

    mxt_i2c_read_reg(BQ76930_ADDR,0x0E,1,&buf[2]);
    mxt_i2c_read_reg(BQ76930_ADDR,0x0F,1,&buf[3]);

    mxt_i2c_read_reg(BQ76930_ADDR,0x10,1,&buf[4]);
    mxt_i2c_read_reg(BQ76930_ADDR,0x11,1,&buf[5]);

    mxt_i2c_read_reg(BQ76930_ADDR,0x12,1,&buf[6]);
    mxt_i2c_read_reg(BQ76930_ADDR,0x13,1,&buf[7]);

    mxt_i2c_read_reg(BQ76930_ADDR,0x14,1,&buf[8]);
    mxt_i2c_read_reg(BQ76930_ADDR,0x15,1,&buf[9]);

    mxt_i2c_read_reg(BQ76930_ADDR,0x16,1,&buf[10]);
    mxt_i2c_read_reg(BQ76930_ADDR,0x17,1,&buf[11]);

    mxt_i2c_read_reg(BQ76930_ADDR,0x18,1,&buf[12]);
    mxt_i2c_read_reg(BQ76930_ADDR,0x19,1,&buf[13]);

    mxt_i2c_read_reg(BQ76930_ADDR,0x1A,1,&buf[14]);
    mxt_i2c_read_reg(BQ76930_ADDR,0x1B,1,&buf[15]);

    mxt_i2c_read_reg(BQ76930_ADDR,0x1C,1,&buf[16]);
    mxt_i2c_read_reg(BQ76930_ADDR,0x1D,1,&buf[17]);

    mxt_i2c_read_reg(BQ76930_ADDR,0x1E,1,&buf[18]);
    mxt_i2c_read_reg(BQ76930_ADDR,0x1F,1,&buf[19]);

    //mxt_i2c_read_reg(BQ76930_ADDR,0x0C | 0x0D,1,&buf[20]);
    // mxt_i2c_read_reg(BQ76930_ADDR,0x21,1,&buf[21]);
    //
    // mxt_i2c_read_reg(BQ76930_ADDR,0x22,1,&buf[22]);
    // mxt_i2c_read_reg(BQ76930_ADDR,0x23,1,&buf[23]);
    //
    // mxt_i2c_read_reg(BQ76930_ADDR,0x24,1,&buf[24]);
    // mxt_i2c_read_reg(BQ76930_ADDR,0x25,1,&buf[25]);
    //
    // mxt_i2c_read_reg(BQ76930_ADDR,0x26,1,&buf[26]);
    // mxt_i2c_read_reg(BQ76930_ADDR,0x27,1,&buf[27]);
    //
    // mxt_i2c_read_reg(BQ76930_ADDR,0x28,1,&buf[28]);
    // mxt_i2c_read_reg(BQ76930_ADDR,0x29,1,&buf[29]);
    //
    // mxt_i2c_read_reg(BQ76930_ADDR,0x2a,1,&buf[30]);
    // mxt_i2c_read_reg(BQ76930_ADDR,0x2b,1,&buf[31]);
    //
    // mxt_i2c_read_reg(BQ76930_ADDR,0x2c,1,&buf[31]);
    // mxt_i2c_read_reg(BQ76930_ADDR,0x2d,1,&buf[32]);
    //
    // mxt_i2c_read_reg(BQ76930_ADDR,0x2e,1,&buf[33]);
    // mxt_i2c_read_reg(BQ76930_ADDR,0x2f,1,&buf[34]);

    // mxt_i2c_read_reg(BQ76930_ADDR,0x30,1,&buf[35]);
    // mxt_i2c_read_reg(BQ76930_ADDR,0x31,1,&buf[36]);

    // mxt_i2c_read_reg(BQ76930_ADDR,0x32,1,&buf[37]);
    // mxt_i2c_read_reg(BQ76930_ADDR,0x33,1,&buf[38]);

    // mxt_i2c_read_reg(BQ76930_ADDR,0x50,1,&buf[39]);
    // mxt_i2c_read_reg(BQ76930_ADDR,0x51,1,&buf[40]);

    // mxt_i2c_read_reg(BQ76930_ADDR,0x59,1,&buf[41]);
    // mxt_i2c_read_reg(BQ76930_ADDR,0x60,1,&buf[42]);
    // mxt_i2c_read_reg(BQ76930_ADDR,0x61,1,&buf[43]);
    // mxt_i2c_read_reg(BQ76930_ADDR,0x68,1,&buf[44]);
    // mxt_i2c_read_reg(BQ76930_ADDR,0x70,1,&buf[45]);
    // mxt_i2c_read_reg(BQ76930_ADDR,0x76,1,&buf[46]);
    printf("buf :");

    for(i=0;i<21;i++)
    {
    printf("=%x=",buf[i]);
    }
    for(i=0;i<21;i++)
    {
    printf("^%d^",buf[i]);
    }
    }

    #include "BQIIC.h"
    #include "sys.h"
    #include "delay.h"
    #include "usart.h"

    static void HalBq769x0IIC_Init(void)
    {
    GPIO_InitTypeDef GPIO_InitStructure;

    GPIO_InitStructure.GPIO_Pin = BQ769x0_IIC_SCL_PIN ;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //????
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_Pin = BQ769x0_IIC_SDA_PIN; ;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD ; //????
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    // GPIO_Init(BQ769x0_IIC_PORT, &GPIO_InitStructure);
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    BQ769x0_IIC_SCL_H;
    BQ769x0_IIC_SDA_H;
    }
    //??IIC????
    static void HalBq769x0IIC_Start(void)
    {
    BQ769x0_IIC_SDA_OUT; //sda???
    BQ769x0_IIC_SCL_H;
    BQ769x0_IIC_SDA_H;
    delay_us(BQ769x0_IIC_DELAY_US);
    BQ769x0_IIC_SDA_L; //START:when CLK is high,DATA change form high to low
    delay_us(BQ769x0_IIC_DELAY_US);
    BQ769x0_IIC_SCL_L; //??I2C??,?????????
    }
    //??IIC????
    static void HalBq769x0IIC_Stop(void)
    {
    BQ769x0_IIC_SDA_OUT ;//sda
    BQ769x0_IIC_SCL_L;
    BQ769x0_IIC_SDA_L; //STOP:when CLK is high DATA change form low to high
    delay_us(BQ769x0_IIC_DELAY_US);
    BQ769x0_IIC_SCL_H;
    delay_us(BQ769x0_IIC_DELAY_US);
    BQ769x0_IIC_SDA_H; //
    delay_us(BQ769x0_IIC_DELAY_US);
    }
    //
    //
    //
    static uint8_t HalBq769x0IIC_Wait_Ack(void)
    {
    uint32_t ucErrTime = 0;
    BQ769x0_IIC_SDA_IN ; //SDA?????
    delay_us(BQ769x0_IIC_DELAY_US);
    BQ769x0_IIC_SCL_H;
    delay_us(BQ769x0_IIC_DELAY_US);
    while(BQ769x0_IIC_READ_SDA())
    {
    ucErrTime++;
    if(ucErrTime > BQ769x0_IIC_ACK_TIME_OUT)
    {
    printf("BQ769x0_IIC_ACK_TIME_OUT");
    HalBq769x0IIC_Stop();
    return 1;
    }
    }

    BQ769x0_IIC_SCL_L; //????L
    return 0;
    }
    //??ACK??
    static void HalBq769x0IIC_Ack(void)
    {
    BQ769x0_IIC_SCL_L;
    BQ769x0_IIC_SDA_OUT;
    BQ769x0_IIC_SDA_L;
    delay_us(BQ769x0_IIC_DELAY_US);
    BQ769x0_IIC_SCL_H;
    // HalNormalDelayUs(BQ769x0_IIC_DELAY_US);
    delay_us(BQ769x0_IIC_DELAY_US);
    BQ769x0_IIC_SCL_L;
    }

    //???ACK??
    static void HalBq769x0IIC_NAck(void)
    {
    BQ769x0_IIC_SCL_L;
    BQ769x0_IIC_SDA_OUT ;
    BQ769x0_IIC_SDA_H;
    delay_us(BQ769x0_IIC_DELAY_US);
    BQ769x0_IIC_SCL_H;
    delay_us(BQ769x0_IIC_DELAY_US);
    BQ769x0_IIC_SCL_L;
    }

    static void HalBq769x0IIC_Send_Byte(uint8_t txd)
    {
    uint8_t t;
    BQ769x0_IIC_SDA_OUT;
    BQ769x0_IIC_SCL_L;
    for(t = 0; t < 8; t++)
    {
    if(txd & 0x80)
    {
    BQ769x0_IIC_SDA_H;
    }
    else
    {
    BQ769x0_IIC_SDA_L;
    }
    txd <<= 1;
    delay_us(BQ769x0_IIC_DELAY_US);
    BQ769x0_IIC_SCL_H;
    delay_us(BQ769x0_IIC_DELAY_US);
    BQ769x0_IIC_SCL_L;
    }
    BQ769x0_IIC_SDA_IN;
    }

    static uint8_t HalBq769x0IIC_Read_Byte(uint8_t ack)
    {
    uint8_t i, receive = 0;
    BQ769x0_IIC_SDA_IN;//SDA?????
    for(i = 0; i < 8; i++ )
    {
    BQ769x0_IIC_SCL_L;
    delay_us(BQ769x0_IIC_DELAY_US);
    BQ769x0_IIC_SCL_H;
    receive <<= 1;
    if(BQ769x0_IIC_READ_SDA())
    {
    receive++;
    }
    delay_us(BQ769x0_IIC_DELAY_US);
    }
    if (!ack)
    {
    HalBq769x0IIC_NAck(); //??nACK
    }
    else
    {
    HalBq769x0IIC_Ack(); //??ACK
    }
    return receive;
    }

    //???IIC??
    void HalBq769x0IIC_SoftReset(void)
    {
    uint32_t i;
    //start
    BQ769x0_IIC_SCL_H;
    BQ769x0_IIC_SDA_H;

    delay_us(BQ769x0_IIC_DELAY_US);
    BQ769x0_IIC_SDA_L; //START:when CLK is high,DATA change form high to low
    delay_us(BQ769x0_IIC_DELAY_US);
    BQ769x0_IIC_SCL_L; //??I2C??,?????????

    delay_us(BQ769x0_IIC_DELAY_US);
    BQ769x0_IIC_SDA_H;
    delay_us(BQ769x0_IIC_DELAY_US);

    for(i = 0; i < 9; i++)
    {
    BQ769x0_IIC_SCL_H;
    delay_us(BQ769x0_IIC_DELAY_US);
    BQ769x0_IIC_SCL_L;
    delay_us(BQ769x0_IIC_DELAY_US);
    }

    BQ769x0_IIC_SCL_H;
    delay_us(BQ769x0_IIC_DELAY_US);
    BQ769x0_IIC_SDA_L;
    delay_us(BQ769x0_IIC_DELAY_US);
    BQ769x0_IIC_SCL_L;
    delay_us(BQ769x0_IIC_DELAY_US);
    BQ769x0_IIC_SCL_H;
    delay_us(BQ769x0_IIC_DELAY_US);
    BQ769x0_IIC_SDA_H;
    delay_us(BQ769x0_IIC_DELAY_US);
    }

    /* */
    static int8_t HalBq769x0I2CSendBytes(uint8_t *DataBuffer, uint16_t ByteCount)
    {
    uint16_t i;
    uint8_t slave_addr = BQ769X0_SLAVE_ADDR << 1; //0x08

    HalBq769x0IIC_Start();
    HalBq769x0IIC_Send_Byte(slave_addr | BQ_CMD_WRITE); //0x00
    HalBq769x0IIC_Wait_Ack();

    for(i = 0; i < ByteCount; i++)
    {
    HalBq769x0IIC_Send_Byte(DataBuffer[i]);
    HalBq769x0IIC_Wait_Ack();
    }

    HalBq769x0IIC_Stop();

    return 0x00;
    }

    static int8_t HalBq769x0I2CReadBytes(uint8_t *DataBuffer, uint16_t ExpectedByteNumber)
    {
    uint16_t i;
    uint8_t slave_addr = BQ769X0_SLAVE_ADDR << 1;

    HalBq769x0IIC_Start();
    HalBq769x0IIC_Send_Byte(slave_addr | BQ_CMD_READ);
    HalBq769x0IIC_Wait_Ack();

    for(i = 0; i < ExpectedByteNumber; i++)
    {
    if(i == ExpectedByteNumber - 1)
    {
    DataBuffer[i] = HalBq769x0IIC_Read_Byte(0);
    }
    else
    {
    DataBuffer[i] = HalBq769x0IIC_Read_Byte(1);
    }
    }

    HalBq769x0IIC_Stop();

    return 0;
    }

    void HalBq769x0Init(void)
    {
    HalBq769x0IIC_Init();
    }

    #ifdef BQWITHCRC
    static uint8_t CRC8(uint8_t *ptr, uint8_t len, uint8_t key)
    {
    uint8_t i;
    uint8_t crc = 0;
    while(len-- != 0)
    {
    for(i = 0x80; i != 0; i /= 2)
    {
    if((crc & 0x80) != 0)
    {
    crc *= 2;
    crc ^= key;
    }
    else
    {
    crc *= 2;
    }

    if((*ptr & i) != 0)
    {
    crc ^= key;
    }
    }
    ptr++;
    }
    return(crc);
    }

    int8_t HalBQ_ReadRegisterByte(uint8_t Register, uint8_t *Data)
    {
    uint8_t TargetRegister = Register;
    uint8_t ReadData[2];
    uint8_t CRCInput[2];
    uint8_t crc_val = 0;

    HalBq769x0I2CSendBytes(&TargetRegister, 1);
    HalBq769x0I2CReadBytes(ReadData, 2);

    CRCInput[0] = (BQ769X0_SLAVE_ADDR << 1) + 1;
    CRCInput[1] = ReadData[0];

    crc_val = CRC8(CRCInput, 2, CRC_KEY);

    if (crc_val != ReadData[1])
    {
    SysLog("crc err!! %02x,%02x,crc_cal=%02x", ReadData[0], ReadData[1], crc_val);
    return -1;
    }

    *Data = ReadData[0];

    return 0;
    }

    int8_t HalBQ_ReadRegisterWord(uint8_t Register, uint16_t *Data)
    {
    uint8_t TargetRegister = Register;
    uint8_t ReadData[4];
    uint8_t CRCInput[2];
    uint8_t crc_val = 0;

    HalBq769x0I2CSendBytes(&TargetRegister, 1);
    HalBq769x0I2CReadBytes(ReadData, 4);

    CRCInput[0] = (BQ769X0_SLAVE_ADDR << 1) + 1;
    CRCInput[1] = ReadData[0];

    crc_val = CRC8(CRCInput, 2, CRC_KEY);

    if (crc_val != ReadData[1])
    {
    return -1;
    }

    crc_val = CRC8(ReadData + 2, 1, CRC_KEY);

    if (crc_val != ReadData[3])
    {
    return -1;
    }

    *Data = (ReadData[0] << 8) + ReadData[2];
    return 0;
    }

    int8_t HalBQ_ReadBlock(uint8_t Register, uint8_t *Buffer, uint8_t Length) //¼Ä´æÆ÷µØÖ· Êý¾Ý Êý¾Ý³¤¶È
    {
    uint8_t TargetRegister = Register;
    uint8_t ReadData[BQ769X0_REGISTER_NUM * 2];
    uint8_t CRCInput[2];
    uint8_t crc_val = 0;
    int8_t i;

    HalBq769x0I2CSendBytes(&TargetRegister, 1);
    HalBq769x0I2CReadBytes(ReadData, 2 * Length);

    CRCInput[0] = (BQ769X0_SLAVE_ADDR << 1) + 1;
    CRCInput[1] = ReadData[0];

    crc_val = CRC8(CRCInput, 2, CRC_KEY);
    if (crc_val != ReadData[1])
    {
    return -1;
    }
    else
    {
    Buffer[0] = ReadData[0];
    }

    for(i = 2; i < Length * 2; i += 2)
    {
    crc_val = CRC8(ReadData + i, 1, CRC_KEY);

    if (crc_val != ReadData[i + 1])
    {
    return -1;
    }
    else
    {
    Buffer[i >> 1] = ReadData[i];
    }
    }

    return 0;
    }

    int8_t HalBQ_WriteRegisterByte(uint8_t Register, uint8_t Data)
    {
    uint8_t DataBuffer[4];

    DataBuffer[0] = BQ769X0_SLAVE_ADDR << 1;
    DataBuffer[1] = Register;
    DataBuffer[2] = Data;
    DataBuffer[3] = CRC8(DataBuffer, 3, CRC_KEY);

    return(HalBq769x0I2CSendBytes(DataBuffer + 1, 3));
    }

    int8_t HalBQ_WriteRegisterWord(uint8_t Register, uint16_t Data)
    {
    uint8_t DataBuffer[6];

    DataBuffer[0] = BQ769X0_SLAVE_ADDR << 1;
    DataBuffer[1] = Register;
    DataBuffer[2] = (uint8_t)(Data & 0xff);
    DataBuffer[3] = CRC8(DataBuffer, 3, CRC_KEY);
    DataBuffer[4] = (uint8_t)((Data >> 8) & 0xff);
    DataBuffer[5] = CRC8(DataBuffer + 4, 1, CRC_KEY);

    return(HalBq769x0I2CSendBytes(DataBuffer + 1, 5));
    }

    int8_t HalBQ_WriteBlock(uint8_t StartAddress, uint8_t *Buffer, uint8_t Length)
    {
    uint8_t send_buffer[BQ769X0_REGISTER_NUM * 2 + 2]; // 0x40
    int8_t result;
    uint8_t i, *pt;

    send_buffer[0] = BQ769X0_SLAVE_ADDR << 1;
    send_buffer[1] = StartAddress;
    send_buffer[2] = Buffer[0];
    send_buffer[3] = CRC8(send_buffer, 3, CRC_KEY);

    pt = send_buffer + 4;

    for(i = 1; i < Length; i++)
    {
    *pt++ = Buffer[i];
    *pt++ = CRC8(Buffer + i, 1, CRC_KEY);
    }

    result = HalBq769x0I2CSendBytes(send_buffer + 1, 2 * Length + 1);
    return result;
    }

    /////////////////////////////////////////////////////////////////////////////
    #else
    int8_t HalBQ_WriteBlock(uint8_t StartAddress, uint8_t *Buffer, uint8_t Length)
    {
    uint8_t send_buffer[BQ769X0_REGISTER_NUM + 1];
    int8_t i, result;
    uint8_t *pt = send_buffer;

    if(Length > BQ769X0_REGISTER_NUM)
    {
    return -1;
    }

    *pt++ = StartAddress;

    for(i = 0; i < Length; i++)
    {
    *pt++ = Buffer[i];
    }

    result = HalBq769x0I2CSendBytes(send_buffer, Length + 1);

    return result;
    }

    int8_t HalBQ_WriteRegisterByte(uint8_t Register, uint8_t Data)
    {
    uint8_t DataBuffer[2];
    int8_t tempVal;

    DataBuffer[0] = Register;
    DataBuffer[1] = Data;

    tempVal = HalBq769x0I2CSendBytes(DataBuffer, 2);

    return tempVal;
    }

    int8_t HalBQ_WriteRegisterWord(uint8_t Register, uint16_t Data)
    {
    uint8_t DataBuffer[3];
    int8_t tempVal;

    DataBuffer[0] = Register;
    DataBuffer[1] = (uint8_t)(Data & 0xff);
    DataBuffer[2] = (uint8_t)((Data >> 8) & 0xff);

    tempVal = HalBq769x0I2CSendBytes(DataBuffer, 3);
    return tempVal;
    }

    int8_t HalBQ_ReadRegisterByte(uint8_t Register, uint8_t *DataBuf)
    {
    uint8_t TargetRegister = Register;
    HalBq769x0I2CSendBytes(&TargetRegister, 1);
    HalBq769x0I2CReadBytes(DataBuf, 1);
    return 0;
    }

    int8_t HalBQ_ReadRegisterWord(uint8_t Register, uint16_t *DataBuf)
    {
    uint8_t ReadData[4];
    uint8_t TargetRegister = Register;
    HalBq769x0I2CSendBytes(&TargetRegister, 1);
    HalBq769x0I2CReadBytes(ReadData, 2);
    *DataBuf = ((uint16_t)ReadData[0] << 8) + (uint16_t)ReadData[2];

    return 0;
    }

    int8_t HalBQ_ReadBlock1(uint8_t StartRegisterAddress, uint8_t *Buffer, uint16_t BlockSize)
    {
    uint8_t TargetRegister = StartRegisterAddress;
    uint16_t SentByte = 0;

    HalBq769x0I2CSendBytes(&TargetRegister, 1);
    HalBq769x0I2CReadBytes(Buffer, BlockSize);

    return 0;
    }
    #endif