提问人:bbeeb8 提问时间:3/25/2023 最后编辑:the busybeebbeeb8 更新时间:3/30/2023 访问量:161
EEPROM 存储有问题。外部 EEPROM 负责数据传输,但在读取时仅返回 255
Having issues with EEPROM storage. External EEPROM acks data transfer, but only returns 255 when read
问:
我正在做一个项目,其中一部分我正在尝试使用 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 时的示波器:
以下是从 EEPROM 读取时的示波器:
以下是EEPROM读写功能。对 和 的调用是在此处未列出的单独函数中调用的,并且读取和写入函数调用之间存在额外的延迟。eepromWrite
eepromRead
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上有阻止写入的写控制,但是我已经确认写入模块当前已禁用。
答:
在可能的情况下,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 无法启动内部写入周期。
我找到的解决方案包括在 Harmony 配置设置中打开 Bit Bang I2C 实现,并将勘误方法设置为BIT_BANG_STOP。在那之后,我不再有任何阅读或写作错误,上面的代码也正常工作。
评论