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();
}
大家知道为什么原子哥的积分这么高吗。
因为随处可见就是原子哥发的:“帮顶。。。。。”。
一周热门 更多>