STM32读取bq33100数据——硬件IIC

背景:拟采用bq33100超级电容管理芯片,实现自动的超级电容组的均压任务。需监控芯片的工作情况,以及电容组的均压情况。

平台:

硬件:STM32F103C8T6

通信:SMBus(低速IIC)

目标芯片:bq33100(TI)

SMbus简介:SMBus其实就是低速的IIC,和IIC协议基本相同,速度限制在10K~100KHz之间,一般应用于电源管理芯片等。

通信方式说明:这里考虑到SMBus需要限制IIC的速度,而通常使用的软件模拟IIC,我目前不清楚具体其通讯速率,而且我发现很多类似电源管理芯片的通信都是直接使用的硬件IIC,因此决定试一下硬件IIC的方式。由于STM32的硬件IIC普遍反映不是太稳定,可能会不定时卡死,这里参考野火的硬件IIC的历程中做了相应的超时处理(一旦卡死,就放弃本次的IIC通信),在实际的使用过程中,基本从来没有出现过触发这个卡死处理机制的情况(也就是说,其实可以尝试取消掉超时处理),但是这里以防万一还是选择保留。

配置代码:

void vIicConfig(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	I2C_InitTypeDef I2C_InitStructure;
	
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
	RCC_APB1PeriphClockCmd( RCC_APB1Periph_I2C1, ENABLE );
	
	/* GPIO.B6(IIC1_SCL) GPIO.B7(IIC1_SDA) */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
	GPIO_Init( GPIOB, &GPIO_InitStructure );
	
	/* can try to set to smbus mode */
	I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
	I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
	I2C_InitStructure.I2C_OwnAddress1 = HUST_ADDRESS;
	I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
	I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
	/* smbus require frequency between 100KHz and 10KHz -> 10K */
	I2C_InitStructure.I2C_ClockSpeed = I2C_Speed;
	
	I2C_Cmd( I2C1, ENABLE );
	I2C_Init( I2C1, &I2C_InitStructure );
	
	/* enable iic acknowledge */
	I2C_AcknowledgeConfig( I2C1, ENABLE );
}

IIC读数据函数封装:(含超时处理以及错误报告)

/* for bq33100 chip realtime monitoring (just read base data) */
uint8_t I2C_Hardware_BufferRead(u8* pBuffer, u8 ReadAddr, u16 NumByteToRead)
{
  I2CTimeout = I2C_LONG_TIMEOUT;
  
  while(I2C_GetFlagStatus(IIC1, I2C_FLAG_BUSY))
  {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(9);
  }
  
  /* Send START condition */
  I2C_GenerateSTART(IIC1, ENABLE);
  
  I2CTimeout = I2C_SHORT_TIMEOUT;
  /* Test on EV5 and clear it */
  while(!I2C_CheckEvent(IIC1, I2C_EVENT_MASTER_MODE_SELECT))
  {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(10);
  }
  
  /* Send EEPROM address for write */
  I2C_Send7bitAddress(IIC1, BQ33100_DEVICE_ADDRESS, I2C_Direction_Transmitter);

  I2CTimeout = I2C_SHORT_TIMEOUT;
  /* Test on EV6 and clear it */
  while(!I2C_CheckEvent(IIC1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
  {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(11);
  }
    
  /* Clear EV6 by setting again the PE bit */
  I2C_Cmd(IIC1, ENABLE);

  /* Send the EEPROM's internal address to write to */
  I2C_SendData(IIC1, ReadAddr);  

   
  I2CTimeout = I2C_SHORT_TIMEOUT;
  /* Test on EV8 and clear it */
  while(!I2C_CheckEvent(IIC1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
  {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(12);
  }
    
  /* Send STRAT condition a second time */  
  I2C_GenerateSTART(IIC1, ENABLE);
  
  I2CTimeout = I2C_SHORT_TIMEOUT;
  /* Test on EV5 and clear it */
  while(!I2C_CheckEvent(IIC1, I2C_EVENT_MASTER_MODE_SELECT))
  {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(13);
  }
    
  /* Send EEPROM address for read */
  I2C_Send7bitAddress(IIC1, BQ33100_DEVICE_ADDRESS, I2C_Direction_Receiver);
  
  I2CTimeout = I2C_SHORT_TIMEOUT;
  /* Test on EV6 and clear it */
  while(!I2C_CheckEvent(IIC1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
  {
    if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(14);
  }
  
  /* While there is data to be read */
  while(NumByteToRead)  
  {
    if(NumByteToRead == 1)
    {
      /* Disable Acknowledgement */
      I2C_AcknowledgeConfig(IIC1, DISABLE);
      
      /* Send STOP Condition */
      I2C_GenerateSTOP(IIC1, ENABLE);
    }

    /* Test on EV7 and clear it */    
    I2CTimeout = I2C_LONG_TIMEOUT;
    
		while(I2C_CheckEvent(IIC1, I2C_EVENT_MASTER_BYTE_RECEIVED)==0)  
		{
			if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(3);
		}
    {      
      /* Read a byte from the EEPROM */
      *pBuffer = I2C_ReceiveData(IIC1);

      /* Point to the next location where the byte read will be saved */
      pBuffer++; 
      
      /* Decrement the read bytes counter */
      NumByteToRead--;        
    }   
  }

  /* Enable Acknowledgement to be ready for another reception */
  I2C_AcknowledgeConfig(IIC1, ENABLE);
  
  return 0;
}

/* hardware iic block processing */
static uint8_t I2C_TIMEOUT_UserCallback(uint8_t errorCode)
{
  Error_Report(errorCode);
  
  return errorCode;
}

/* report error information for debug */
static void Error_Report(uint8_t errorcode)
{
	if(errorcode != 0)
	{
		
	}
}

bq33100通信函数示例:(只截取其中2个)

/* read health percent */
void bq33100_readhealthpercent(void)
{
	uint8_t origin_healthpercent;
		
	bq33100.healthpercent_errorcode = I2C_Hardware_BufferRead(&origin_healthpercent,Health_ADD,1);
	
	bq33100.healthpercent = origin_healthpercent;
}

/* read capacitance */
void bq33100_readcapacitance(void)
{
	uint8_t temp[2];
	uint16_t tmp = 0;
	uint16_t origin_capacitance = 0;
	
	bq33100.capacitance_errorcode = I2C_Hardware_BufferRead(temp,Capacitance_ADD,2);

	tmp = (((uint16_t)temp[1] << 8) & 0xFF00);
	
	origin_capacitance = ((u16)(tmp + temp[0]) & 0xFFFF);
		
	bq33100.capacitance_mF = (float)origin_capacitance*1000;
}

 ——cloud over sky

——2020/3/1
 

 

 

 

 

posted @ 2020-03-08 23:48  Yu_tiann  阅读(442)  评论(0编辑  收藏  举报