2 beijidejiaobu beijidejiaobu 于 2015.06.17 13:55 提问

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

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();
}
图片说明

1个回答

zwave
zwave   2015.06.18 15:25

程序这么多,很难看完。给你一个建议,先把从机的 读,写时序每个步骤搞清楚,然后按照从机的时序来写主机的每一个读写动作。刚好这里有个参考。http://blog.sina.com.cn/s/blog_b5e6d3de0102vjn4.html

Csdn user default icon
上传中...
上传图片
插入图片