stm32使用i2c读写eeprom的HAL库实现

stm32使用i2c读写eeprom的HAL库实现

本文目标:基于HAL库的stm32实现eeprom的i2c实验

按照本文的描述,应该可以跑通实验并举一反三。

先决条件:装有编译和集成的开发环境,比如:Keil uVision5、STM32CubeMX

使用外设:I2C1、USART1、GPIO

EEPROM(也称为E 2 PROM)代表电可擦除可编程只读存储器,是计算机中使用的一种非易失性存储器,通常集成在智能卡和远程无钥匙系统等微控制器中,或作为一个单独的芯片设备,通过允许擦除和重新编程单个字节来存储相对少量的数据。

实验目的

使用stm32调通eeprom的读写实验,在本实验过程中,我们将涉及 STM32 的 GPIO 端口配置、USART1和 I2C1的使用等

缘起

这篇文章是在搜索资料时,没能找到我想要的资料,于是自己先在自己的硬件平台上进行实战体验一下。

搭建工程

使用STM32CubeMX配置stm32的基本配置。基本的配置如下:开启swd调试,开启外部时钟。

RCC配置

Debug配置

  • 配置USART1,用于printf调试

USART1配置

  • 配置I2C1用于跟i2c设备通讯

I2C1配置

  • 时钟界面选项卡:

时钟配置

  • 工程选项卡:

工程配置展示

工程配置展示

点击右上角的的生成代码:

生成代码

使用keil打开工程,编译工程,一切都是ok

先编译一下生成的文件

开始编写代码,首先要把串口的打印映射好,使用下面的代码片段可用正常使用printf打印

int fputc( int ch, FILE *f )
{
	USART_TypeDef* USARTx = USART1;
	while ((USARTx->SR & (1<<7)) == 0);
	USARTx->DR = ch;
	return ch;
}

接下来就是确定了i2c地址的问题了,使用扫描寻找i2c设备地址,看哪一个有回应。

    uint8_t i=0;
    HAL_StatusTypeDef status;
    for(i=0;i<127;i++)
    {
        status=HAL_I2C_Master_Transmit(&hi2c1,i<<1,0,0,200);
        if(status==HAL_OK)
        {
            printf("i2c addr:0x%02X is ok\r\n",i<<1);
        }
        else if(status==HAL_TIMEOUT)
        {
            printf("i2c addr:0x%02X is timeout\r\n",i<<1);
        }
        else if(status==HAL_BUSY)
        {
            printf("i2c addr:0x%02X is busy\r\n",i<<1);
        }
    }
    printf("scan end\r\n");

发现在板子上有3个地址回应

扫描地址

那么哪个地址是对应我们这次使用eeprom设备呢,通过在网上寻找资料,参考了大牛写的博客:AT24C02 E2PROM芯片详解_24c02读写时序_Z小旋的博客-CSDN博客

0xA0的设备地址就很像本次实验所需要的设备地址。这里扫描出有3个地址有回应,不确定是哪个地址的话,都在软件中尝试一下,毕竟软件搞不坏硬件哈。

接下来编写一个测试函数进行测试一下

#define EEPROM_ADDRESS 0xA0
int hardware_eeprom_mode_test(void)
{
	
	// 定义一个用于存储测试数据和读取结果的数组
	uint8_t test_data[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
	uint8_t read_data[8];

	// 定义一个用于存储操作结果和执行时间的变量
	HAL_StatusTypeDef result;
	uint32_t tickstart;
	uint32_t tickstop;
	uint32_t write_time;
	uint32_t read_time;

	printf("\r\nhardware_eeprom_mode_test\r\n");
	// 检测 eeprom 是否准备就绪 尝试连接10次
	result = HAL_I2C_IsDeviceReady(&hi2c1, EEPROM_ADDRESS, 10, 1000);
	if (result == HAL_OK) // eeprom 准备就绪
	{
			printf("eeprom is ready!\n");
	}
	else // eeprom 连接失败
	{
			printf("eeprom connection error: %d\n", result);
	}

	// 向 eeprom 的地址 0 写入 8 个字节的测试数据
	tickstart = HAL_GetTick(); // 获取写入前的系统时钟计数值
	result = HAL_I2C_Mem_Write(&hi2c1, EEPROM_ADDRESS, 0, I2C_MEMADD_SIZE_8BIT, test_data, 8, 1000);
	tickstop = HAL_GetTick(); // 获取写入后的系统时钟计数值
	write_time = tickstop - tickstart; // 计算写入操作的执行时间
	if (result == HAL_OK) // 写入成功
	{
			printf("eeprom write success!\n");
			printf("eeprom write time: %d ms\n", write_time);
	}
	else // 写入失败
	{
			printf("eeprom write error: %d\n", result);
	}

	// 从 eeprom 的地址 0 读取 8 个字节的数据
	tickstart = HAL_GetTick(); // 获取读取前的系统时钟计数值
	result = HAL_I2C_Mem_Read(&hi2c1, EEPROM_ADDRESS, 0, I2C_MEMADD_SIZE_8BIT, read_data, 8, 1000);
	tickstop = HAL_GetTick(); // 获取读取后的系统时钟计数值
	read_time = tickstop - tickstart; // 计算读取操作的执行时间
	if (result == HAL_OK) // 读取成功
	{
			printf("eeprom read success!\n");
			printf("eeprom read time: %d ms\n", read_time);
			// 打印读取结果
			for (int i = 0; i < 8; i++)
			{
					printf("%02X ", read_data[i]);
			}
			printf("\n");
	}
	else // 读取失败
	{
			printf("eeprom read error: %d\n", result);
	}

	return 0;
}

也可以使用安富莱电子的bsp的eeprom代码进行软件进行测试,这里也展示一下

#define LENS 8

int software_eeprom_mode_test(void)
{
	// 定义一个用于存储测试数据的数组
	uint8_t test_write_data[8] = {0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55};

	// 定义一个用于存储读取结果的数组
	uint8_t read_data[LENS];
	
	uint8_t write_result = 0;
	uint32_t tickstart = 0;
	uint32_t tickstop = 0;
	printf("\r\nsoftware_eeprom_mode_test\r\n");
	bsp_InitI2C();                            // 初始化i2c
  tickstart = HAL_GetTick(); 
	write_result = ee_WriteBytes(test_write_data, 0, sizeof(test_write_data)/sizeof(test_write_data[0])); // 写数据
	tickstop = HAL_GetTick();
	uint32_t write_time = tickstop - tickstart;
	printf("Write result: %d\n", write_result);
	printf("Write time: %d ms\n", write_time);

	tickstart = HAL_GetTick(); 
	uint8_t read_result = ee_ReadBytes(read_data, 0, LENS); // 读数据
	tickstop = HAL_GetTick();
	uint32_t read_time = tickstop - tickstart;
	printf("Read result: %d\n", read_result);
	printf("Read time: %d ms\n", read_time);
	if (read_result == 1)                   // 读取成功
	{
			printf("Read success!\n");
			// 打印读取结果
			for (int i = 0; i < LENS; i++)
			{
					printf("%02X ", read_data[i]);
			}
			printf("\n");
	}
	else // 读取失败
	{
			printf("Read error: %d\n", read_result);
			return -1;
	}

    return 0;
}

其中使用安富莱电子的代码需要进行简单移植一下

移植软件

main.c中的编写的代码片段

编写代码

实验现象

读写eeprom实验现象

可以观察到stm32硬件方式读写8个字节都是1ms,而使用软件方式写时间是4ms,读时间是2ms。硬件方式比软件方式快1倍的时间,对一些时许要求严格的通讯可以考虑使用硬件I2C的方式来实现。

本文中使用的测试工程

【免费】这个是一个i2c读写eeprom的实验HAL库方式实现stm32f103zet6-eeprom.rar资源-CSDN文库

附录

思考过程中使用AI作为辅助:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 3
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
你可以使用STM32HAL库实现I2C读写EEPROM。首先,确保已经正确配置了I2C外设和相关引脚。然后,按照以下步骤进行操作: 1. 初始化I2C外设:使用`HAL_I2C_Init()`函数初始化I2C外设。 2. 配置EEPROM地址:在发送I2C读写请求之前,需要设置EEPROM的地址。这可以通过向I2C外设发送一个写入EEPROM地址的I2C Start信号,然后发送EEPROM地址字节来实现。 3. 发送数据:如果要向EEPROM写入数据,可以使用`HAL_I2C_Master_Transmit()`函数发送数据。如果要从EEPROM读取数据,可以使用`HAL_I2C_Master_Receive()`函数接收数据。 下面是一个示例代码,演示如何使用HAL库进行I2C读写EEPROM: ```c #include "stm32xxxx.h" // 根据具体的芯片型号选择头文件 #define EEPROM_ADDRESS 0xA0 // EEPROM的I2C地址 // 初始化I2C外设 void I2C_Init(void) { // I2C外设初始化代码 // ... } // 向EEPROM写入数据 void EEPROM_Write(uint16_t address, uint8_t* data, uint16_t size) { // 发送I2C Start信号和EEPROM地址 HAL_I2C_Master_Transmit(&hi2c1, EEPROM_ADDRESS, (uint8_t*)&address, 2, HAL_MAX_DELAY); // 发送数据到EEPROM HAL_I2C_Master_Transmit(&hi2c1, EEPROM_ADDRESS, data, size, HAL_MAX_DELAY); } // 从EEPROM读取数据 void EEPROM_Read(uint16_t address, uint8_t* data, uint16_t size) { // 发送I2C Start信号和EEPROM地址 HAL_I2C_Master_Transmit(&hi2c1, EEPROM_ADDRESS, (uint8_t*)&address, 2, HAL_MAX_DELAY); // 从EEPROM接收数据 HAL_I2C_Master_Receive(&hi2c1, EEPROM_ADDRESS, data, size, HAL_MAX_DELAY); } ``` 请注意,上述代码中的`hi2c1`是I2C外设的句柄,具体根据你的芯片型号和使用的外设进行修改。此外,还需要根据EEPROM的具体规格和通信协议进行相应的配置。 希望以上信息对你有所帮助!如有其他问题,请随时提问。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

独处东汉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值