Возникли проблемы с хранилищем EEPROM. Внешняя EEPROM подтверждает передачу данных, но при чтении возвращает только 255.
Я работаю над проектом и частично пытаюсь использовать библиотеку драйверов Harmony I2C для отправки данных в и из eeprom, используя линии SDA и SCL.
При чтении строк SDA и SCL с помощью осциллографа правильная последовательность битов передается в EEPROM, и EEPROM подтверждает данные. Однако при попытке чтения из EEPROM он отправляет обратно все 1. Кроме того, при вызове встроенной функции I2C
Последние несколько дней я устранял неполадки, но не могу найти причину этого.
Я использую микроконтроллер 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. После этого у меня больше не было ошибок чтения или записи, и приведенный выше код работал как надо.