0

我想知道是否有人找到了一种方法来确定主控与 stm32f40x 芯片通信的意图?从stm32f40x芯片上的固件来看,主控发送的ADDRess是不可用的,其中包含的r/w位(地址的第0位)也是不可用的。那么如何防止碰撞呢?有没有其他人处理过这个?如果是这样,您使用了哪些技术?我的暂定解决方案如下供参考。我延迟了对 DR 数据寄存器的任何写入,直到发生 TXE 中断。起初我认为这为时已晚,一个字节的垃圾会被淘汰,但它似乎正在工作。

static inline void LLEVInterrupt(uint16_t irqSrc)
{
    uint8_t  i;
    volatile uint16_t status;
    I2CCBStruct* buffers;
    I2C_TypeDef* addrBase;

    // see which IRQ occurred, process accordingly...
    switch (irqSrc)
    {
        case I2C_BUS_CHAN_1:
            addrBase = this.addrBase1;
            buffers = &this.buffsBus1;
            break;
        case I2C_BUS_CHAN_2:
            addrBase = this.addrBase2;
            buffers = &this.buffsBus2;
            break;
        case I2C_BUS_CHAN_3:
            addrBase = this.addrBase3;
            buffers = &this.buffsBus3;
            break;
        default:
            while(1);
    }

    // ...START condition & address match detected
    if (I2C_GetITStatus(addrBase, I2C_IT_ADDR) == SET)
    {
        // I2C_IT_ADDR: Cleared by software reading SR1 register followed reading SR2, or by hardware
        //  when PE=0.
        // Note: Reading I2C_SR2 after reading I2C_SR1 clears the ADDR flag, even if the ADDR flag was
        //  set after reading I2C_SR1. Consequently, I2C_SR2 must be read only when ADDR is found
        //  set in I2C_SR1 or when the STOPF bit is cleared.
        status = addrBase->SR1;
        status = addrBase->SR2;

        // Reset the index and receive count
        buffers->txIndex = 0;
        buffers->rxCount = 0;

        // setup to ACK any Rx'd bytes
        I2C_AcknowledgeConfig(addrBase, ENABLE);
        return;
    }

    // Slave receiver mode
    if (I2C_GetITStatus(addrBase, I2C_IT_RXNE) == SET)
    {
        // I2C_IT_RXNE: Cleared by software reading or writing the DR register 
        //  or by hardware when PE=0.

        // copy the received byte to the Rx buffer
        buffers->rxBuf[buffers->rxCount] = (uint8_t)I2C_ReadRegister(addrBase, I2C_Register_DR);
        if (RX_BUFFER_SIZE > buffers->rxCount)
        {
            buffers->rxCount++;
        }
        return;
    }

    // Slave transmitter mode
    if (I2C_GetITStatus(addrBase, I2C_IT_TXE) == SET)
    {
        // I2C_IT_TXE: Cleared by software writing to the DR register or 
        //  by hardware after a start or a stop condition or when PE=0.

        // send any remaining bytes
        I2C_SendData(addrBase, buffers->txBuf[buffers->txIndex]);
        if (buffers->txIndex < buffers->txCount)
        {
            buffers->txIndex++;
        }
        return;
    }

    // ...STOP condition detected
    if (I2C_GetITStatus(addrBase, I2C_IT_STOPF) == SET)
    {
        // STOPF (STOP detection) is cleared by software sequence: a read operation 
        //  to I2C_SR1 register (I2C_GetITStatus()) followed by a write operation to 
        //  I2C_CR1 register (I2C_Cmd() to re-enable the I2C peripheral).
        // From the reference manual RM0368:
        // Figure 163. Transfer sequence diagram for slave receiver
        // if (STOPF == 1) {READ SR1; WRITE CR1}
        // clear the IRQ status
        status = addrBase->SR1;
        // Write to CR1
        I2C_Cmd(addrBase, ENABLE);

        // read cycle (reset the status?
        if (buffers->txCount > 0)
        {
            buffers->txCount = 0;
            buffers->txIndex = 0;
        }

        // write cycle begun?
        if (buffers->rxCount > 0)
        {
            // pass the I2C data to the enabled protocol handler
            for (i = 0; i < buffers->rxCount; i++)
            {
                #if (COMM_PROTOCOL == COMM_PROTOCOL_DEBUG)
                 status = ProtProcRxData(buffers->rxBuf[i]);
                #elif (COMM_PROTOCOL == COMM_PROTOCOL_PTEK)
                 status = PTEKProcRxData(buffers->rxBuf[i]);
                #else
                 #error ** Invalid Host Protocol Selected **
                #endif
                if (status != ST_OK)
                {
                    LogErr(ST_COMM_FAIL, __LINE__);
                }
            }
            buffers->rxCount = 0;
        }
        return;
    }

    if (I2C_GetITStatus(addrBase, I2C_IT_AF) == SET)
    {
        // The NAck received from the host on the last byte of a transmit 
        //  is shown as an acknowledge failure and must be cleared by 
        //  writing 0 to the AF bit in SR1.
        // This is not a real error but just how the i2c slave transmission process works.
        // The hardware has no way to know how many bytes are to be transmitted, so the 
        //  NAck is assumed to be a failed byte transmission.
        // EV3-2: AF=1; AF is cleared by writing ‘0’ in AF bit of SR1 register.
        I2C_ClearITPendingBit(addrBase, I2C_IT_AF);
        return;
    }

    if (I2C_GetITStatus(addrBase, I2C_IT_BERR) == SET)
    {
        // There are extremely infrequent bus errors when testing with I2C Stick.
        // Safer to have this check and clear than to risk an 
        //  infinite loop of interrupts
        // Set by hardware when the interface detects an SDA rising or falling 
        //  edge while SCL is high, occurring in a non-valid position during a 
        //  byte transfer.
        // Cleared by software writing 0, or by hardware when PE=0.
        I2C_ClearITPendingBit(addrBase, I2C_IT_BERR);
        LogErr(ST_COMM_FAIL, __LINE__);
        return;
    }

    if (I2C_GetITStatus(addrBase, I2C_IT_OVR) == SET)
    {
        // Check for other errors conditions that must be cleared.
        I2C_ClearITPendingBit(addrBase, I2C_IT_OVR);
        LogErr(ST_COMM_FAIL, __LINE__);
        return;
    }

    if (I2C_GetITStatus(addrBase, I2C_IT_TIMEOUT) == SET)
    {
        // Check for other errors conditions that must be cleared.
        I2C_ClearITPendingBit(addrBase, I2C_IT_TIMEOUT);
        LogErr(ST_COMM_FAIL, __LINE__);
        return;
    }

    // a spurious IRQ occurred; log it
    LogErr(ST_INV_STATE, __LINE__);
}
4

2 回答 2

0

I'm not shure if I understand you. May you should provide more information or an example about what you would like to do.

Maybe this helps: My experience is, that in many I2C implementations the R/W-Bit is used together with the 7-bit-address, so most of the times, there is no additional function to set or reset the R/W-Bit.

So that means all addresses beyond 128 should be used to read data from slaves and all addresses over 127 should be used to write data to slaves.

于 2015-02-10T07:40:21.583 回答
0

即使硬件知道 LSbit 是设置还是清除,似乎也无法确定由接收地址发起的事务是读取还是写入。主机的意图只有在 RXNE 或 TXE 中断/位发生时才能知道。

于 2015-04-29T15:09:29.707 回答