首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >没有r/w位可由I2C外设的STM32F40x芯片提供给固件

没有r/w位可由I2C外设的STM32F40x芯片提供给固件
EN

Stack Overflow用户
提问于 2015-02-04 17:07:32
回答 2查看 206关注 0票数 0

我想知道是否有人找到了确定主人与stm32f40x芯片通信的意图的方法?从stm32f40x芯片上固件的角度来看,主机发送的ADDRess不可用,其中包含的r/w位(地址的0位)也不可用。那么我怎样才能避免碰撞呢?还有其他人处理过这事吗?如果是这样的话,你使用了哪些技术?以下是我的初步解决方案,供大家参考。我延迟了对DR数据寄存器的任何写入,直到TXE中断发生。一开始我以为这太晚了,一字节的垃圾会被清除掉,但它似乎起作用了。

代码语言:javascript
复制
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__);
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-02-10 07:40:21

如果我明白你的意思我就不放心了。希望你能提供更多关于你想要做的事情的信息或例子。

也许有助于:我的经验是,在许多I2C实现中,R/W位与7位地址一起使用,所以大多数情况下,没有额外的功能来设置或重置R/W位。

因此,这意味着所有128以上的地址都应该用于从奴隶中读取数据,而所有超过127的地址都应该用来将数据写入从节点。

票数 0
EN

Stack Overflow用户

发布于 2015-04-29 15:09:29

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28327285

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档