我有一个定制的 STM32F439VITx 板,运行频率为 60MHz,由 HSI 提供时钟。我在 I2C3 上有三个设备,其中两个功能正常,第三个是 mb85rc64 非易失性存储器,在读取和写入操作时均失败。
I2C 配置如下:
- void MX_I2C3_Init(void)
- {
- hi2c3.Instance = I2C3;
- hi2c3.Init.ClockSpeed = 100000;
- hi2c3.Init.DutyCycle = I2C_DUTYCYCLE_2;
- hi2c3.Init.OwnAddress1 = 0;
- hi2c3.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
- hi2c3.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
- hi2c3.Init.OwnAddress2 = 0;
- hi2c3.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
- hi2c3.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
- if (HAL_I2C_Init(&hi2c3) != HAL_OK)
- {
- Error_Handler();
- }
- /** Configure Analogue filter
- */
- if (HAL_I2CEx_ConfigAnalogFilter(&hi2c3, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
- {
- Error_Handler();
- }
- /** Configure Digital filter
- */
- if (HAL_I2CEx_ConfigDigitalFilter(&hi2c3, 0) != HAL_OK)
- {
- Error_Handler();
- }
- }
我正在像这样发送 I2C 命令:
- static const uint8_t DevAddress = 0b10100000; // preshifted
- static const uint16_t MemAddress = 0;
- static const uint16_t MemAddSize = I2C_MEMADD_SIZE_16BIT;
- static const uint16_t Size = 1;
- uint8_t Data[Size];
- static const uint32_t Timeout = 1000;
- Data[0] = 1;
- HAL_StatusTypeDef hal = HAL_I2C_Mem_Write(&hi2c3, DevAddress, MemAddress, MemAddSize, Data, Size, Timeout);
追溯源头,HAL_I2C_Mem_Write() 毫无问题地调用了 I2C_WaitOnMasterAddressFlagUntilTimeout:
- HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
- {
- /* Init tickstart for timeout management*/
- uint32_t tickstart = HAL_GetTick();
- /* Check the parameters */
- assert_param(IS_I2C_MEMADD_SIZE(MemAddSize));
- if (hi2c->State == HAL_I2C_STATE_READY)
- {
- /* Wait until BUSY flag is reset */
- if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK)
- {
- return HAL_BUSY;
- }
- /* Process Locked */
- __HAL_LOCK(hi2c);
- /* Check if the I2C is already enabled */
- if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE)
- {
- /* Enable I2C peripheral */
- __HAL_I2C_ENABLE(hi2c);
- }
- /* Disable Pos */
- CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS);
- hi2c->State = HAL_I2C_STATE_BUSY_TX;
- hi2c->Mode = HAL_I2C_MODE_MEM;
- hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
- /* Prepare transfer parameters */
- hi2c->pBuffPtr = pData;
- hi2c->XferCount = Size;
- hi2c->XferSize = hi2c->XferCount;
- hi2c->XferOptions = I2C_NO_OPTION_FRAME;
- /* Send Slave Address and Memory Address */
- if (I2C_RequestMemoryWrite(hi2c, DevAddress, MemAddress, MemAddSize, Timeout, tickstart) != HAL_OK)
I2C_RequestMemoryWrite 就调用 I2C_WaitOnMasterAddressFlagUntilTimeout 而没有任何可疑的事情发生:
- static HAL_StatusTypeDef I2C_RequestMemoryWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart)
- {
- /* Generate Start */
- SET_BIT(hi2c->Instance->CR1, I2C_CR1_START);
- /* Wait until SB flag is set */
- if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK)
- {
- if (READ_BIT(hi2c->Instance->CR1, I2C_CR1_START) == I2C_CR1_START)
- {
- hi2c->ErrorCode = HAL_I2C_WRONG_START;
- }
- return HAL_TIMEOUT;
- }
- /* Send slave address */
- hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(DevAddress);
- /* Wait until ADDR flag is set */
- if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK)
I2C_WaitOnMasterAddressFlagUntilTimeout 然后立即进入 if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET)条件并失败。
- static HAL_StatusTypeDef I2C_WaitOnMasterAddressFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, uint32_t Timeout, uint32_t Tickstart)
- {
- while (__HAL_I2C_GET_FLAG(hi2c, Flag) == RESET)
- {
- if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET)
- {
- /* Generate Stop */
- SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP);
- /* Clear AF Flag */
- __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
- hi2c->PreviousState = I2C_STATE_NONE;
- hi2c->State = HAL_I2C_STATE_READY;
- hi2c->Mode = HAL_I2C_MODE_NONE;
- hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
- /* Process Unlocked */
- __HAL_UNLOCK(hi2c);
- return HAL_ERROR;
- }
在我看来,这是接收地址 ACK 失败。
代码就这么多。数据表告诉我,要将 1 写入地址 0,我应该发送:
S10100000A00000000A00000000A00000001AP
其中 S 和 P 是我设置的开始和停止条件,A 是 mb85rc64 设置的确认,并带有一个可能可疑的脚注“停止后,从缓冲区到内存的内部写操作周期不需要一段时间条件产生。” 我假设这不相关,因为我还没有真正写入内存。
失败事务的示波器如下所示:
时钟信号看起来可能有点脏,但除此之外还有什么明显导致 WaitOnMasterAddressFlag 失败的原因吗?
0
|
1个回答
|
|
|