Embedded STM32F40x芯片的I2C外围设备没有可用于固件的r/w位

Embedded STM32F40x芯片的I2C外围设备没有可用于固件的r/w位,embedded,communication,stm32,i2c,stm32f4discovery,Embedded,Communication,Stm32,I2c,Stm32f4discovery,我想知道是否有人找到了一种方法来确定主机与stm32f40x芯片通信的意图?从stm32f40x芯片固件的角度来看,主机发送的地址不可用,其中包含的r/w位(地址的位0)也不可用。那么如何防止碰撞呢?还有其他人处理过吗?如果是这样,你使用了什么技术?我的暂定方案如下,以供参考。我延迟了对DR数据寄存器的任何写入,直到TXE中断发生。起初我以为这样做太晚了,一个字节的垃圾会被打卡,但它似乎在工作 static inline void LLEVInterrupt(uint16_t irqSrc) {

我想知道是否有人找到了一种方法来确定主机与stm32f40x芯片通信的意图?从stm32f40x芯片固件的角度来看,主机发送的地址不可用,其中包含的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__);
}
静态内联无效LLEVInterrupt(uint16\u t irqSrc)
{
uint8_t i;
易失性uint16_t状态;
I2CCBStruct*缓冲区;
I2C_TypeDef*addrBase;
//查看发生的IRQ,相应地处理。。。
交换机(irqSrc)
{
案例I2C_总线_CHAN_1:
addrBase=this.addrBase1;
缓冲区=&this.buffsBus1;
打破
案例I2C_总线_CHAN_2:
addrBase=this.addrBase2;
缓冲区=&this.buffsBus2;
打破
案例I2C_总线_CHAN_3:
addrBase=this.addrBase3;
缓冲区=&this.buffsBus3;
打破
违约:
而(1),;
}
//…检测到开始条件和地址匹配
if(I2C_GetITStatus(addrBase,I2C_IT_ADDR)==SET)
{
//I2C_IT_ADDR:通过软件读取SR1寄存器,然后读取SR2,或通过硬件进行清除
//当PE=0时。
//注意:在读取I2C_SR1之后读取I2C_SR2将清除ADDR标志,即使ADDR标志已被删除
//在读取I2C_SR1后设置。因此,当找到ADDR时,I2C_SR2必须为只读
//在I2C_SR1或清除STOPF位时设置。
status=addrBase->SR1;
status=addrBase->SR2;
//重置索引和接收计数
缓冲区->txIndex=0;
缓冲区->rxCount=0;
//设置为确认任何接收字节
I2C_确认图(添加数据库,启用);
回来
}
//从接收机模式
if(I2C_GetITStatus(addrBase,I2C_IT_RXNE)==SET)
{
//I2C_IT_RXNE:通过软件读取或写入DR寄存器进行清除
//或在PE=0时通过硬件。
//将接收到的字节复制到Rx缓冲区
buffers->rxBuf[buffers->rxCount]=(uint8_t)I2C_读取寄存器(addrBase,I2C_寄存器\u DR);
如果(接收缓冲区大小>缓冲区->接收计数)
{
缓冲区->rxCount++;
}
回来
}
//从发射机模式
if(I2C_GetITStatus(addrBase,I2C_IT_TXE)==SET)
{
//I2C_IT_TXE:通过软件写入DR寄存器或
//在启动或停止条件后或PE=0时通过硬件。
//发送剩余的字节
I2C_SendData(addrBase,buffers->txBuf[buffers->txIndex]);
如果(缓冲区->txIndextxCount)
{
缓冲区->txIndex++;
}
回来
}
//…检测到停止条件
if(I2C_GetITStatus(addrBase,I2C_IT_STOPF)==SET)
{
//STOPF(停止检测)通过软件顺序清除:读取操作
//到I2C_SR1寄存器(I2C_GetITStatus()),然后执行写入操作
//I2C_CR1寄存器(I2C_Cmd()用于重新启用I2C外围设备)。
//参考手册RM0368:
//图163.从接收机的传输序列图
//如果(STOPF==1){READ SR1;WRITE CR1}
//清除IRQ状态
status=addrBase->SR1;
//写入CR1
I2C_Cmd(addrBase,ENABLE);
//读取循环(重置状态?
如果(缓冲区->txCount>0)
{
缓冲区->txCount=0;
缓冲区->txIndex=0;
}
//写周期开始了吗?
如果(缓冲区->rxCount>0)
{
//将I2C数据传递给已启用的协议处理程序
对于(i=0;irxCount;i++)
{
#if(通信协议==通信协议调试)
状态=扩展数据(缓冲区->rxBuf[i]);
#elif(通信协议==通信协议PTEK)
状态=PTEKProcRxData(缓冲区->rxBuf[i]);
#否则
#错误**选择的主机协议无效**
#恩迪夫
如果(状态!=ST_OK)
{
日志错误(ST通信故障,线路故障);
}
}
缓冲区->rxCount=0;
}
回来
}
if(I2C_GetITStatus(addrBase,I2C_IT_AF)==SET)
{
//在传输的最后一个字节上从主机接收的NAck
//显示为确认故障,必须由
//将0写入SR1中的AF位。
//这不是真正的错误,而是i2c从机传输过程的工作原理。
//硬件无法知道要传输多少字节,因此
//假设NAck是一个失败的字节传输。
//EV3-2:AF=1;通过在SR1寄存器的AF位中写入“0”来清除AF。
I2C_ClearITPendingBit(添加数据库、I2C_IT_AF);
回来
}
if(I2C_GetITStatus(addrBase,I2C_IT_BERR)==SET)
{
//使用I2C棒测试时,总线错误极为罕见。
//进行此检查和清除比冒险
//无限循环中断
//当接口检测到SDA上升或下降时,由硬件设置
//SCL高时的边缘,在故障期间发生在无效位置
//字节传输。
//通过软件写入0清除,或在PE=0时通过硬件清除。
I2C_ClearITPendingBit(添加数据库,I2C_IT_BERR);
日志错误(ST通信故障,线路故障);
回来
}
if(I2C_GetITStatus(addrBase,I2C_IT_OVR)==SET)
{
//检查其他