问题一:STM32的I2C里那个BUSY位,置1的条件是SDA或SCL为低,是包括自己发起传输时将SDA和SCL拉低吗,是否意思是,不管这两条线是谁拉低的,只要有一根线出现低电平就置位BUSY?清除的条件是检测到STOP,那这个STOP是包括自己发出的STOP的 还是总线上其它器件产生的?
Bit 1 BUSY: Bus busy
0: No communication on the bus
1: Communication ongoing on the bus
–Set by hardware on detection of SDA or SCL low
–cleared by hardware on detection of a Stop condition.
It indicates a communication in progress on the bus. This information is still updated when
the interface is disabled (PE=0).
问题二:STM32108PKT I2C-E2PROM例程里,I2C_Comm_MasterSend函数里发送完数据后最后有一段 "/* launch check write status procedure */"的代码,又等待1s,等待总线空闲,发start,address,stop什么的,有什么用?我去掉这一段的话,在发送函数之后需要加一段延时才能跟接收函数,否则返回ADDR_MATCH_ERR 错误,这又是为什么,因为本身接收函数里就有一等待/判断总线空闲代码
I2C_Result I2C_Comm_MasterSend(I2C_TypeDef* I2Cx, uint16_t slaveaddr, uint8_t offset, uint8_t* pBuffer, uint32_t length)
{
__IO uint32_t check_time = 0;
/*wait 5us min for bus free time limitation for later transaction*/
*(uint32_t *)0xe000e014 = one_us_unit*5; //SysTick_SetReload(one_us_unit*5);
*(uint32_t *)0xe000e018 = 0; //SysTick_CounterCmd(SysTick_Counter_Clear);
*(uint32_t *)0xe000e010 |= 1; //SysTick_CounterCmd(SysTick_Counter_Enable);
while(!I2C_OT);
*(uint32_t *)0xe000e010 &= 0xfffffffe; //SysTick_CounterCmd(SysTick_Counter_Disable);
I2C_OT = FALSE;
/*wait bus free*/
*(uint32_t *)0xe000e014 = BUS_BUSY_TIMEOUT; //SysTick_SetReload(BUS_BUSY_TIMEOUT);
*(uint32_t *)0xe000e018 = 0; //SysTick_CounterCmd(SysTick_Counter_Clear);
*(uint32_t *)0xe000e010 |= 1; //SysTick_CounterCmd(SysTick_Counter_Enable);
while((I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY))&&(!I2C_OT));
*(uint32_t *)0xe000e010 &= 0xfffffffe; //SysTick_CounterCmd(SysTick_Counter_Disable);
if (I2C_OT)
{
I2C_OT = FALSE;
return BUS_BUSY;
}
/*send start and wait*/
I2C_GenerateSTART(I2Cx, ENABLE);
*(uint32_t *)0xe000e014 = SEND_START_TIMEOUT; //SysTick_SetReload(SEND_START_TIMEOUT);
*(uint32_t *)0xe000e018 = 0; //SysTick_CounterCmd(SysTick_Counter_Clear);
*(uint32_t *)0xe000e010 |= 1; //SysTick_CounterCmd(SysTick_Counter_Enable);
while(!(I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT) || I2C_OT));
*(uint32_t *)0xe000e010 &= 0xfffffffe; //SysTick_CounterCmd(SysTick_Counter_Disable);
if (I2C_OT)
{
I2C_OT = FALSE;
return SEND_START_ERR;
}
/* send 7-bit slave address and wait */
I2C_Send7bitAddress(I2Cx, (u8)(slaveaddr & 0xFF), I2C_Direction_Transmitter);
*(uint32_t *)0xe000e014 = SEND_ADDR7_TIMEOUT; //SysTick_SetReload(SEND_ADDR7_TIMEOUT);
*(uint32_t *)0xe000e018 = 0; //SysTick_CounterCmd(SysTick_Counter_Clear);
*(uint32_t *)0xe000e010 |= 1; //SysTick_CounterCmd(SysTick_Counter_Enable);
while(!(I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) || I2C_OT));
*(uint32_t *)0xe000e010 &= 0xfffffffe; //SysTick_CounterCmd(SysTick_Counter_Disable);
if (I2C_OT)
{
I2C_OT = FALSE;
I2C_GenerateSTOP(I2Cx, ENABLE);
while ((I2Cx->CR1 & 0x200) == 0x200); //wait while stop bit not cleared
if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF))
I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
return ADDR_MATCH_ERR;
}
/* send offset if needed */
if (offset != 0xff)
{
I2C_SendData(I2Cx, offset);
*(uint32_t *)0xe000e014 = SEND_DATA_TIMEOUT; //SysTick_SetReload(SEND_DATA_TIMEOUT);
*(uint32_t *)0xe000e018 = 0; //SysTick_CounterCmd(SysTick_Counter_Clear);
*(uint32_t *)0xe000e010 |= 1; //SysTick_CounterCmd(SysTick_Counter_Enable);
while(!(I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED) || I2C_OT));
*(uint32_t *)0xe000e010 &= 0xfffffffe; //SysTick_CounterCmd(SysTick_Counter_Disable);
if (I2C_OT)
{
I2C_OT = FALSE;
I2C_GenerateSTOP(I2Cx, ENABLE);
while ((I2Cx->CR1 & 0x200) == 0x200); //wait while stop bit not cleared
if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF))
I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
return DATA_TIMEOUT;
}
}
I2C_SendData(I2Cx, *pBuffer++);
length--;
while (length--)
{
*(uint32_t *)0xe000e014 = SEND_DATA_TIMEOUT;
*(u32 *)0xe000e018 = 0;
*(uint32_t *)0xe000e010 |= 1;
while (((I2C_GetLastEvent(I2Cx) & 0x04) != 0x04)&&(!I2C_OT));
*(uint32_t *)0xe000e010 &= 0xfffffffe;
if (I2C_OT)
{
I2C_OT = FALSE;
I2C_GenerateSTOP(I2Cx, ENABLE);
while ((I2Cx->CR1 & 0x200) == 0x200);
if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF))
I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
return DATA_TIMEOUT;
}
I2C_SendData(I2Cx, *pBuffer++);
}
*(uint32_t *)0xe000e014 = SEND_DATA_TIMEOUT;
*(uint32_t *)0xe000e018 = 0;
*(uint32_t *)0xe000e010 |= 1;
while (!(I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED) || I2C_OT));
*(uint32_t *)0xe000e010 &= 0xfffffffe;
if (I2C_OT)
{
I2C_OT = FALSE;
I2C_GenerateSTOP(I2Cx, ENABLE);
while ((I2Cx->CR1 & 0x200) == 0x200);
if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF))
I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
return DATA_TIMEOUT;
}
/* send stop to close communication */
I2C_GenerateSTOP(I2Cx, ENABLE);
/* launch check write status procedure */能力 //以下代码毛用?
while(check_time != 1000000/5)
{
/*wait 5us min for bus free time limitation for later transaction : check phase*/
*(uint32_t *)0xe000e014 = one_us_unit*5; //SysTick_SetReload(one_us_unit*5);
*(uint32_t *)0xe000e018 = 0; //SysTick_CounterCmd(SysTick_Counter_Clear);
*(uint32_t *)0xe000e010 |= 1; //SysTick_CounterCmd(SysTick_Counter_Enable);
while(!I2C_OT);
*(uint32_t *)0xe000e010 &= 0xfffffffe; //SysTick_CounterCmd(SysTick_Counter_Disable);
I2C_OT = FALSE;
/* wait bus for free */
*(uint32_t *)0xe000e014 = CHECK_TIMEOUT;
*(uint32_t *)0xe000e018 = 0;
*(uint32_t *)0xe000e010 |= 1;
while((I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY))&&(!I2C_OT));
*(uint32_t *)0xe000e010 &= 0xfffffffe;
I2C_OT = FALSE;
if (I2C_OT) //上面这句都已经赋为FALSE了,还判断它的真假????
{
I2C_OT = FALSE;
/* during 1s, bus is occupied by other i2c comm */
/* after check_timeout(1s), target's internal must complete */
return NO_ERR; //如果I2C_OT为真都已经超时了,还返回NO_ERR??
}
I2C_GenerateSTART(I2Cx, ENABLE);
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2Cx, slaveaddr, I2C_Direction_Transmitter);
/* wait for 10 I2C clock pulse period and then check ADDR set or not*/
*(uint32_t *)0xe000e014 = one_us_unit*i2c_10clk_us;
*(uint32_t *)0xe000e018 = 0;
*(uint32_t *)0xe000e010 |= 1;
while(!I2C_OT);
*(uint32_t *)0xe000e010 &= 0xfffffffe;
I2C_OT = FALSE;
if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_ADDR))
{
break;
}
I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
I2C_GenerateSTOP(I2Cx, ENABLE);
while ((I2Cx->CR1 & 0x200) == 0x200); //STOP bit
check_time++;
}
if (check_time ==1000000/5)
return WRITE_FAILURE;
I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
I2C_GenerateSTOP(I2Cx, ENABLE);
while ((I2Cx->CR1 & 0x200) == 0x200);
return NO_ERR;
}