英飞凌
直播中

youyoulan

12年用户 1107经验值
私信 关注

如果启用了I2C从站FIFO\"中的\"地址,为什么该行会将地址复制到FW缓冲区呢?

我有一个基于"I2C_Slave_Using_Callbacks" 的 PSoC4 MAX 器件的 I2C 从设备项目。 它已启用"Accept Slave Address In RX FIFO" 。 但是,我的设备被主站发送的从站地址淹没了。 下面粗体字一行是将地址复制到我的 FW 缓冲区。 我本以为地址会在此之前被删除,但事实似乎并非如此。 我还有什么不明白的地方?

static void SlaveHandleDataReceive(CySCB_Type *base, cy_stc_scb_i2c_context_t *context){    /* Check whether there is space to put data */    if (context->slaveRxBufferSize > 0UL)    {        if (context->useRxFifo)        {            uint32_t level;            /* Get the number of bytes to read from RX FIFO */            uint32_t numToCopy = Cy_SCB_GetRxFifoLevel(base) + 1UL;            /* Get data from RX FIFO */            numToCopy = Cy_SCB_ReadArray(base, context->slaveRxBuffer, numToCopy);            context->slaveRxBufferIdx  += numToCopy;            context->slaveRxBufferSize -= numToCopy;            context->slaveRxBuffer      =  context->slaveRxBuffer[numToCopy];            /* Prepare to read a next chunk of data */            if (context->slaveRxBufferSize > CY_SCB_I2C_FIFO_SIZE)            {                level = context->slaveRxBufferSize - CY_SCB_I2C_FIFO_SIZE;                level = ((level > CY_SCB_I2C_FIFO_SIZE) ? (CY_SCB_I2C_FIFO_SIZE / 2UL) : level) - 1UL;            }            else            {                SCB_I2C_CTRL(base) |= SCB_I2C_CTRL_S_NOT_READY_DATA_NACK_Msk;                level = (context->slaveRxBufferSize == 0UL) ? (0UL) : (context->slaveRxBufferSize - 1UL);                Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);            }            /* Set the RX level to trigger an interrupt */            Cy_SCB_SetRxFifoLevel(base, level);        }        else        {            /* Continue the transfer: send an ACK */            SCB_I2C_S_CMD(base) |= SCB_I2C_S_CMD_S_ACK_Msk;            /* Put data into the RX buffer */            context->slaveRxBuffer[context->slaveRxBufferIdx] = (uint8_t) Cy_SCB_ReadRxFifo(base);            ++context->slaveRxBufferIdx;            --context->slaveRxBufferSize;        }    }    else    {        /* Finish a transfer: send a NACK and discard the received byte */        SCB_I2C_S_CMD(base) |= SCB_I2C_S_CMD_S_NACK_Msk;        Cy_SCB_SetRxInterruptMask(base, CY_SCB_CLEAR_ALL_INTR_SRC);    }}

回帖(1)

youyoulan

2024-7-24 17:36:51
0) {
/* Copy the address to the FW buffer */
context->slaveRxBuffer[context->slaveRxBufferIndex] = context->rxFifo[0];

/* Increment the buffer index */
context->slaveRxBufferIndex++;

/* Decrement the remaining size */
context->slaveRxBufferSize--;

/* Clear the first entry in the RX FIFO */
Cy_SCB_I2C_ClearRxInterrupt(base, 1);

/* Call the user-defined callback function */
if (context->slaveRxBufferIndex == 1) {
context->callback(CY_SCB_I2C_SLAVE_WRITE_EVENT, NULL);
}
}
}

从您的代码中,我可以看到您正在实现一个I2C从站,使用回调函数处理数据接收。您提到已经启用了"Accept Slave Address In RX FIFO"选项,但是您的设备仍然被主站发送的从站地址淹没。

问题可能出在以下几行代码:

```
/* Copy the address to the FW buffer */
context->slaveRxBuffer[context->slaveRxBufferIndex] = context->rxFifo[0];
```

这里,您将从RX FIFO中的第一个字节(即从站地址)复制到FW缓冲区。然而,您希望在处理完地址后将其从FIFO中删除。这就是为什么您在下一行代码中调用了`Cy_SCB_I2C_ClearRxInterrupt(base, 1);`,以清除RX FIFO中的第一个条目。

但是,这里可能存在一个问题:在调用回调函数之前,您可能需要先处理FIFO中的数据。在您的代码中,回调函数在`context->slaveRxBufferIndex == 1`时被调用,这意味着当FW缓冲区中只有一个字节时,回调函数就会被调用。然而,这个字节可能是从站地址,而不是实际的数据。

为了解决这个问题,您可以尝试以下步骤:

1. 在复制地址到FW缓冲区之前,检查RX FIFO中的下一个字节是否是有效的数据。如果是,您可以跳过地址处理。

2. 如果RX FIFO中的下一个字节是有效的数据,您可以将地址从FIFO中删除,然后继续处理数据。

3. 如果RX FIFO中的下一个字节不是有效的数据,您可以将地址复制到FW缓冲区,并在回调函数中处理它。

这样,您可以确保从站地址不会被淹没,并且您的设备可以正确地处理接收到的数据。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分