关于同时使用两条IIC总线中断问题

使用GD32的两条IIC总线,IIC0配置为主机中断接收数据,IIC1配置为从机中断发送数据,两个中断优先级相同,但是接收的数据不正确是怎么回事儿?

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 这篇博客: GD32F407之硬件IIC(从机模式)中的 将发送和接收数据整合在一起,整合一定要注意接收和发送的标志位不同, 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
    oid Si2c_Transfer_Data(uint32_t i2c_periph,BYTE Channel)
    {
        /* wait until ADDSEND bit is set */
        if(i2c_flag_get(i2c_periph, I2C_ADDSEND)){
            ADDSEND_FLAG=1;
            /* clear ADDSEND bit */
            i2c_flag_clear(i2c_periph, I2C_ADDSEND);
        }
        if(ADDSEND_FLAG){
            if(i2c_flag_get(i2c_periph, I2C_RBNE) && (SRFalg ==0)){
                /*  Receive register  addr*/
                SReceAddrBuffer[Channel] = i2c_receive_data(i2c_periph);
                SRFalg = 1;
            }
            if(SReceAddrBuffer[Channel] != 0XFF){
                if(i2c_flag_get(i2c_periph, I2C_TBE)){
                    /* Send a word data */
                    MatchAdd_SendData(i2c_periph,SReceAddrBuffer[Channel]);
                    ADDSEND_FLAG=0;
                    SRFalg = 0;
                }
    
                if((SRFalg==1) && i2c_flag_get(i2c_periph, I2C_RBNE)){
                    /*Receive a byte data */
                    SReceDataBuffer[Channel] = i2c_receive_data(i2c_periph);
                    MatchAdd_ReceData(SReceAddrBuffer[Channel],SReceDataBuffer[Channel]);
                }
    
                if(i2c_flag_get(i2c_periph, I2C_STPDET)){
                    /* Receive mode clear the STPDET bit */
                    ic20Flag = 2;
                    SRFalg = 0;
                    ADDSEND_FLAG=0;
                    i2c_enable(i2c_periph);
                    i2c_interrupt_disable(i2c_periph, I2C_CTL1_ERRIE | I2C_CTL1_BUFIE | I2C_CTL1_EVIE);
                }
                if(ic20Flag == 2){
                    i2c_interrupt_enable(i2c_periph, I2C_CTL1_ERRIE | I2C_CTL1_BUFIE | I2C_CTL1_EVIE);
                    ic20Flag = 0;
                }
            }
        }
    }

    注意:首先我们知道,,一般的IIC从设备都是有很多寄存器地址的,所以我们主机肯定也会发一个寄存器地址过来,官方源码里面是没有做处理的就当做(0x00),所以在整合的代码里面我有两次接收数据一个是寄存器地址放到地址数组和一个是数据放到了数据数组中。

    5、接收发送处理函数

    接收一个WORD数据

    void MatchAdd_ReceData(BYTE Cmd,BYTE Data)
    { 
        if (Cmd == 0x02)
        {   /* Currently system power state. */
            PwrState.byte = Data;
        } 
        else if (Cmd == 0xB3)
        {   /* button event state */
            ButtState.byte = Data;
        }
        else if (Cmd == 0xB4)
        {   /* button event number */
            SCINumber = Data;
        }
            
        else if (Cmd == 0xB5)
        {  
            HeartBeatEnable = Data;
        } 
        else if (Cmd == 0xB6)
        {  
            HeartBeatTimer = Data;
        }
        else if (Cmd == 0xB7)
        {  
            HeartBeatFlag = Data;
        }
    }

    发送一个WORD数据

    void MatchAdd_SendData(uint32_t i2c_periph ,BYTE Cmd)
    {
        WORD rval = 0;
        WORD *pntr;
        if (Cmd == 0x02)
        {   /* Currently system power state. */
            rval = (WORD) PwrState.byte;
        } 
        else if (Cmd == 0xB3)
        {   /* button event state */
            rval = (WORD) ButtState.byte;
        }
        else if (Cmd == 0xB4)
        {   /* button sci event number */
            rval = (WORD) SCINumber;
        }
    
        i2c_transmit_worddata(i2c_periph,rval);
    }

    注意:接受和发送的寄存器其实是同一个地址,通俗说就是从机有一个0x00--0xFF的地址的寄存器来让主机读写

    官方里面没有发送一个Word数据函数,修改如下

    void i2c_transmit_worddata(uint32_t i2c_periph, uint16_t Data)
    {
        /* send a data byte */
        I2C_DATA(i2c_periph) = Data;
        I2C_DATA(i2c_periph) = Data>>8;
    }

    6、中断函数

    void I2C0_EV_IRQHandler(void)
    {
        //DEBUG(0XAA);
        Si2c_Transfer_Data(I2C0,0);
    }

    到此GD32F407硬件IIC就结束了,其实硬件模式的从机还是比主机简单很多,主要是文档非常详细。

     


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^