uint8_t I2C_WriteByte(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t data)
{
uint8_t u8Xfering = 1U, u8Err = 0U, u8Ctrl = 0U;
uint32_t u32TimeOutCount;
g_I2C_i32ErrCode = 0;
I2C_START(i2c);
while (u8Xfering && (u8Err == 0U))
{
u32TimeOutCount = SystemCoreClock;
I2C_WAIT_READY(i2c)
{
u32TimeOutCount--;
if(u32TimeOutCount == 0)
{
g_I2C_i32ErrCode = I2C_TIMEOUT_ERR;
break;
}
}
switch (I2C_GET_STATUS(i2c))
{
case 0x08:
I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1U | 0x00U)); /* Write SLA+W to Register I2CDAT */
u8Ctrl = I2C_CTL_SI; /* Clear SI */
break;
case 0x18: /* Slave Address ACK */
I2C_SET_DATA(i2c, data); /* Write data to I2CDAT */
break;
case 0x20: /* Slave Address NACK */
case 0x30: /* Master transmit data NACK */
u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
u8Err = 1U;
break;
case 0x28:
u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
u8Xfering = 0U;
break;
case 0x38: /* Arbitration Lost */
default: /* Unknow status */
I2C_SET_CONTROL_REG(i2c, I2C_CTL_STO_SI); /* Clear SI and send STOP */
u8Ctrl = I2C_CTL_SI;
u8Err = 1U;
break;
}
I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */
}
u32TimeOutCount = SystemCoreClock;
while ((i2c)->CTL0 & I2C_CTL0_STO_Msk)
{
u32TimeOutCount--;
if(u32TimeOutCount == 0)
{
g_I2C_i32ErrCode = I2C_TIMEOUT_ERR;
break;
}
}
return (u8Err | u8Xfering); /* return (Success)/(Fail) status */
}
该函数写的比较复杂,最后返回一个是否发送成功的标志。
最后是通过检测两个事件,I2C总线是否完成了发送,如果没有就检测第二个标志,是否发送超时了。超时后也会自动结束函数,防止阻塞卡死。
|