📄 i2c_ee.c
字号:
/* 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)
{
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_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);
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;
}
I2C_Result I2C_Comm_MasterReceive(I2C_TypeDef* I2Cx, uint16_t slaveaddr, uint8_t offset, uint8_t* pBuffer, uint32_t length)
{
/* wait 5us max for bus free time limitation for later transaction */
*(uint32_t *)0xe000e014 = one_us_unit*5;
*(uint32_t *)0xe000e018 = 0;
*(uint32_t *)0xe000e010 |= 1;
while(!I2C_OT);
*(uint32_t *)0xe000e010 &= 0xfffffffe;
I2C_OT = FALSE;
/* wait bus free */
*(uint32_t *)0xe000e014 = BUS_BUSY_TIMEOUT;
*(uint32_t *)0xe000e018 = 0;
*(uint32_t *)0xe000e010 |= 1;
while((I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY))&&(!I2C_OT));
*(uint32_t *)0xe000e010 &= 0xfffffffe;
if (I2C_OT)
{
I2C_OT = FALSE;
return BUS_BUSY;
}
/* send start and wait */
I2C_GenerateSTART(I2Cx, ENABLE);
*(uint32_t *)0xe000e014 = SEND_START_TIMEOUT;
*(uint32_t *)0xe000e018 = 0;
*(uint32_t *)0xe000e010 |= 1;
while(!(I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT) || I2C_OT));
*(uint32_t *)0xe000e010 &= 0xfffffffe;
if (I2C_OT)
{
I2C_OT = FALSE;
return SEND_START_ERR;
}
/*
if offset needed:
(1) slave address with write direction
(2) offset
(3) re-start
*/
if (offset!=0xff)
{
/* (1) */
I2C_Send7bitAddress(I2Cx, (uint8_t)(slaveaddr & 0xFF), I2C_Direction_Transmitter);
*(uint32_t *)0xe000e014 = SEND_ADDR7_TIMEOUT;
*(uint32_t *)0xe000e018 = 0;
*(uint32_t *)0xe000e010 |= 1;
while(!(I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) || I2C_OT));
*(u32 *)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 ADDR_MATCH_ERR;
}
/* (2) */
I2C_SendData(I2Cx, offset);
*(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;
}
/* (3) */
I2C_GenerateSTART(I2Cx, ENABLE);
*(uint32_t *)0xe000e014 = SEND_START_TIMEOUT;
*(uint32_t *)0xe000e018 = 0;
*(uint32_t *)0xe000e010 |= 1;
while(!(I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT) || I2C_OT));
*(uint32_t *)0xe000e010 &= 0xfffffffe;
if (I2C_OT)
{
I2C_OT = FALSE;
return SEND_START_ERR;
}
}
/* send addr with read direction */
I2C_Send7bitAddress(I2Cx, (uint8_t)(slaveaddr & 0xFF), I2C_Direction_Receiver);
/*
different implementation of receive data
depends on communication length
(1) length >=3
(2) length = 2
(3) length = 1
*/
if (length >=3)
{
*(uint32_t *)0xe000e014 = SEND_ADDR7_TIMEOUT;
*(uint32_t *)0xe000e018 = 0;
*(uint32_t *)0xe000e010 |= 1;
while(!(I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) || 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 ADDR_MATCH_ERR;
}
/* receive data */
/* use another safe procedure to receive data */
while(length)
{
if (length !=3)
{
*(uint32_t *)0xe000e014 = RECEIVE_DATA_TIMEOUT;
*(uint32_t *)0xe000e018 = 0;
*(uint32_t *)0xe000e010 |= 1;
while(((I2C_GetLastEvent(I2Cx)&0x04) != 0x04)&& !I2C_OT); // poll on BTF
*(uint32_t *)0xe000e010 &= 0xfffffffe;
if (I2C_OT)
{
I2C_OT = FALSE;
I2C_GenerateSTOP(I2Cx, ENABLE);
return DATA_TIMEOUT;
}
*pBuffer++ = I2C_ReceiveData(I2Cx);
length--;
}
if (length == 3)
{
/* D(n-2) in DR; D(n-1) in shift register */
*(uint32_t *)0xe000e014 = RECEIVE_DATA_TIMEOUT;
*(uint32_t *)0xe000e018 = 0;
*(uint32_t *)0xe000e010 |= 1;
while(((I2C_GetLastEvent(I2Cx)&0x04) != 0x04)&& !I2C_OT); // poll on BTF
*(uint32_t *)0xe000e010 &= 0xfffffffe;
if (I2C_OT)
{
I2C_OT = FALSE;
I2C_GenerateSTOP(I2Cx, ENABLE);
return DATA_TIMEOUT;
}
/* clear ACK */
I2C_AcknowledgeConfig(I2Cx, DISABLE);
__disable_irq(); //NVIC_SETPRIMASK();
/* read D(n-2) */
*pBuffer++ = I2C_ReceiveData(I2Cx);
/* program stop */
I2C_GenerateSTOP(I2Cx, ENABLE);
/* read D(n-1) */
*pBuffer++ = I2C_ReceiveData(I2Cx);
__enable_irq(); //NVIC_RESETPRIMASK();
*(uint32_t *)0xe000e014 = RECEIVE_DATA_TIMEOUT;
*(uint32_t *)0xe000e018 = 0;
*(uint32_t *)0xe000e010 |= 1;
while(((I2C_GetLastEvent(I2Cx)&0x40) != 0x40)&& !I2C_OT); // poll on RxNE
*(uint32_t *)0xe000e010 &= 0xfffffffe;
if (I2C_OT)
{
I2C_OT = FALSE;
I2C_GenerateSTOP(I2Cx, ENABLE);
return DATA_TIMEOUT;
}
*pBuffer = I2Cx->DR;
length = 0;
}
}
*(uint32_t *)0xe000e014 = RECEIVE_DATA_TIMEOUT;
*(uint32_t *)0xe000e018 = 0;
*(uint32_t *)0xe000e010 |= 1;
while (((I2Cx->CR1 & 0x200) == 0x200)&&(!I2C_OT));
*(uint32_t *)0xe000e010 &= 0xfffffffe;
if (I2C_OT)
{
I2C_OT = FALSE;
return SEND_STOP_ERR;
}
I2C_AcknowledgeConfig(I2Cx, ENABLE);
}
else if (length == 2)
{
vu32 tmp;
/* ACK=1,POS=1 */
I2Cx->CR1 = 0xc01;
*(uint32_t *)0xe000e014 = SEND_ADDR7_TIMEOUT;
*(uint32_t *)0xe000e018 = 0;
*(uint32_t *)0xe000e010 |= 1;
while((!I2C_GetFlagStatus(I2Cx,I2C_FLAG_ADDR))&& !I2C_OT); //wait for ADDR event
*(uint32_t *)0xe000e010 &= 0xfffffffe;
if (I2C_OT)
{
I2C_OT = FALSE;
I2C_GenerateSTOP(I2Cx, ENABLE);
return ADDR_MATCH_ERR;
}
__disable_irq(); //NVIC_SETPRIMASK();
/* clear ADDR */
tmp = I2Cx->SR2;
/* disable ACK */
I2C_AcknowledgeConfig(I2Cx, DISABLE);
__enable_irq(); //NVIC_RESETPRIMASK();
*(uint32_t *)0xe000e014 = RECEIVE_DATA_TIMEOUT;
*(uint32_t *)0xe000e018 = 0;
*(uint32_t *)0xe000e010 |= 1;
while(((I2C_GetLastEvent(I2Cx)&0x0004) != 0x0004)&& !I2C_OT); // poll on BTF
*(uint32_t *)0xe000e010 &= 0xfffffffe;
if (I2C_OT)
{
I2C_OT = FALSE;
I2C_GenerateSTOP(I2Cx, ENABLE);
return DATA_TIMEOUT;
}
__disable_irq(); //NVIC_SETPRIMASK();
I2C_GenerateSTOP(I2Cx, ENABLE);
*pBuffer++ = I2Cx->DR;
*pBuffer = I2Cx->DR;
__enable_irq(); //NVIC_RESETPRIMASK();
length = 0;
/* POS=0; ACK=PE=1 */
I2Cx->CR1 = 0x0401;
}
else if (length == 1)
{
__IO uint32_t tmp;
*(uint32_t *)0xe000e014 = SEND_ADDR7_TIMEOUT;
*(uint32_t *)0xe000e018 = 0;
*(uint32_t *)0xe000e010 |= 1;
while((!I2C_GetFlagStatus(I2Cx,I2C_FLAG_ADDR))&& !I2C_OT); //wait for ADDR event
*(uint32_t *)0xe000e010 &= 0xfffffffe;
if (I2C_OT)
{
I2C_OT = FALSE;
I2C_GenerateSTOP(I2Cx, ENABLE);
return ADDR_MATCH_ERR;
}
/* disable ACK */
I2C_AcknowledgeConfig(I2Cx, DISABLE);
__disable_irq(); //NVIC_SETPRIMASK();
/* clear ADDR */
tmp = I2Cx->SR2;
I2C_GenerateSTOP(I2Cx, ENABLE);
__enable_irq(); //NVIC_RESETPRIMASK();
*(uint32_t *)0xe000e014 = RECEIVE_DATA_TIMEOUT;
*(uint32_t *)0xe000e018 = 0;
*(uint32_t *)0xe000e010 |= 1;
while(((I2C_GetLastEvent(I2Cx)&0x40) != 0x40)&& !I2C_OT); // poll on RxNE
*(uint32_t *)0xe000e010 &= 0xfffffffe;
if (I2C_OT)
{
I2C_OT = FALSE;
I2C_GenerateSTOP(I2Cx, ENABLE);
return DATA_TIMEOUT;
}
*pBuffer = I2Cx->DR;
length = 0;
while ((I2Cx->CR1 & 0x200) == 0x200);
I2C_AcknowledgeConfig(I2Cx, ENABLE);
}
return NO_ERR;
}
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -