You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PSoC4 MAX中I2C从机地址在RX缓冲区的处理疑问

PSoC4 MAX I2C从机地址填充固件缓冲区问题

问题背景

将基于英飞凌/Cypress PSoC4的旧项目移植到PSoC4 MAX芯片,设备作为I2C从机与主机通信:主机每秒发送3次仅包含从机地址的ping包,从机同时需要响应用户触发的特定命令。当前遇到的问题是:固件缓冲区被这些周期性的从机地址填满,导致用户命令被淹没丢失,而旧项目使用的旧版I2C库无此问题。

从机配置

当前I2C从机配置开启了acceptAddrInFifo=true:

const cy_stc_scb_i2c_config_t CYBSP_SCB_I2C_config =
{
    .i2cMode = CY_SCB_I2C_SLAVE,
    .useRxFifo = true,
    .useTxFifo = true,
    .slaveAddress = 0x58,
    .slaveAddressMask = 0xFE,
    .acceptAddrInFifo = true,
    .ackGeneralAddr = false,
    .hsEnable = false,
    .enableWakeFromSleep = true,
    .enableDigitalFilter = false,
    .lowPhaseDutyCycle = 0,
    .highPhaseDutyCycle = 0,
};

核心疑问

从机地址在ACK主机后是否应该进入固件缓冲区?若不应进入,该如何正确消耗这些地址?

代码逻辑分析

结合提供的ISR及相关处理函数,问题根源在于acceptAddrInFifo=true时的地址处理流程:

1. ISR处理逻辑

在Cy_SCB_I2C_SlaveInterrupt中:

  • 当检测到acceptAddrInFifo=true且触发地址匹配中断时,会设置slaveAddrInFifo=true,此时会跳过SlaveHandleDataReceive(避免在地址阶段就把地址写入固件缓冲区)。
  • 当主机发送stop信号后,SlaveHandleStop会检查RX FIFO是否有数据,若固件缓冲区有空间,会重新开启RX中断。此时slaveAddrInFifo已复位为false,后续RX中断触发时,SlaveHandleDataReceive会将FIFO中的地址字节写入固件缓冲区,导致地址不断积累。

2. SlaveHandleAddress处理逻辑

该函数负责地址匹配后的ACK/NACK处理:

  • 如果未设置地址回调函数cbAddr,则仅完成ACK/NACK操作,不会处理RX FIFO中的地址字节,导致地址留在FIFO中。
  • 只有当设置了cbAddr并触发CY_SCB_I2C_ADDR_IN_FIFO_EVENT时,才会在回调中处理地址,但默认逻辑中没有自动丢弃地址的操作。

3. SlaveHandleAck处理逻辑

该函数仅准备后续读写的缓冲区和中断配置,不会处理遗留的地址字节。

解决方案

针对上述问题,可通过以下方式解决:

方案1:关闭地址入FIFO功能

将配置中的acceptAddrInFifo设为false,此时硬件不会将匹配的从机地址存入RX FIFO,仅触发地址中断,由SlaveHandleAddress处理,地址不会进入固件缓冲区。此方案最直接,适合不需要在FIFO中获取地址的场景。

方案2:实现地址回调函数丢弃地址

如果必须开启acceptAddrInFifo,则实现cbAddr回调函数,在回调中手动读取并丢弃RX FIFO中的地址字节:

cy_en_scb_i2c_command_t addrCallback(uint32_t events)
{
    if(events & CY_SCB_I2C_ADDR_IN_FIFO_EVENT)
    {
        // 读取并丢弃FIFO中的地址字节
        Cy_SCB_ReadRxData(CYBSP_SCB_I2C_HW);
    }
    return CY_SCB_I2C_ACK;
}

// 初始化时注册回调
context.cbAddr = addrCallback;

方案3:在Stop事件中清理仅含地址的FIFO数据

在SlaveHandleStop或自定义的stop回调中,判断如果RX FIFO中仅存在地址字节(即ping包无后续数据),则直接清空FIFO,不写入固件缓冲区:

// 在Stop处理逻辑中添加
if(Cy_SCB_GetNumInRxFifo(base) == 1 && slaveAddrInFifo)
{
    // 仅地址的ping包,清空FIFO
    Cy_SCB_ClearRxFifo(base);
}

内容的提问来源于stack exchange,提问作者nobby

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 19:28:08