ylq1433223 发表于 2025-4-24 08:53

N32WB452CEQ6单片机I2C异常

在多次使用I2C和从机通信中,发现经常会有单片机I2C开始条件执行过后,状态寄存器为0的异常情况,经抓过波形发现单片机确实没有发出开始条件,各位大佬,帮忙看看代码是不会有什么问题uint8_ti2c_master_recv(u8* pBuffer, uint8_t ReadAddr, uint16_t NumByteToRead)
{
                if(NumByteToRead > 1)
                {
                        /** Disable Acknowledgement */
                        I2C_ConfigAck(I2C2, ENABLE);
                }
                I2CTimeout = I2CT_LONG_TIMEOUT;
    while (I2C_GetFlag(I2C2, I2C_FLAG_BUSY))
    {
                        if((I2CTimeout --) == 0)
                        {
      I2C_TIMEOUT_UserCallback(MASTER_BUSY);                               
                                return 0;
                        }                       
    }               
    /** Send START condition */               
    // send start   
//                I2C_Enable(I2C2,DISABLE);
//                I2C_Enable(I2C2,ENABLE);
    I2C_GenerateStart(I2C2, ENABLE);
                I2CTimeout = I2CT_LONG_TIMEOUT;
    /** Test on EV5 and clear it */
    while (!I2C_CheckEvent(I2C2, I2C_EVT_MASTER_MODE_FLAG))
    {
                        if((I2CTimeout --) == 0)
                        {
      I2C_TIMEOUT_UserCallback(MASTER_MODE);                               
                                return 0;
                        }
    }
                /** Send write address for write */
    I2C_SendAddr7bit(I2C2, 0x40, I2C_DIRECTION_SEND);
    /** Test on EV6 and clear it */
    I2CTimeout = I2CT_LONG_TIMEOUT;
    while (!I2C_CheckEvent(I2C2, I2C_EVT_MASTER_TXMODE_FLAG))
    {
                        if((I2CTimeout --) == 0)
                        {
      I2C_TIMEOUT_UserCallback(MASTER_TXMODE);
                                return 0;
                        }
    }
                I2C_Enable(I2C2, ENABLE);
                I2C_SendData(I2C2, ReadAddr);
//    /** Test on EV8 and clear it */
    I2CTimeout = I2CT_LONG_TIMEOUT;
    while (!I2C_CheckEvent(I2C2, I2C_EVT_MASTER_DATA_SENDED))
    {
                        if((I2CTimeout --) == 0)
                        {
      I2C_TIMEOUT_UserCallback(MASTER_SENDING);
                                return 0;
                        }
    }
                /** Send STRAT condition a second time */
    I2C_GenerateStart(I2C2, ENABLE);
//    /** Test on EV5 and clear it */
    I2CTimeout = I2CT_LONG_TIMEOUT;
    while (!I2C_CheckEvent(I2C2, I2C_EVT_MASTER_MODE_FLAG))
    {
      if((I2CTimeout --) == 0)
                        {
      I2C_TIMEOUT_UserCallback(MASTER_MODE);
                                return 0;
                        }
    }
//                /** Send EEPROM address for read */
    I2C_SendAddr7bit(I2C2, 0x41, I2C_DIRECTION_RECV);
    /* Test on EV6 and clear it */
    I2CTimeout = I2CT_LONG_TIMEOUT;
                while (!I2C_GetFlag(I2C2, I2C_FLAG_ADDRF))
    {
      if((I2CTimeout --) == 0)
      {
            I2C_TIMEOUT_UserCallback(MASTER_BYTEF);
                                                return 0;
      }
    }
                if(NumByteToRead == 1)
                {
                        /** Disable Acknowledgement */
                        I2C_ConfigAck(I2C2, DISABLE);
                        (void)(I2C2->STS1); /// clear ADDR
                        (void)(I2C2->STS2);
                        I2C_GenerateStop(I2C2, ENABLE);
                }
                else
                {
                        I2C_ConfigAck(I2C2, ENABLE);
                        (void)(I2C2->STS1);
                        (void)(I2C2->STS2);
                        while(NumByteToRead)
                        {                               
                                if(NumByteToRead == 1)
                                {
                                        /** Disable Acknowledgement */
                                        I2C_ConfigAck(I2C2, DISABLE);
                                        I2C_GenerateStop(I2C2, ENABLE);
                                }
                                /** Wait until RXNE flag is set */
                                I2CTimeout = I2CT_LONG_TIMEOUT;
                                while (!I2C_GetFlag(I2C2, I2C_FLAG_RXDATNE))
                                {
                                        if((I2CTimeout --) == 0)
                                        {
                                                I2C_TIMEOUT_UserCallback(MASTER_BYTEF);
                                                return 0;
                                        }
                                }
                                /** Read data from DAT */
                                /** Read a byte from the EEPROM */
                                *pBuffer++ = I2C_RecvData(I2C2);
                                NumByteToRead--;                       
                        }
                        //I2C_GenerateStop(I2C2, ENABLE);
                }
                return 1;
}

ylq1433223 发表于 2025-4-24 08:55

N32WB452CEQ6单片机I2C异常

主要是经常在通讯开始的第一个开始条件上,它没发出来,剩下的也不会执行

昊430 发表于 2025-4-24 21:59

就是没有发出吧

ylq1433223 发表于 2025-4-27 08:57

昊430 发表于 2025-4-24 21:59
就是没有发出吧

是的,单片机到这确实没发,多次执行发送启动条件也是没有发出,只能暂时通过重新初始化I2C解决这个问题

qeeuly 发表于 2025-4-29 09:49

仿真查看寄存器值

技术工程师 发表于 2025-4-29 11:27

建议还是用模拟I2C,硬件I2C大大小小都有些问题

probedog 发表于 2025-5-27 10:58

I2C总线的硬件连接是否正确,包括SCL和SDA线的上拉电阻。

classroom 发表于 2025-5-27 10:59

检查I2C时钟配置是否正确。

flycamelaaa 发表于 2025-5-27 11:00

I2C_EVT_MASTER_TXMODE_FLAG是用于指示I2C控制器已进入发送模式的事件标志。确保从机地址和方向设置正确。

powerantone 发表于 2025-5-27 11:00

确保I2C_EVT_MASTER_MODE_FLAG是正确的事件标志,用于指示I2C控制器已进入主模式。

suncat0504 发表于 2025-5-28 18:54

建议先用I2C例程测试。没问题再改造为自己的处理。

suncat0504 发表于 2025-5-28 18:56

要想让硬件的I2C外设正常工作,需要很多设置。看看设置处理是否被执行了。

suncat0504 发表于 2025-5-28 18:58

必要的话,在程序的每个分支中加入log输出,通过log,看看程序是否是按照你设想的逻辑顺序执行的。
页: [1]
查看完整版本: N32WB452CEQ6单片机I2C异常