EEPROM 存储有问题。外部 EEPROM 负责数据传输,但在读取时仅返回 255

Having issues with EEPROM storage. External EEPROM acks data transfer, but only returns 255 when read

提问人:bbeeb8 提问时间:3/25/2023 最后编辑:the busybeebbeeb8 更新时间:3/30/2023 访问量:161

问:

我正在做一个项目,其中一部分我正在尝试使用 Harmony I2C 驱动程序库,以便使用 SDA 和 SCL 线路向 eeprom 发送数据。

当使用示波器读取 SDA 和 SCL 线路时,正确的位序列被传递到 EEPROM,EEPROM 对数据进行确认。但是,当尝试从 EEPROM 读取时,它会发回所有 1。此外,当调用内置 I2C 函数时,它会返回 0 字节的读取和写入。DRV_I2C_BytesTransferred

在过去的几天里,我一直在进行故障排除,但我似乎找不到导致这种情况的原因。

我在 MPLAB X IDE 上使用 PIC32MZ1024ECM144-I/PL 微控制器和 Harmony V2.06。我正在使用的 EEPROM 是 M24C02-RMN6TP。

以下是写入 EEPROM 时的示波器:

Oscilloscope when writing

以下是从 EEPROM 读取时的示波器:

enter image description here

enter image description here

以下是EEPROM读写功能。对 和 的调用是在此处未列出的单独函数中调用的,并且读取和写入函数调用之间存在额外的延迟。eepromWriteeepromRead

SYS_MODULE_OBJ objectHandle;

uint8_t deviceAddressSlave;

uint8_t numOfBytes;

uint8_t         TXbuffer[32];

/* I2C driver RX Buffer */
uint8_t         RXbuffer[32];

DRV_I2C_BUFFER_EVENT APP_Check_Transfer_Status(DRV_HANDLE drvOpenHandle, DRV_I2C_BUFFER_HANDLE drvBufferHandle);

uint32_t    APP_Number_Of_Bytes_Transferred(DRV_HANDLE drvOpenHandle, DRV_I2C_BUFFER_HANDLE drvBufferHandle);



DRV_HANDLE drvI2CMasterHandle; //Returned from DRV_I2C_Open for I2C Master
DRV_I2C_BUFFER_HANDLE bufHandle_M1; //Returned from calling a Data Transfer function
uintptr_t i2cOpStatus; //Operation status of I2C operation returned from callback
DRV_HANDLE drvI2CSlaveHandle; //Returned from DRV_I2C_Open for I2C Slave
DRV_I2C_BUFFER_HANDLE bufHandle_S1; //Returned from calling a Data Transfer function
DRV_I2C_BUFFER_HANDLE bufHandle_S2; //Returned from calling a Data Transfer function

typedef enum {
    
        TxRx_OPEN = 0,
        TxRx_TO_EXTERNAL_SLAVE,
        TxRx_EXTERNAL_SLAVE_STATUS_CHECK_1,
        TxRx_STATUS_CHECK,
        TxRx_COMPLETED

} APP_EEPROM_WR_STATES;

static APP_EEPROM_WR_STATES appWriteState = TxRx_OPEN;

DRV_I2C_BUFFER_EVENT Transaction;


bool APP_Write_Tasks(void)
{
    switch (appWriteState)
    {
        case TxRx_OPEN:
        {;
            /* Open the I2C Driver for Master */
            appData.drvI2CHandle_Master = DRV_I2C_Open( DRV_I2C_INDEX_0,
                                                     DRV_IO_INTENT_READWRITE );

            if(appData.drvI2CHandle_Master != DRV_HANDLE_INVALID)
            {
                
                appWriteState = TxRx_TO_EXTERNAL_SLAVE;
            }
            else
            {
                appData.state = APP_STATE_ERROR;
            }

            break;
        }
        case TxRx_TO_EXTERNAL_SLAVE:
        {    
            /* Number of bytes to transfer */
            numOfBytes = 3;

            deviceAddressSlave = 0xA0;
            
            
            if ( (appData.appI2CWriteBufferHandle[0] == DRV_I2C_BUFFER_HANDLE_INVALID) || 
                    (APP_Check_Transfer_Status(appData.drvI2CHandle_Master,     appData.appI2CWriteBufferHandle[0]) == DRV_I2C_BUFFER_EVENT_COMPLETE) ||
                        (APP_Check_Transfer_Status(appData.drvI2CHandle_Master, appData.appI2CWriteBufferHandle[0]) == DRV_I2C_BUFFER_EVENT_ERROR) )
            {
                
           
                appData.appI2CWriteBufferHandle[0] = DRV_I2C_Transmit (appData.drvI2CHandle_Master,deviceAddressSlave, &TXbuffer[0], numOfBytes, NULL);

                
            }
             
            if (APP_Check_Transfer_Status(appData.drvI2CHandle_Master, appData.appI2CWriteBufferHandle[0]) == DRV_I2C_BUFFER_EVENT_ERROR){
            }

            appWriteState = TxRx_EXTERNAL_SLAVE_STATUS_CHECK_1;
            
            break;
        }   
        case TxRx_EXTERNAL_SLAVE_STATUS_CHECK_1:
        {
            Transaction = APP_Check_Transfer_Status(appData.drvI2CHandle_Master, appData.appI2CWriteBufferHandle[0]);
            appWriteState =TxRx_STATUS_CHECK;
            if  ( Transaction == DRV_I2C_BUFFER_EVENT_COMPLETE)
            {
                appWriteState =TxRx_STATUS_CHECK;
            }
             else if  (Transaction == DRV_I2C_BUFFER_EVENT_ERROR)  //Useful for error checking
            {
                appWriteState =TxRx_STATUS_CHECK;
            }
            
            break;
        }        
        case TxRx_STATUS_CHECK:
        {
            
// Only defined for dynamic driver.            
            #ifdef DRV_I2C_CLIENTS_NUMBER            
extern const DRV_I2C_INIT drvI2C0InitData;
            DRV_I2C_Close( appData.drvI2CHandle_Master );
            DRV_I2C_Deinitialize (sysObj.drvI2C0);
            #endif
            
            DelayMs(800);
            #ifdef DRV_I2C_CLIENTS_NUMBER            
            sysObj.drvI2C0 = DRV_I2C_Initialize(DRV_I2C_INDEX_0, (SYS_MODULE_INIT *)&drvI2C0InitData);
            #endif
            
            /* to run the application only once,  
             * set next state to TxRx_COMPLETED */
//            appWriteState = TxRx_COMPLETED;
            
            /* to run the application in a continuous loop,  
             * set next state to TxRx_OPEN */
            #ifdef DRV_I2C_CLIENTS_NUMBER            
            appWriteState = TxRx_COMPLETED;
            #else
            appWriteState = TxRx_TO_EXTERNAL_SLAVE;
            #endif
            break;
        }
        case TxRx_COMPLETED:
        {
            return true;
            break;
        }
    }
    
    return false;
}




void writeEEPROM(void) {
    TXbuffer[0] = 0xF0;
    TXbuffer[1] = ((unsigned short)300 >> 8); //1
    TXbuffer[2] = (char) 300; //44
    
    
    
    while (!APP_Write_Tasks());
    
    DRV_I2C_Close( appData.drvI2CHandle_Master );
}




void readEEPROM(void) {
    appData.drvI2CHandle_Master = DRV_I2C_Open( DRV_I2C_INDEX_0, DRV_IO_INTENT_READWRITE );
    /*memset(TXbuffer, 0, sizeof TXbuffer);  //Used when not calling write function
    deviceAddressSlave = 0xA0;
    numOfBytes = 3;  
    TXbuffer[0] = 0xF0;
    TXbuffer[1] = ((unsigned short)300 >> 8); //1
    TXbuffer[2] = (char) 300; //44*/
    
    appData.appI2CReadBufferHandle[0] = DRV_I2C_TransmitThenReceive(appData.drvI2CHandle_Master, 0xA0, &TXbuffer[0], 1, &RXbuffer, 2, NULL);

    DRV_I2C_Close(appData.drvI2CHandle_Master);
}



DRV_I2C_BUFFER_EVENT APP_Check_Transfer_Status(DRV_HANDLE drvOpenHandle, DRV_I2C_BUFFER_HANDLE drvBufferHandle)
{
    return (DRV_I2C_TransferStatusGet (appData.drvI2CHandle_Master, drvBufferHandle));
}

uint32_t APP_Number_Of_Bytes_Transferred(DRV_HANDLE drvOpenHandle, DRV_I2C_BUFFER_HANDLE drvBufferHandle)
{
    return (DRV_I2C_BytesTransferred (appData.drvI2CHandle_Master,drvBufferHandle));
}

这些函数基于 Harmony 附带的驱动程序示例代码。我一直在测试将分成 2 个字节的值 300 发送到 EEPROM。但是,无论我尝试什么地址或发送什么值,EEPROM都只发回255,即所有位都设置为1。EEPROM上有阻止写入的写控制,但是我已经确认写入模块当前已禁用。

C 微芯片 EEPROM 谐波

评论

0赞 Joshua 3/25/2023
总是读取 255 通常是一个坏的 EEPROM。但也许你的代码很糟糕。
0赞 Ian Abbott 3/25/2023
在“写入”迹线上,STOP序列开始时SCL信号上的低频毛刺看起来有点奇怪。
0赞 chux - Reinstate Monica 3/25/2023
bbeeb8,提示:使用自动格式化程序来改善代码的外观和清晰度。

答:

1赞 Vladimir 3/25/2023 #1

在可能的情况下,EEPROM需要一些延迟来写入数据。

第一步 - 尝试在写入函数 200 毫秒后使用延迟。 如果您要读取写入的数据,下一步是检查数据写入过程是否完成:enter image description here

前任:

/**
 * @brief  Check if device present or ready
 * @param  [in] i2c_addr I2C devices address
 * @retval true if ok or ready
 */
bool i2c_is_bevice_present (uint8_t i2c_addr) {
    _tx_buf_len = 0;
    if (i2c_transmit(i2c_addr, true) != I2C_SUCCESS) {
        return false;
    }
    return true;
}


static bool is_m24c02_ready (void) {
    return i2c_is_bevice_present(M42C02_I2C_ADDRES_MEMORY);
}

/**
 * @brief  M24C02 write byte
 * @param  [In] addres Addres
 * @param  [In] data byte to write
 * @retval none
 */
void m24c02_write_byte(uint16_t addres, uint8_t data) {
    while (is_m24c02_ready() == false);
    m24c02_i2c_write(addres, &data, 1);
    while (is_m24c02_ready() == false);
}

评论

0赞 bbeeb8 3/28/2023
我试图添加延迟并检查写入是否已完成,但我仍然遇到同样的问题。即使在检查显示 EEPROM 不再写入后,读取也会返回所有 1。
0赞 bbeeb8 3/30/2023 #2

所以我找到了一个解决方案。我不确定到底是什么问题,但我认为我使用的 I2C 驱动程序没有正确发送 I2C 停止条件,这导致 EEPROM 无法启动内部写入周期。

我找到的解决方案包括在 Harmony 配置设置中打开 Bit Bang I2C 实现,并将勘误方法设置为BIT_BANG_STOP。在那之后,我不再有任何阅读或写作错误,上面的代码也正常工作。