OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 9765|回复: 34

有哪位朋友做过STM32的IO口模拟I2C读取BQ34Z100电量计数据吗,在下老读到数据时0xffff,

[复制链接]

2

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
112
金钱
112
注册时间
2015-8-17
在线时间
20 小时
发表于 2015-9-6 16:08:40 | 显示全部楼层 |阅读模式
5金钱

#include "config.h"
extern unsigned char TxData[BUFFERSIZE];
extern unsigned char RxData[BUFFERSIZE];

void BQ34Z100_I2C_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin=I2C_SCL|I2C_SDA;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_Init(GPIOB,&GPIO_InitStructure);

I2C_SCL_H;
I2C_SDA_H;
}
/**********************************************************
I2C_SDA_OUT初始化函数
**************************************************************/
void BQ34Z100_I2C_SDA_OUT(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin=I2C_SDA;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
 /**********************************************************
I2C_SDA_IN初始化函数
**************************************************************/
void BQ34Z100_I2C_SDA_IN(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin=I2C_SDA;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}

//void MSP430_SWI2CMST_delay(void)
//{
//  __delay_cycles(GPIODELAYCYCLES);          // Quick delay
//}

void BQ34Z100_I2C_start(void)
{
 BQ34Z100_I2C_SDA_OUT();  
I2C_SDA_H;
I2C_SCL_H;
delay_us(4);
I2C_SDA_L;
delay_us(4);
 I2C_SCL_L;
delay_us(4);

}

void BQ34Z100_I2C_stop(void)
{
BQ34Z100_I2C_SDA_OUT();  
I2C_SDA_L;
 delay_us(4);
I2C_SCL_H;
delay_us(4); 
I2C_SDA_H;
delay_us(4);

}

unsigned char BQ34Z100_I2C_txByte(unsigned char data)
{
  unsigned char bits, temp, ack;

   I2C_SCL_L;
  temp = data;                              // Initialize temp variable
  bits = 0x08;  
 BQ34Z100_I2C_SDA_OUT();                            // Load I2C bit counter
  while (bits != 0x00)                      // Loop until all bits are shifted
  {
    if (temp & 0x80)                        // Test data bit
      I2C_SDA_H;                              // SDA = 1
    else
    I2C_SDA_L;                             // SDA = 0
    delay_us(4);                              // Quick delay
  I2C_SCL_H;                               // SCL = 1
   // while (I2C_SCL_READ() == 0);              //111去掉   Wait for any SCL clock stretching change1
    delay_us(4);                           // Quick delay
    temp = (temp << 1);                     // Shift bits 1 place to the left
     I2C_SCL_L;                                 // SCL = 0
    bits = (bits - 1);                      // Loop until 8 bits are sent
  }
delay_us(4);//  I2CDELAY;
   I2C_SDA_H;                                   // SDA = 1
  I2C_SCL_H;  
// while (I2C_SCL_READ() == 0);          // Wait for any SCL clock stretchingchange2
 delay_us(4);                              // Quick delay
  ack=I2C_SDA_READ();                    // Read ACK state from Slave
  I2C_SCL_L;                                 // SCL = 0
  if (ack)                                  // Return ACK state to calling app
    return (1);
  else
    return (0);




}

unsigned char BQ34Z100_I2C_rxByte(char ack)
{
  unsigned char bits, data = 0;
 BQ34Z100_I2C_SDA_IN();
 I2C_SDA_H;                                 // SDA = 1
  bits = 0x08;                              // Load I2C bit counter
  while (bits > 0)                          // Loop until all bits are read
  {
    I2C_SCL_H;                               // SCL = 1
// while (I2C_SCL_READ() == 0);  //    while ((PxIN & SCL) == 0); 111去掉             // Wait for any SCL clock stretchingchange3
    delay_us(4);                             // Quick delay
    data = (data << 1);                     // Shift bits 1 place to the left
    if(I2C_SDA_READ()==1)                        // Check digital input
      data = (data + 1);                    // If input is high, store a '1'
    I2C_SCL_L;                                // SCL = 0
   delay_us(4);                            // Quick delay
    bits = (bits - 1);                      // Decrement I2C bit counter
  }
  if (ack)                                  // Need to send ACK to Slave?
    I2C_SDA_L;/                               // Yes, so pull SDA low
  else


I2C_SDA_H;                               // No, so keep SDA high
I2C_SCL_H;                                // SCL = 1
  delay_us(4);                               // Equivalent to sending N(ACK)
  I2C_SCL_L;                                  // SCL = 0
  I2C_SDA_H;                                   // SDA = 1

  return (data);                            // Return 8-bit data byte
}

void BQ34Z100_I2C_writeBlock(unsigned char SlaveAddress,
                                unsigned int numBytes, unsigned char multi,
                                void* TxData)
{
  unsigned int  i;
  unsigned char *temp;

  temp = (unsigned char *)TxData;           // Initialize array pointer
  BQ34Z100_I2C_start();                  // Send Start condition
  BQ34Z100_I2C_txByte(SlaveAddress); // [ADDR] + R/W bit = 0
  for (i = 0; i < numBytes; i++)
  {
    BQ34Z100_I2C_txByte(*(temp));        // Send data and ack
    temp++;                                 // Increment pointer to next element
  }
  if (multi == 0)                           // Need STOP condition?
  {
    BQ34Z100_I2C_stop();                 // Yes, send STOP condition
  }
 delay_us(4);// I2CDELAY;                                 // Quick delay
}

void BQ34Z100_I2C_readBlock(unsigned char SlaveAddress,
                               unsigned int numBytes, void* RxData)
{
  unsigned int  i;
  unsigned char* temp;

  temp = (unsigned char *)RxData;           // Initialize array pointer
  BQ34Z100_I2C_start();                  // Send Start condition
  BQ34Z100_I2C_txByte(SlaveAddress+0x01); // [ADDR] + R/W bit = 1
  for (i = 0; i < numBytes; i++)
  {
    if (i == (numBytes - 1))
      *(temp) = BQ34Z100_I2C_rxByte(0);// Read last 8-bit data with no ACK
    else
      *(temp) = BQ34Z100_I2C_rxByte(1);// Read 8-bit data & then send ACK
    temp++;                                 // Increment pointer to next element
  }
 BQ34Z100_I2C_stop();                   // Send Stop condition
}



unsigned int transBytes2UnsignedInt(unsigned char msb, unsigned char lsb)
{
  unsigned int tmp;

  tmp = ((msb << 8) & 0xFF00);
  return ((unsigned int)(tmp + lsb) & 0x0000FFFF);
}

void BQ34Z100_read(unsigned char cmd, unsigned int bytes)
{
  unsigned char tx[1];

  tx[0] = cmd;

  BQ34Z100_I2C_writeBlock(I2CSLAVEADDR, 1, 1, tx);
  
  BQ34Z100_I2C_readBlock(I2CSLAVEADDR, bytes, RxData);
}
主函数里:读取芯片温度
BQ34Z100_read(0x0C, 2);//读取温度

最佳答案

查看完整内容[请看2#楼]

注意delay的时间就行
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

2

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
112
金钱
112
注册时间
2015-8-17
在线时间
20 小时
 楼主| 发表于 2015-9-6 16:08:41 | 显示全部楼层
小苑 发表于 2018-3-20 16:31
楼主好,我也再用stm32用i2c读取BQ34Z100 信息,也是这样字 ,不知道怎么弄,有成功的代码分享下吗?

注意delay的时间就行
回复

使用道具 举报

3

主题

2170

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
5781
金钱
5781
注册时间
2013-11-22
在线时间
1212 小时
发表于 2015-9-6 22:11:51 | 显示全部楼层
帮顶。。。。
回复

使用道具 举报

3

主题

65

帖子

0

精华

初级会员

Rank: 2

积分
127
金钱
127
注册时间
2014-10-31
在线时间
8 小时
发表于 2015-9-7 09:08:09 | 显示全部楼层
波形都不对,先慢慢检查一下吧,注意点就是I2C SCL SDA 是开漏方式,通过外部上拉才能把电平拉高,而不是你把他设置为输出高
回复

使用道具 举报

2

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
112
金钱
112
注册时间
2015-8-17
在线时间
20 小时
 楼主| 发表于 2015-9-8 16:19:21 | 显示全部楼层
回复【3楼】brook_z:
---------------------------------
#include "config.h"

unsigned char Data_buff[] = {0,4}; 
unsigned char Read_buff[6];
float temperature;   //温度
float humidity; //湿度
void Delay_us(u32 count)
{
count *= 6;
while(count--)
{
__nop();
}
}
/**********************************************************
初始化函数
**************************************************************/
void I2C_initt(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin=I2C_SCL|I2C_SDA;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;
GPIO_Init(GPIOB,&GPIO_InitStructure);

I2C_SCL_H;
I2C_SDA_H;
}
/**********************************************************
I2C_SDA_OUT初始化函数
**************************************************************/
void I2C_SDA_OUT(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
//   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin=I2C_SDA;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
 /**********************************************************
I2C_SDA_IN初始化函数
**************************************************************/
void I2C_SDA_IN(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin=I2C_SDA;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}

 /***************************************************
 下面是I2C协议的基本函数
**************************************************************/



void I2C_start(void) // I2C启动  Start
{
I2C_SDA_OUT();
I2C_SDA_H;
Delay_us(30);
I2C_SCL_H;
Delay_us(60);
I2C_SDA_L;
Delay_us(60);
    I2C_SCL_L;
Delay_us(60);
}
/**************I2C停止************************/
void I2C_stop(void) // I2C停止   Stop

I2C_SDA_OUT();
I2C_SDA_L;
    Delay_us(30);
I2C_SCL_H;
Delay_us(60);
I2C_SDA_H;
Delay_us(60);
}
/************I2C 主接受 继续操作*****************************/
void I2C_Rec_Ack(void) // I2C 主接受,继续操作,确认应答 
{
I2C_SDA_L;
    Delay_us(60);
I2C_SCL_H;
    Delay_us(60);
I2C_SCL_L;
    Delay_us(60);
}
/*********** *****************
I2C 主接受 结束操作
******************************/
void I2C_End_Ack(void) // I2C 主接受,结束操作,确认应答 
{
I2C_SDA_H;
Delay_us(60);
I2C_SCL_H;
Delay_us(60);
I2C_SCL_L;
Delay_us(60);
}
/**********************************
Ack 判断确认
**************************************/

u8 I2C_Test_Ack(void) // I2C 从接受确认应答 
{
unsigned char I2Ctest_time;
u8  Ack_SDA;

    //Delay_us(30);   //360
    I2C_SDA_H;
I2C_SDA_IN(); //设置为输入

    Delay_us(30);
I2C_SCL_H;
Delay_us(30); // wait ACK SDA=0  30
I2Ctest_time = 0;

while (1)
{
//        Delay_us(30);
if(I2C_SDA_READ()==0)
{
Ack_SDA =1;
break;
}
I2Ctest_time++;
if(I2Ctest_time>80)
{
Ack_SDA = 0;
break; // 必须调整为合适的时间间隔
}
}

I2C_SDA_OUT();//设置为输出
I2C_SCL_L;

    Delay_us(30);
return(Ack_SDA);
}
/*******************************************
I2C判断从器件是否忙
I2C_Addr
 0:not busy
1: busy
********************************************/
u8 I2C_CheckBusy(unsigned char I2C_Addr)
{
I2C_stop();
I2C_start();
I2C_send( I2C_Addr + I2C_WAddr );
if(!I2C_Test_Ack())
{
return 1;  //busy
}
else
{
return 0; //not 
}
}

/*******************************************
I2C接收数据
****************************************************/
unsigned char I2C_receive(void)    ////I2C接受 数据从高位到低位
{
unsigned char I2C_data;
unsigned char re_i;

I2C_SDA_H;
I2C_SDA_IN(); //设置为输入
I2C_data = 0;
for(re_i=0; re_i<8; re_i++)
{
I2C_SCL_H;            
Delay_us(30);
I2C_data<<=1;
if(I2C_SDA_READ()==1) 
I2C_data += 1;
I2C_SCL_L;
Delay_us(30);
}
I2C_SDA_OUT();//设置为输出
return(I2C_data);
}
/******************************************************
I2C发送字节数据
**********************************************************/
void I2C_send(unsigned char I2C_data)   // I2C发送

unsigned char sendi;
I2C_SDA_OUT();//设置为输出
for(sendi=0; sendi<8; sendi++)
{
if(I2C_data&0x80)
{
I2C_SDA_H;
}
else
{
I2C_SDA_L;
}

Delay_us(30); // 50
        I2C_SCL_H;
Delay_us(30);  // 50
I2C_data<<=1;
        I2C_SCL_L;
Delay_us(30);  // 50
}
}


/**************************************************************
函数名:I2C_Read
功能  :从24c02随机地址中读入数据  实现页读功能  当Len大于8时,会从该页头开始重复读
传入参数:I2C_Addr: I2C 器件地址
   Data_Addr: 字地址
   Len     :写入字节的长度
传出参数:pData :指向传入参数的指针
返回值:成功返回TURE  失败返回FALSE
****************************************************/
u8 I2C_Read(unsigned char I2C_Addr,unsigned char *pData, unsigned char Len)    // I2C 连续读Len字节
{
unsigned char readi2c;

I2C_start();
I2C_send(I2C_Addr + I2C_RAddr);
if(I2C_Test_Ack())
{
Delay_us(50);

// if(Len>0)
// {
// for(readi2c=0;readi2c<Len;readi2c++)
// {
// *pData = ( I2C_receive() ); pData++;
// I2C_Rec_Ack();
// }
*pData = I2C_receive();

         I2C_End_Ack();
I2C_stop();
return(TRUE);
// }
}

I2C_stop();
return(FALSE);
}



/************************************************************
函数名:I2C_Write
功能  :指定地址中写入数据  
传入参数:I2C_Addr: I2C 器件地址
   Fun_Data: 功能码
   pData :指向传入参数的指针
   Len     :写入字节的长度

返回值:成功返回TURE  失败返回FALSE
****************************************************************/
u8 I2C_Write(unsigned char I2C_Addr, unsigned char Fun_Data, unsigned char *pData, unsigned char Len)
{// I2C 连续写Len字节
unsigned char writei;

I2C_start();
I2C_send(I2C_Addr + I2C_WAddr);
if(I2C_Test_Ack())
{
I2C_send(Fun_Data);
if(I2C_Test_Ack())
{
for(writei=0; writei><Len; writei++)
{
I2C_send( *pData );
pData++;
if(!I2C_Test_Ack())//如果没有应答信号 停止写入
{
I2C_stop();
return(FALSE);
}
}
I2C_stop();
return(TRUE);
}
}
I2C_stop();
return(FALSE);
}

u8 I2C_Write_t(unsigned char I2C_Addr, unsigned char Fun_Data,  unsigned char Len)
{// I2C 连续写Len字节
unsigned char writei;

I2C_start();
I2C_send(I2C_Addr + I2C_WAddr);
if(I2C_Test_Ack())
{
I2C_send(Fun_Data);
if(I2C_Test_Ack())
{

I2C_stop();
return(TRUE);
}
}
I2C_stop();
return(FALSE);
}
/*************************************************************

先唤醒AM2311注意延时处理
*****************************************************************/

unsigned int transBytes2UnsignedInt(unsigned char msb, unsigned char lsb)
{
  unsigned int tmp;

  tmp = ((msb ><< 8) & 0xFF00);
  return ((unsigned int)(tmp + lsb) & 0x0000FFFF);
}
/*************************************************************

根据DATAsheet,先唤醒AM2311注意延时处理
*****************************************************************/
void BQ34Z100_run(void)
  {
// AM2311_Start(BQ34Z100_Addr);//唤醒AM2321温湿度传感器  然后就可以读写器件了  

    I2C_Write_t(BQ34Z100_Addr, FUN_CODE_READ, 2);
//I2C_Write_t(BQ34Z100_Addr,0x0D, 2);

 delay_us(80);
 //I2C_Read(BQ34Z100_Addr, Read_buff, 1);

humidity =transBytes2UnsignedInt(Read_buff[0],Read_buff[1]);
// temperature = transBytes2UnsignedInt(unsigned char msb, unsigned char lsb)

  //delay_ms(1);//这个延时函数不宜过长,

   }
回复

使用道具 举报

2

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
112
金钱
112
注册时间
2015-8-17
在线时间
20 小时
 楼主| 发表于 2015-9-8 16:20:24 | 显示全部楼层
回复【3楼】brook_z:
---------------------------------
为什么发送地址和指令给BQ34Z100时,ACK,有时候有,有时候没有,这个是什么原因
回复

使用道具 举报

3

主题

65

帖子

0

精华

初级会员

Rank: 2

积分
127
金钱
127
注册时间
2014-10-31
在线时间
8 小时
发表于 2015-9-8 16:43:22 | 显示全部楼层
抓波形,肯定有的波形不对,不然不是这个样子,还有一个问题,我以前在调试的时候发现的,比如说你想把SCL 拉高,延时几十us,但是如果延时几十us,但是scl没有变高怎么办,这个时候就会波形不对,就会出现那种缺少clk型号的问题。
   SCL_SET();
    count = 0;
    {
    
        SCL_SET();
    }while(!CHK_SCL() && (count++<5000));    // 等待SCL变高,发送START信号或者RESTART信号
回复

使用道具 举报

2

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
112
金钱
112
注册时间
2015-8-17
在线时间
20 小时
 楼主| 发表于 2015-9-9 09:55:34 | 显示全部楼层
unsigned char Read_buff[6];
void Delay_us(u32 count)
{
count *= 6;
while(count--)
{
__nop();
}
}
/**********************************************************
初始化函数
**************************************************************/
void I2C_initt(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin=I2C_SCL|I2C_SDA;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;
GPIO_Init(GPIOB,&GPIO_InitStructure);

I2C_SCL_H;
I2C_SDA_H;
}
/**********************************************************
I2C_SDA_OUT初始化函数
**************************************************************/
void I2C_SDA_OUT(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
//  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin=I2C_SDA;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
 /**********************************************************
I2C_SDA_IN初始化函数
**************************************************************/
void I2C_SDA_IN(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin=I2C_SDA;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}

 /***************************************************
 下面是I2C协议的基本函数
**************************************************************/



void I2C_start(void) // I2C启动 Start
{
I2C_SDA_OUT();
I2C_SDA_H;
Delay_us(30);
I2C_SCL_H;
Delay_us(60);
I2C_SDA_L;
Delay_us(60);
    I2C_SCL_L;
Delay_us(60);
}
/**************I2C停止************************/
void I2C_stop(void) // I2C停止 Stop

I2C_SDA_OUT();
I2C_SDA_L;
    Delay_us(30);
I2C_SCL_H;
Delay_us(60);
I2C_SDA_H;
Delay_us(60);
}
/************I2C 主接受 继续操作*****************************/
void I2C_Rec_Ack(void) // I2C 主接受,继续操作,确认应答 
{
I2C_SDA_L;
    Delay_us(60);
I2C_SCL_H;
    Delay_us(60);
I2C_SCL_L;
    Delay_us(60);
}
/*********** *****************
I2C 主接受 结束操作
******************************/
void I2C_End_Ack(void) // I2C 主接受,结束操作,确认应答 
{
I2C_SDA_H;
Delay_us(60);
I2C_SCL_H;
Delay_us(60);
I2C_SCL_L;
Delay_us(60);
}
/**********************************
Ack 判断确认
**************************************/

u8 I2C_Test_Ack(void) // I2C 从接受确认应答 
{
unsigned char I2Ctest_time;
u8  Ack_SDA;

    //Delay_us(30);   //360
    I2C_SDA_H;

I2C_SDA_IN(); //设置为输入

    Delay_us(30);
I2C_SCL_H;
Delay_us(30); // wait ACK SDA=0  30
I2Ctest_time = 0;

while (1)
{
//        Delay_us(30);
if(I2C_SDA_READ()==0)
{
Ack_SDA =1;
break;
}
I2Ctest_time++;
if(I2Ctest_time>80)
{
Ack_SDA = 0;
break; // 必须调整为合适的时间间隔
}
}

I2C_SDA_OUT();//设置为输出
Delay_us(30);
I2C_SCL_L;

    Delay_us(30);
return(Ack_SDA);
}
/*******************************************
I2C判断从器件是否忙
I2C_Addr
 0:not busy
1: busy
********************************************/
u8 I2C_CheckBusy(unsigned char I2C_Addr)
{
I2C_stop();
I2C_start();
I2C_send( I2C_Addr + I2C_WAddr );
if(!I2C_Test_Ack())
{
return 1;  //busy
}
else
{
return 0; //not 
}
}

/*******************************************
I2C接收数据
****************************************************/
unsigned char I2C_receive(void)   ////I2C接受 数据从高位到低位
{
unsigned char I2C_data;
unsigned char re_i;

I2C_SDA_H;

I2C_SDA_IN(); //设置为输入
I2C_data = 0;
for(re_i=0; re_i<8; re_i++)
{
I2C_SCL_H;            
Delay_us(30);
I2C_data<<=1;
if(I2C_SDA_READ()==1) 
I2C_data += 1;
I2C_SCL_L;
Delay_us(30);
}
I2C_SDA_OUT();//设置为输出
return(I2C_data);
}
/******************************************************
I2C发送字节数据
**********************************************************/
void I2C_send(unsigned char I2C_data)  // I2C发送

unsigned char sendi;
I2C_SDA_OUT();//设置为输出
for(sendi=0; sendi<8; sendi++)
{
if(I2C_data&0x80)
{
I2C_SDA_H;
}
else
{
I2C_SDA_L;
}

Delay_us(30); // 50
        I2C_SCL_H;
Delay_us(30);  // 50
I2C_data<<=1;
        I2C_SCL_L;
Delay_us(30);  // 50
}
}


/**************************************************************
函数名:I2C_Read
功能  :从24c02随机地址中读入数据  实现页读功能  当Len大于8时,会从该页头开始重复读
传入参数:I2C_Addr : I2C 器件地址
  Data_Addr: 字地址
  Len    :写入字节的长度
传出参数:pData :指向传入参数的指针
返回值:成功返回TURE  失败返回FALSE
****************************************************/
u8 I2C_Read(unsigned char I2C_Addr,unsigned char *pData, unsigned char Len)   // I2C 连续读Len字节
{
unsigned char readi2c;

I2C_start();
I2C_send(I2C_Addr + I2C_RAddr);
if(I2C_Test_Ack())
{
Delay_us(50);

// if(Len>0)
// {
// for(readi2c=0;readi2c<Len;readi2c++)
// {
// *pData = ( I2C_receive() ); pData++;
// I2C_Rec_Ack();
// }
*pData = I2C_receive();

        I2C_End_Ack();
I2C_stop();
return(TRUE);
// }
}

I2C_stop();
return(FALSE);
}



/************************************************************
函数名:I2C_Write
功能  :指定地址中写入数据  
传入参数:I2C_Addr : I2C 器件地址
  Fun_Data: 功能码
  pData :指向传入参数的指针
  Len    :写入字节的长度

返回值:成功返回TURE  失败返回FALSE
****************************************************************/
u8 I2C_Write(unsigned char I2C_Addr, unsigned char Fun_Data, unsigned char *pData, unsigned char Len)
{// I2C 连续写Len字节
unsigned char writei;

I2C_start();
I2C_send(I2C_Addr + I2C_WAddr);
if(I2C_Test_Ack())
{
I2C_send(Fun_Data);
if(I2C_Test_Ack())
{
for(writei=0; writei<Len; writei++)
{
I2C_send( *pData );
pData++;
if(!I2C_Test_Ack())//如果没有应答信号 停止写入
{
I2C_stop();
return(FALSE);
}
}
I2C_stop();
return(TRUE);
}
}
I2C_stop();
return(FALSE);
}

u8 I2C_Write_t(unsigned char I2C_Addr, unsigned char Fun_Data,  unsigned char Len)
{// I2C 连续写Len字节
unsigned char writei;

I2C_start();
I2C_send(I2C_Addr + I2C_WAddr);
delay_us(200);
if(I2C_Test_Ack())
{
I2C_send(Fun_Data);
delay_us(200);
if(I2C_Test_Ack())
{

I2C_stop();
return(TRUE);
}
}
I2C_stop();
return(FALSE);
}
/*************************************************************

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

unsigned int transBytes2UnsignedInt(unsigned char msb, unsigned char lsb)
{
  unsigned int tmp;

  tmp = ((msb << 8) & 0xFF00);
  return ((unsigned int)(tmp + lsb) & 0x0000FFFF);
}
/*************************************************************


*****************************************************************/
void BQ34Z100_run(void)
  {

   I2C_Write_t(BQ34Z100_Addr, FUN_CODE_READ, 2);
// delay_us(80);
//I2C_Read(BQ34Z100_Addr, Read_buff, 1);

  }


回复

使用道具 举报

2

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
112
金钱
112
注册时间
2015-8-17
在线时间
20 小时
 楼主| 发表于 2015-9-9 09:58:17 | 显示全部楼层
回复【6楼】brook_z:
---------------------------------
这帖子下面,我发了波形上去了,好像也对的,但单步调的时候ACK有时候有,有时候没有,我先发地址0xAA,第九个时钟等应答ACK,再发寄存器地址FUN_CODE_READ=0x08,
回复

使用道具 举报

3

主题

65

帖子

0

精华

初级会员

Rank: 2

积分
127
金钱
127
注册时间
2014-10-31
在线时间
8 小时
发表于 2015-9-9 10:45:41 | 显示全部楼层
现在波形不是按照你发送的数据回的么,是对的,主要还有一点就是,怎么消除SDA上面短时间变高的波形,哪个波形主要是在你转方向的时候产生的。
输入模式改为悬浮输入GPIO_Mode_IN_FLOATING,你外部是不是有上拉么?为什么还要输入上拉。有时候没有是不是BQ 休眠没有响应哦,
回复

使用道具 举报

3

主题

65

帖子

0

精华

初级会员

Rank: 2

积分
127
金钱
127
注册时间
2014-10-31
在线时间
8 小时
发表于 2015-9-9 10:49:46 | 显示全部楼层
还有你的频率有点低你没有发现?怎么才12k多一点,把频率提高一点吧
回复

使用道具 举报

2

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
112
金钱
112
注册时间
2015-8-17
在线时间
20 小时
 楼主| 发表于 2015-9-9 11:24:11 | 显示全部楼层
我把void I2C_SDA_IN(void)里的GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;了,波形那个画红标记的第一处还是那样有一点高电平,还有一处,我改过了读取SDA  的延迟时间
在u8 I2C_Test_Ack(void)函数里
if(I2C_SDA_READ()==0)
{
Ack_SDA =1;
break;
}
I2Ctest_time++;
if(I2Ctest_time>50)原来是40; // 必须调整为合适的时间间隔
{
Ack_SDA = 0;
break; 
}
}
波形如下




回复

使用道具 举报

2

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
112
金钱
112
注册时间
2015-8-17
在线时间
20 小时
 楼主| 发表于 2015-9-9 11:25:00 | 显示全部楼层
回复【10楼】brook_z:
---------------------------------
我把改过的截图发到这个帖子上了,还有这频率怎么改呢,
回复

使用道具 举报

3

主题

65

帖子

0

精华

初级会员

Rank: 2

积分
127
金钱
127
注册时间
2014-10-31
在线时间
8 小时
发表于 2015-9-9 11:31:09 | 显示全部楼层
I2C_receive()与I2C_send 改为delay_us(30)改为10

u8 I2C_Write_t(unsigned char I2C_Addr, unsigned char Fun_Data,  unsigned char Len)
{// I2C 连续写Len字节
unsigned char writei;

I2C_start();
I2C_send(I2C_Addr + I2C_WAddr);
delay_us(100);
if(I2C_Test_Ack())
{
delay_us(100);
I2C_send(Fun_Data);
delay_us(100);
if(I2C_Test_Ack())
{

I2C_stop();
return(TRUE);
}
}
I2C_stop();
return(FALSE);
}
回复

使用道具 举报

2

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
112
金钱
112
注册时间
2015-8-17
在线时间
20 小时
 楼主| 发表于 2015-9-9 12:14:16 | 显示全部楼层
u8 I2C_Write_t(unsigned char I2C_Addr, unsigned char Fun_Data,  unsigned char Len)
{// I2C 连续写Len字节
unsigned char writei;

I2C_start();
I2C_send(I2C_Addr + I2C_WAddr);
delay_us(100);
if(I2C_Test_Ack())
{  delay_us(100);  //
I2C_send(Fun_Data);
delay_us(100);//
if(I2C_Test_Ack())
{

I2C_stop();
return(TRUE);
}
}
I2C_stop();
return(FALSE);
}改后的,还是一样ACK,时有时无
 I2C_send和I2C_receive也该了


回复

使用道具 举报

2

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
112
金钱
112
注册时间
2015-8-17
在线时间
20 小时
 楼主| 发表于 2015-9-9 12:15:01 | 显示全部楼层
回复【13楼】brook_z:
---------------------------------
改过了,图贴上去了,ACK还是有问题
回复

使用道具 举报

3

主题

65

帖子

0

精华

初级会员

Rank: 2

积分
127
金钱
127
注册时间
2014-10-31
在线时间
8 小时
发表于 2015-9-9 13:50:55 | 显示全部楼层
ACK还有什么问题。波形不是都ok了么?
回复

使用道具 举报

3

主题

65

帖子

0

精华

初级会员

Rank: 2

积分
127
金钱
127
注册时间
2014-10-31
在线时间
8 小时
发表于 2015-9-9 14:04:42 | 显示全部楼层
你自己函数还有问题,你写数据,只写了AA + 08 ?
后面不是还有数据内容么?
回复

使用道具 举报

3

主题

65

帖子

0

精华

初级会员

Rank: 2

积分
127
金钱
127
注册时间
2014-10-31
在线时间
8 小时
发表于 2015-9-9 14:11:51 | 显示全部楼层
u8 I2C_Test_Ack(void) // I2C 从接受确认应答 
{
unsigned char I2Ctest_time;
u8  Ack_SDA;

    //Delay_us(30);   //360
    I2C_SDA_H;

I2C_SDA_IN(); //设置为输入

    Delay_us(30);
I2C_SCL_H;
Delay_us(30); // wait ACK SDA=0  30
I2Ctest_time = 0;

while (1)
{
       Delay_us(10); --------增加这个延时
if(I2C_SDA_READ()==0)
{
Ack_SDA =1;
break;
}
I2Ctest_time++;
if(I2Ctest_time>80)
{
Ack_SDA = 0;
break; // 必须调整为合适的时间间隔
}
}

I2C_SDA_OUT();//设置为输出
Delay_us(30);
I2C_SCL_L;

    Delay_us(30);
return(Ack_SDA);
}
请问: I2Ctest_time >80这个时间够不够啊?
t(RSPS) Response time, bq34z100 to host 190 950 μs
规格书写的很清楚,最小190us,你在查ACK里面加一个延时,10ms,你在看一下
回复

使用道具 举报

2

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
112
金钱
112
注册时间
2015-8-17
在线时间
20 小时
 楼主| 发表于 2015-9-9 14:12:30 | 显示全部楼层
回复【17楼】brook_z:
---------------------------------
我现在把那个的//I2C_Read(BQ34Z100_Addr, Read_buff, 1);不渎
void BQ34Z100_run(void)
  {

   I2C_Write_t(BQ34Z100_Addr, FUN_CODE_READ, 2);
// delay_us(80);
//I2C_Read(BQ34Z100_Addr, Read_buff, 1);

  }
那个波形 是只写了AA + 08 的
回复

使用道具 举报

3

主题

65

帖子

0

精华

初级会员

Rank: 2

积分
127
金钱
127
注册时间
2014-10-31
在线时间
8 小时
发表于 2015-9-9 14:19:33 | 显示全部楼层
你的意思是你先发S+AA+08 +P,然后发现S+AB+读取内容+P?
这个关系不应该是 S +AA+08+ RS+ AB+内容 +P。
回复

使用道具 举报

2

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
112
金钱
112
注册时间
2015-8-17
在线时间
20 小时
 楼主| 发表于 2015-9-9 14:26:28 | 显示全部楼层
回复【20楼】brook_z:
---------------------------------
RS是什么?该怎么写
回复

使用道具 举报

3

主题

65

帖子

0

精华

初级会员

Rank: 2

积分
127
金钱
127
注册时间
2014-10-31
在线时间
8 小时
发表于 2015-9-9 14:34:03 | 显示全部楼层
也就是start仔细看规格书,严格按照它的时序来,就没有什么问题了
回复

使用道具 举报

2

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
112
金钱
112
注册时间
2015-8-17
在线时间
20 小时
 楼主| 发表于 2015-9-9 14:36:15 | 显示全部楼层
回复【20楼】brook_z:
---------------------------------
我有一个疑问
void Delay_us(u32 count)
{
count *= 6;
while(count--)
{
__nop();
}
}
这个函数是我以前读写AM3211温湿度传感器的,也没有测试过准不准,那些I2C的START和stop都之间的延时是以前的,我直接用过了,影响大吗,
回复

使用道具 举报

3

主题

65

帖子

0

精华

初级会员

Rank: 2

积分
127
金钱
127
注册时间
2014-10-31
在线时间
8 小时
发表于 2015-9-9 14:50:23 | 显示全部楼层
影响不大。这个没有关系,i2c看的是主要时序,具体频率多少,超时定多少,有个大致范围就好了
回复

使用道具 举报

2

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
112
金钱
112
注册时间
2015-8-17
在线时间
20 小时
 楼主| 发表于 2015-9-9 14:58:08 | 显示全部楼层
回复【24楼】brook_z:
---------------------------------
我能收到ACK是不是说明基本的START和STOP没多大问题,但一直有时候有,有什么没有ACK,主要是哪块存在问题,我感觉应该是

u8 I2C_Test_Ack(void) // 的问题,但不知道怎么改好.
回复

使用道具 举报

3

主题

65

帖子

0

精华

初级会员

Rank: 2

积分
127
金钱
127
注册时间
2014-10-31
在线时间
8 小时
发表于 2015-9-9 15:21:21 | 显示全部楼层
u8 I2C_Test_Ack(void) // I2C 从接受确认应答  

unsigned char I2Ctest_time; 
u8  Ack_SDA; 

    //Delay_us(30);   //360 
    I2C_SDA_H; 

I2C_SDA_IN(); //设置为输入 

    Delay_us(30); 
I2C_SCL_H; 
Delay_us(30); // wait ACK SDA=0  30 
I2Ctest_time = 0; 

while (1) 

       Delay_us(10); --------增加这个延时 
if(I2C_SDA_READ()==0) 

Ack_SDA =1; 
break; 

I2Ctest_time++; 
if(I2Ctest_time>80) 

Ack_SDA = 0; 
break; // 必须调整为合适的时间间隔 



I2C_SDA_OUT();//设置为输出 
Delay_us(30); 
I2C_SCL_L; 

    Delay_us(30); 
return(Ack_SDA); 

请问: I2Ctest_time >80这个时间够不够啊? 
t(RSPS) Response time, bq34z100 to host 190 950 μs 
规格书写的很清楚,最小190us,你在查ACK里面加一个延时,10ms,你在看一下
回复

使用道具 举报

2

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
112
金钱
112
注册时间
2015-8-17
在线时间
20 小时
 楼主| 发表于 2015-9-9 15:51:47 | 显示全部楼层
回复【26楼】brook_z:
-------------------------------还是一样,ACK不稳定
回复

使用道具 举报

2

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
112
金钱
112
注册时间
2015-8-17
在线时间
20 小时
 楼主| 发表于 2015-9-10 14:27:26 | 显示全部楼层
回复【26楼】brook_z:
---------------------------------
现在我单独谢都有ACK了,但一起读写
   I2C_Write_t(BQ34Z100_Addr, FUN_CODE_READ, 2,0);
//  delay_us(80);
 I2C_Read(BQ34Z100_Addr, Read_buff, 1);
之所以会有ACK时有时无是因为,有些波形,有START,那么就有ACK,有些波形没有STATT信号,就没有ACK,图片附上了,这一起读写的时,整个波形,有的有START,但没有STOP,有些却:没有START,但有STOP,感觉好奇怪
回复

使用道具 举报

2

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
112
金钱
112
注册时间
2015-8-17
在线时间
20 小时
 楼主| 发表于 2015-9-10 14:30:19 | 显示全部楼层

回复

使用道具 举报

2

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
112
金钱
112
注册时间
2015-8-17
在线时间
20 小时
 楼主| 发表于 2015-9-10 14:31:10 | 显示全部楼层
回复【26楼】brook_z:
---------------------------------
单独操作读或写都有ACK回复的,
回复

使用道具 举报

8

主题

20

帖子

0

精华

新手上路

积分
37
金钱
37
注册时间
2015-9-21
在线时间
17 小时
发表于 2015-10-17 15:51:17 | 显示全部楼层
我想请问下楼主,我现在也想用BQ34Z100做电源检测,这个芯片好像需要配置,要怎样弄啊,是通过TI的那个配置软件弄吗?还是直接用IIC去写?
回复

使用道具 举报

0

主题

3

帖子

0

精华

新手上路

积分
22
金钱
22
注册时间
2016-4-13
在线时间
3 小时
发表于 2016-4-13 11:36:11 | 显示全部楼层
楼主好,我也想用STM32 做电源电量监测,你这个程序能不能分享给我参考下呀,谢谢。qqgirlwyh@163.com 或者是qq3313548247 。
回复

使用道具 举报

1

主题

8

帖子

0

精华

初级会员

Rank: 2

积分
69
金钱
69
注册时间
2014-9-15
在线时间
6 小时
发表于 2018-3-20 16:31:01 | 显示全部楼层
楼主好,我也再用stm32用i2c读取BQ34Z100 信息,也是这样字 ,不知道怎么弄,有成功的代码分享下吗?
回复

使用道具 举报

1

主题

8

帖子

0

精华

初级会员

Rank: 2

积分
69
金钱
69
注册时间
2014-9-15
在线时间
6 小时
发表于 2018-4-4 11:48:59 | 显示全部楼层
ZGFZGF 发表于 2018-3-22 17:21
注意delay的时间就行

好像是的,后来延时加长在加长就好了。。。。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-16 19:54

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表