问题描述
我使用 AT24C02 external eeprom
连接 stm32f401 nucleo
。我面临的问题很少。
让我们考虑一些地址
/* 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,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,uint16_t len) {
HAL_StatusTypeDef xStatus = HAL_ERROR;
xStatus = HAL_I2C_Mem_Read(&hi2c1,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,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,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
应该处理所有情况,我只会向它发送数据。任何帮助将不胜感激。
问候。
解决方法
您错过了 AT24C02 以 16 字节(写)页的形式组织。 损坏是由在写入以@ offset 0x0A 开头的字符串时翻转/换行@ offset 0x0F 引起的。 详情请参阅数据表。