参考的是官网下载的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;
- }
|