参考的是官网下载的DDL2.2.0库里的I2C轮询例程,在I2C主机模式接收长度为1字节数据的情况下,为什么发I2C设备接收地址之前需要先发一个NACK呢?如果不发这个NACK就会返回Timeout错误,并且不上电复位就没有办法正常收发数据,各个和I2C相关的操作返回值都是Timeout错误,重新烧写也不会恢复,需要芯片断电再上电其他操作才正常。
下面这个是官方库的接收代码
/** 主机接受数据
* [url=home.php?mod=space&uid=247401]@brief[/url] Master receive data
*
* @param [in] u16DevAddr The slave address
* @param [in] au8Data The data array
* @param [in] u32Size Data size
* @param [in] u32Timeout Time out count
* @retval int32_t:
* - LL_OK: Success
* - LL_ERR_TIMEOUT: Time out
*/
static int32_t I2C_Master_Receive(uint16_t u16DevAddr, uint8_t au8Data[], uint32_t u32Size, uint32_t u32Timeout)
{
int32_t i32Ret;
I2C_Cmd(I2C_UNIT, ENABLE);
I2C_SWResetCmd(I2C_UNIT, ENABLE);
I2C_SWResetCmd(I2C_UNIT, DISABLE);
i32Ret = I2C_Start(I2C_UNIT, u32Timeout);
if (LL_OK == i32Ret) {
if (1UL == u32Size) {
// I2C_AckConfig(I2C_UNIT, I2C_NACK); // 注释掉NACK进行测试
}
#if (I2C_ADDR_MD == I2C_ADDR_MD_10BIT)
i32Ret = I2C_Trans10BitAddr(I2C_UNIT, u16DevAddr, I2C_DIR_RX, u32Timeout);
#else
i32Ret = I2C_TransAddr(I2C_UNIT, u16DevAddr, I2C_DIR_RX, u32Timeout);
#endif
if (LL_OK == i32Ret) {
i32Ret = I2C_MasterReceiveDataAndStop(I2C_UNIT, au8Data, u32Size, u32Timeout);
}
I2C_AckConfig(I2C_UNIT, I2C_ACK);
}
if (LL_OK != i32Ret) {
(void)I2C_Stop(I2C_UNIT, u32Timeout);
}
I2C_Cmd(I2C_UNIT, DISABLE);
return i32Ret;
}
|