【问题标题】:Multiple write to external eeprom corrupts previous data多次写入外部 eeprom 会损坏以前的数据
【发布时间】:2021-04-11 01:54:58
【问题描述】:

我正在使用stm32f401 nucleo 连接AT24C02 external eeprom。我面临一些问题。

让我们考虑一些地址

/* 24c02 Device Address */
#define EEPROM_ADDRESS                          (uint8_t)0xA0

/*Demo addr*/
#define DEMO_BYTE_ADDR                          (uint16_t)0x01
#define DEMO_WORD_ADDR                          (uint16_t)0x02
#define DEMO_FLOAT_ADDR                         (uint16_t)0x06
#define DEMO_STRING_ADDR                        (uint16_t)0x0A

1.写作和阅读同时进行。
我能够同时向 eeprom 写入和读取数据。

/*Writing Byte*/
uint8_t byte;
eep_write_byte(DEMO_BYTE_ADDR, 50);
eep_read_byte(DEMO_BYTE_ADDR, &byte);

/*Wrinting word*/
uint32_t word;
eep_write_word(DEMO_WORD_ADDR, 123456789);
word = eep_read_word(DEMO_WORD_ADDR);

/*Writing float*/
float fData;
eep_write_float(DEMO_FLOAT_ADDR, 9876.54);
fData = eep_read_float(DEMO_FLOAT_ADDR);

此代码运行良好。下面是输出的快照。

2。写字符串的问题 在上面的代码部分之后,我写了一些行来写字符串和读字符串。正如您在输出缓冲区中看到的那样,dest 包含一些值。

uint8_t dest[50] = {0};
eep_write_string(DEMO_STRING_ADDR, (uint8_t*)"Hello World!", strlen("Hello World!"));
eep_read_string(DEMO_STRING_ADDR, dest, strlen("Hello World!"));

3.写入所有这些值后,读数显示数据损坏 在上面的代码部分之后,如果我读回我写的所有地址会给我损坏的数据。

eep_read_byte(DEMO_BYTE_ADDR, &byte);
word = eep_read_word(DEMO_WORD_ADDR);
fData = eep_read_float(DEMO_FLOAT_ADDR);
eep_read_string(DEMO_STRING_ADDR, dest, strlen("Hello World!"));

下面是这段代码的快照。

如您所见,所有数据现在都已损坏。

您可以从此链接https://pastebin.com/2vYWYhnw 找到 eeprom.c 或直接滚动到下方。

/*
 * eeprom.c
 *
 *  Created on: 04-Jan-2021
 *      Author: DEVJEET MANDAL
 */

#include "i2c.h"
#include "eeprom.h"

#include "stdio.h"
#include "stdlib.h"

/* Low Level function */
void eep_small_delay(void)          {
    for (uint32_t i = 0; i < 65535; i++)
        __asm__("NOP");
}

void i2c_error(void)    {
    HAL_I2C_DeInit(&hi2c1);     //De-init i2c bus
    __asm__("NOP");
    HAL_I2C_Init(&hi2c1);       //re-init i2c bus
    __asm__("NOP");
}

eep_status_t i2c_write(uint16_t u8_reg_addr, uint8_t *u8_data, uint16_t len)            {
    HAL_StatusTypeDef xStatus = HAL_ERROR;
    xStatus = HAL_I2C_Mem_Write(&hi2c1, EEPROM_ADDRESS, u8_reg_addr, I2C_MEMADD_SIZE_16BIT, u8_data, len, 100);
    HAL_Delay(5);
    if (xStatus != HAL_OK)  {i2c_error();}
    return xStatus;
}

eep_status_t i2c_read(uint16_t u8_reg_addr, uint8_t *u8_data, uint16_t len)         {
    HAL_StatusTypeDef xStatus = HAL_ERROR;
    xStatus = HAL_I2C_Mem_Read(&hi2c1, EEPROM_ADDRESS, u8_reg_addr, I2C_MEMADD_SIZE_16BIT, u8_data, len, 100);
    eep_small_delay();
    if (xStatus != HAL_OK)  {i2c_error();}
    return xStatus;
}

/* High Level Functions */
eep_status_t eep_write_byte(uint16_t u8_reg_addr, uint8_t u8_data)      {
    return i2c_write(u8_reg_addr, &u8_data, 1);
}

eep_status_t eep_read_byte(uint16_t u8_reg_addr, uint8_t *u8_data)      {
    return i2c_read(u8_reg_addr, u8_data, 1);
}

eep_status_t eep_is_data_avaiable(void)                     {
    eep_status_t xStatus = EEP_ERROR;
    uint8_t data = 0;
    eep_read_byte(EEPROM_DATA_AVAILABLE_ADDR, &data);
    if (data == 0)      {xStatus = EEP_ERROR;}
    else if (data == 1) {xStatus = EEP_OK;}
    else                {xStatus = EEP_ERROR;}
    return xStatus;
}

eep_status_t eep_set_data_available(uint8_t val)            {
    return eep_write_byte(EEPROM_DATA_AVAILABLE_ADDR, val);
}

eep_status_t eep_write_word(uint16_t reg_addr, uint32_t value)      {
    uint8_t val_byte[4] = {0};
    val_byte[0] = (value >> 24) & 0xFF;
    val_byte[1] = (value >> 16) & 0xFF;
    val_byte[2] = (value >> 8) & 0xFF;
    val_byte[3] = (value >> 0) & 0xFF;
    return i2c_write(reg_addr, val_byte, 4);
}

eep_status_t eep_write_float(uint16_t reg_addr, float value)        {
    union FtoHex{
        float fval;
        uint32_t hval;
    }float_to_hex;

    float_to_hex.fval = value;
    return eep_write_word(reg_addr, float_to_hex.hval);
}

uint32_t eep_read_word(uint16_t reg_addr)                   {
    uint8_t val_buff[4] = {0};
    i2c_read(reg_addr, val_buff, 4);
    return ((val_buff[0] << 24) | (val_buff[1] << 16) | (val_buff[2] << 8) | (val_buff[3] << 0));
}

float eep_read_float(uint8_t reg_addr)  {
    union FtoHex{
        float fval;
        uint32_t hval;
    }float_to_hex;

    float_to_hex.hval = eep_read_word(reg_addr);
    return float_to_hex.fval;
}

void eep_write_string(uint16_t reg_addr, uint8_t *src, uint16_t len)        {
    i2c_write(reg_addr, src, len);
}

void eep_read_string(uint16_t reg_addr, uint8_t *dest, uint16_t len)            {
    i2c_read(reg_addr, dest, len);
}

//---------------------------------------------------------------------

几乎忘了提及我正在运行 I2C @400Khz。虽然我尝试过 100KHz,但结果相同。 下面是 HAL 生成的 I2C init。

/* I2C1 init function */
void MX_I2C1_Init(void)
{

  hi2c1.Instance = I2C1;
  hi2c1.Init.ClockSpeed = 400000;
  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    Error_Handler();
  }

} 

现在的问题是为什么会出现这个问题。基本上HAL 应该处理所有情况,我只会向它发送数据。任何帮助将不胜感激。

问候。

【问题讨论】:

    标签: stm32 i2c hal eeprom stm32cubeide


    【解决方案1】:

    您错过了 AT24C02 是按 16 字节(写入)页面组织的。 在写入以@偏移0x0A开头的字符串时,损坏是由@偏移0x0F的翻转/换行引起的。 有关详细信息,请参阅数据表。

    【讨论】:

    • 我阅读了数据表,但只在页面写入中发现了翻转。因此,如果我连续写入数据没有出错,它将在页面结束后立即被覆盖。所以我所做的我没有写字符串,而只写了字节、单词和浮点数。我在地址 0x10 中写入的字符串。但同样的问题。
    猜你喜欢
    • 2015-08-18
    • 1970-01-01
    • 1970-01-01
    • 2018-08-07
    • 1970-01-01
    • 2012-12-13
    • 1970-01-01
    • 1970-01-01
    • 2014-01-29
    相关资源
    最近更新 更多