STM32F207ZGT中I2C SMBUS总线如何主模式读写?

2019-07-21 06:40发布


STM32F207ZGT中I2C SMBUS总线如何主模式读写? 


我需要使用STM32F207作为主模式,读电池的芯片BQ2060作为从模式走SMBUS总线,下面是我的一些基本设置和代码信息:
void  Battery_Init()
{
        I2C_InitTypeDef  I2C_InitStructure;

        Battery_LowLevel_Init();        
        /* I2C1 configuration: SMBus Host */
        I2C_InitStructure.I2C_Mode = I2C_Mode_SMBusHost;               //设置基于SMBUS的主模式
        I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
        I2C_InitStructure.I2C_OwnAddress1 = I2C_SLAVE_ADDRESS7;//I2C_SLAVE_ADDRESS7=0x16从设备电池的地址
        I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
        I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
        I2C_InitStructure.I2C_ClockSpeed = I2C_SPEED;                   //I2C_SPEED=100000
        /* Apply sEE_I2C configuration after enabling it */        
        I2C_Init(I2C1, &I2C_InitStructure);        //初始化设置
        /* I2C Peripheral Enable */
        I2C_Cmd(I2C1, ENABLE);                                //使能I2C1
}


//下面是我使用STM32F207ZGT作为主模式,电池芯片bq20600作为从模式,对电池芯片的进行读,代码如下:
//I2Cx I2C1
//pBuffer 接收缓存
//CommandCode 字节地址
//NumByteToRead = 2读的字节数
uint32_t I2C_BatteryMasterReadbuffer(I2C_TypeDef* I2Cx,uint8_t* pBuffer, uint8_t CommandCode, uint16_t NumByteToRead)
{
        /*----- receiver Phase -----*/
        BatteryTimeout = BATTERY_LONG_TIMEOUT;
        while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY))
        {
                if((BatteryTimeout--) == 0) return sEE_TIMEOUT_UserCallback();
        }
        /* Send I2C1 START condition */
        I2C_GenerateSTART(I2Cx, ENABLE);

        /* Test on I2C1 EV5 and clear it */
  BatteryTimeout = BATTERY_FLAG_TIMEOUT;
        while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT))
        {
                if((BatteryTimeout--) == 0) return sEE_TIMEOUT_UserCallback();
        }

        /* Send Slave address */
    I2C_Send7bitAddress(I2Cx, SMBusDefaultHeader, I2C_Direction_Transmitter);//SMBusDefaultHeader为电池地址0x16
        
          /* Clear EV6 by setting again the PE bit */
//    I2C_Cmd(I2C1, DISABLE);
        /* Test on I2C1 EV6 and clear it */
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
        {
                if((BatteryTimeout--) == 0) return sEE_TIMEOUT_UserCallback();
        } 


        /* Send Command */
         I2C_SendData(I2Cx, CommandCode);
                
        /*!< Test on EV8_2 and clear it */
         BatteryTimeout = BATTERY_FLAG_TIMEOUT;
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
    {
            if((BatteryTimeout--) == 0) return sEE_TIMEOUT_UserCallback();
    }

        /* Send I2C1 START condition */
        I2C_GenerateSTART(I2Cx, ENABLE);

                /*!< Test on EV5 and clear it (cleared by reading SR1 then writing to DR) */
        BatteryTimeout = BATTERY_FLAG_TIMEOUT;
        while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT))
        {
                if((BatteryTimeout--) == 0) return sEE_TIMEOUT_UserCallback();
        } 
        /* Send Slave address */
  I2C_Send7bitAddress(I2Cx, SMBusDefaultHeader, I2C_Direction_Receiver);

  /*!< Test on EV6 and clear it */
  BatteryTimeout = BATTERY_FLAG_TIMEOUT;
  while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
  {
                if((BatteryTimeout--) == 0) return sEE_TIMEOUT_UserCallback();
  }  

        while(NumByteToRead) 
        {
                if(I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)) //读取数据
                { 
                        //调用库函数将数据取出到 pBuffer
                        *pBuffer = I2C_ReceiveData(I2Cx);
                        pBuffer++; //指针移位
                        NumByteToRead--;//字节数减 1 
                        I2C_AcknowledgeConfig(I2Cx, ENABLE); 
                        /*!< Test on EV7 and clear it */
                        BatteryTimeout = BATTERY_FLAG_TIMEOUT;
                        while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED))
                        {
                                if((BatteryTimeout--) == 0) return sEE_TIMEOUT_UserCallback();
                        }  
                }                 
                
                if ((uint16_t)(NumByteToRead) == 1)
                {
                        /* Wait on ADDR flag to be set (ADDR is still not cleared at this level */
//                         BatteryTimeout = BATTERY_FLAG_TIMEOUT;
//                         while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_ADDR) == RESET)
//                         {
//                                 if((BatteryTimeout--) == 0) return sEE_TIMEOUT_UserCallback();
//                         }     
                        
                        /*!< Disable Acknowledgment */
                        I2C_AcknowledgeConfig(I2Cx, DISABLE);   
                        
                        /* Clear ADDR register by reading SR1 then SR2 register (SR1 has already been read) */
                        (void)I2Cx->SR2;
                        
                        /*!< Send STOP Condition */
                        I2C_GenerateSTOP(I2Cx, ENABLE);
                        
                        /* Wait for the byte to be received */
                        while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_RXNE) == RESET)
                        {
                                if((BatteryTimeout--) == 0) return sEE_TIMEOUT_UserCallback();
                        }
                        
                                *pBuffer = I2C_ReceiveData(I2Cx);        
                                NumByteToRead--;                        
                                
                        BatteryTimeout = BATTERY_FLAG_TIMEOUT;
//                         while(I2Cx->CR1 & I2C_CR1_STOP)
//                         {
//                                 if((BatteryTimeout--) == 0) return sEE_TIMEOUT_UserCallback();
//                         }  
                        /*!< Re-Enable Acknowledgment to be ready for another reception */
                        I2C_AcknowledgeConfig(I2Cx, ENABLE); 
                        return Battery_OK;
                }
        }
                return Battery_OK;        
}

其中,使用F10单步跟进,
执行完
        /* Send I2C1 START condition */
        I2C_GenerateSTART(I2Cx, ENABLE);
I2C寄存器地址出现如下图片,

     之后程序就死在了下面EV5的部分,不知道怎么解决,请求STM32高手指点:
   /* Test on I2C1 EV5 and clear it */
  BatteryTimeout = BATTERY_FLAG_TIMEOUT;
        while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT))
        {
                if((BatteryTimeout--) == 0) return sEE_TIMEOUT_UserCallback();
        }

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。