Возникли проблемы с хранилищем EEPROM. Внешняя EEPROM подтверждает передачу данных, но при чтении возвращает только 255.

Я работаю над проектом и частично пытаюсь использовать библиотеку драйверов Harmony I2C для отправки данных в и из eeprom, используя линии SDA и SCL.

При чтении строк SDA и SCL с помощью осциллографа правильная последовательность битов передается в EEPROM, и EEPROM подтверждает данные. Однако при попытке чтения из EEPROM он отправляет обратно все 1. Кроме того, при вызове встроенной функции I2C, он возвращает 0 байт как для чтения, так и для записи.

Последние несколько дней я устранял неполадки, но не могу найти причину этого.

Я использую микроконтроллер PIC32MZ1024ECM144-I/PL и Harmony V2.06 в MPLAB X IDE. EEPROM, с которым я работаю, — M24C02-RMN6TP.

Вот осциллограф при записи в EEPROM:

Вот осциллограф при чтении из EEPROM:

Вот функции чтения и записи EEPROM. Звонок вивызываются в отдельной функции, не указанной здесь, и между вызовами функций чтения и записи возникает дополнительная задержка.

      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. Я тестировал отправку значения 300, разделенного на 2 байта, в EEPROM. Однако независимо от того, какой адрес я пытаюсь использовать или какие значения я отправляю, EEPROM только каждый отправляет обратно 255, IE все биты установлены в 1. В EEPROM есть контроль записи, который блокирует запись, однако я подтвердил, что блок записи в настоящее время отключен. .

2 ответа

Возможно, EEPROM потребуется некоторая задержка для записи данных.

Первый шаг — попробуйте использовать задержку после функции записи 200 мс. Если вы прочитаете записанные данные, следующим шагом будет проверка завершения процесса записи данных:

Бывший:

      /**
 * @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);
}

Итак, я нашел решение. Я не уверен, в чем именно заключалась проблема, но я думаю, что драйверы I2C, которые я использовал, неправильно отправляли условие остановки I2C, из-за чего EEPROM не запускал внутренний цикл записи.

Решение, которое я нашел, включает в себя включение реализации Bit Bang I2C в настройках конфигурации Harmony и установку метода исправлений BIT_BANG_STOP. После этого у меня больше не было ошибок чтения или записи, и приведенный выше код работал как надо.

Другие вопросы по тегам