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调试,开启外部时钟。
- 配置USART1,用于printf调试
- 配置I2C1用于跟i2c设备通讯
- 时钟界面选项卡:
- 工程选项卡:
点击右上角的的生成代码:
使用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中的编写的代码片段
实验现象
可以观察到stm32硬件方式读写8个字节都是1ms,而使用软件方式写时间是4ms,读时间是2ms。硬件方式比软件方式快1倍的时间,对一些时许要求严格的通讯可以考虑使用硬件I2C的方式来实现。
本文中使用的测试工程
【免费】这个是一个i2c读写eeprom的实验HAL库方式实现stm32f103zet6-eeprom.rar资源-CSDN文库
附录
思考过程中使用AI作为辅助:
在这里插入图片描述