问答

汇集网友智慧,解决技术难题

21ic问答首页 - GD32E230作为IIC从机时接收数据会卡顿是什么原因

MCU 接收 GD32E230 IIC从机 卡顿 原因

GD32E230作为IIC从机时接收数据会卡顿是什么原因

Henry-hu2024-08-29
在配置完成IIC从机模式后,主机向从机发送9位数据,在从机收到数据后主函数的代码会跑不到,不知道在什么地方造成了阻塞,接收完毕会产生多次的STPDEF中断吗,但是IIC从机模式的故障应该也不会影响到主函数的运行才对,有没有懂的大佬帮忙分析一下谢谢,代码如下#include "gd32e230.h"

#define MSG_RECV_BYTE_SUM 9
#define MSG_SEND_BYTE_SUM 6

#define I2C0_OWN_ADDRESS7 0x44

void iic_msg_gpio_config_init(void)
{
    /* enable GPIOB clock */
    rcu_periph_clock_enable(RCU_GPIOB);
    /* enable I2C0 clock */
    rcu_periph_clock_enable(RCU_I2C0);

    /* connect PB6 to I2C0_SCL */
    gpio_af_set(GPIOB, GPIO_AF_1, GPIO_PIN_6);
    /* connect PB7 to I2C0_SDA */
    gpio_af_set(GPIOB, GPIO_AF_1, GPIO_PIN_7);
    /* configure GPIO pins of I2C0 */
    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_6);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_7);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_7);

    /* I2C clock configure */
    i2c_clock_config(I2C0, 400000, I2C_DTCY_2);
    /* I2C address configure */
    i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, I2C0_OWN_ADDRESS7);
    /* enable I2C0 */
    i2c_enable(I2C0);
    /* enable acknowledge */
    i2c_ack_config(I2C0, I2C_ACK_ENABLE);

    nvic_irq_enable(I2C0_EV_IRQn, 23);
    nvic_irq_enable(I2C0_ER_IRQn, 32);

    /* enable the I2C0 interrupt */
    i2c_interrupt_enable(I2C0, I2C_INT_ERR);
    i2c_interrupt_enable(I2C0, I2C_INT_EV);
    i2c_interrupt_enable(I2C0, I2C_INT_BUF);
}

void i2c0_event_irq_handler(void)
{
    if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_ADDSEND))
    {
        // 0:接收端
        // 1:发送端
        tI2cSlave.uFlag.Bits.DirState = i2c_flag_get(I2C0, I2C_FLAG_TR);
        if (tI2cSlave.uFlag.Bits.DirState == RESET)
        {
            msg_iic_recv_buf_count = 0;

            for (uint8_t i = 0; i < MSG_RECV_BYTE_SUM; i++)
            {
                i2c_rxbuffer1[i = 0;
            }
        }
        else
        {
            /* clear I2C_TDATA register */
            i2c_flag_clear(I2C0, I2C_FLAG_TBE);

            slave_msg_send.soft_versions = 0x00;
            i2c_txbuffer[0 = slave_msg_send.soft_versions;

            i2c_txbuffer[1 = slave_msg_send.KEY_state;

            slave_msg_send.reserved_1 = 0x00;
            slave_msg_send.reserved_2 = 0x00;
            slave_msg_send.reserved_3 = 0x00;

            i2c_txbuffer[2 = slave_msg_send.reserved_1;

            i2c_txbuffer[3 = slave_msg_send.reserved_2;

            i2c_txbuffer[4 = slave_msg_send.reserved_3;

            slave_msg_send.check_sum = 0;
            uint32_t cheak = 0;
            cheak += i2c_txbuffer[0];
            cheak += i2c_txbuffer[1];
            cheak += i2c_txbuffer[2];
            cheak += i2c_txbuffer[3];
            cheak += i2c_txbuffer[4];

            cheak = ~cheak;
            cheak = cheak + 1;

            i2c_txbuffer[5 = cheak;
            slave_msg_send.check_sum = cheak;

            msg_iic_send_buf_count = 0;
        }
        /* clear the ADDSEND bit */
        i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_ADDSEND);
    }
    else if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_RBNE)) // && dma_flag_get(DMA_RX_CH, DMA_FLAG_FTF)
    {
        if (msg_iic_recv_buf_count < MSG_RECV_BYTE_SUM)
        {
            i2c_rxbuffer1[msg_iic_recv_buf_count = i2c_data_receive(I2C0);

            if (msg_iic_recv_buf_count == (MSG_RECV_BYTE_SUM - 1))
            {
                UpdateReceiveProc();
            }
            ++msg_iic_recv_buf_count;
        }
        else
        {
            i2c_data_receive(I2C0);
        }
    }
    else if ((i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_TBE))) // && dma_flag_get(DMA_TX_CH, DMA_FLAG_FTF)
    {
        /* send a data byte */
        if (msg_iic_send_buf_count < MSG_SEND_BYTE_SUM)
        {
            /* if reception data register is not empty, I2C0 will read a data from I2C_RDATA */
            i2c_data_transmit(I2C0, i2c_txbuffer[msg_iic_send_buf_count]);

            msg_iic_send_buf_count++;
        }
        else
        {
            i2c_data_transmit(I2C0, 0xff);
        }
    }
    else if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_STPDET))
    {
        /* clear STPDET interrupt flag */
        i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_STPDET);

        if (tI2cSlave.uFlag.Bits.DirState == RESET)
        {
            tI2cSlave.uFlag.Bits.RecSuccess = SUCCESS;
            msg_iic_recv_buf_count = 0x00;
        }
        else
        {
            tI2cSlave.uFlag.Bits.SendSuccess = SUCCESS;
            tI2cSlave.SendSize = 0x00; // 避免没有接收到命令重新发数据
            msg_iic_send_buf_count = 0x00;
        }

        i2c_enable(I2C0);
    }
    else if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_AERR))
    {
        /* clear STPDET interrupt flag */
        i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_AERR);
        tI2cSlave.uFlag.Bits.SendSuccess = SUCCESS;
    }
}

void i2c0_error_irq_handler(void)
{
    /* no acknowledge received */
    if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_AERR))
    {
        i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_AERR);
    }

    /* SMBus alert */
    if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SMBALT))
    {
        i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBALT);
    }

    /* bus timeout in SMBus mode */
    if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SMBTO))
    {
        i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBTO);
    }

    /* over-run or under-run when SCL stretch is disabled */
    if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_OUERR))
    {
        i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_OUERR);
    }

    /* arbitration lost */
    if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_LOSTARB))
    {
        i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_LOSTARB);
    }

    /* bus error */
    if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_BERR))
    {
        i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_BERR);
    }

    /* CRC value doesn't match */
    if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_PECERR))
    {
        i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_PECERR);
    }

    /* disable the I2C0 interrupt */
    i2c_interrupt_disable(I2C0, I2C_INT_ERR);
    i2c_interrupt_disable(I2C0, I2C_INT_BUF);
    i2c_interrupt_disable(I2C0, I2C_INT_EV);
}

void I2C0_EV_IRQHandler(void)
{
    i2c0_event_irq_handler();
}

void I2C0_ER_IRQHandler(void)
{
    i2c0_error_irq_handler();
}



回答 +关注 5
2139人浏览 9人回答问题 分享 举报
9 个回答

您需要登录后才可以回复 登录 | 注册