CubeMX配置STM32F103C8T6硬件IIC读写EEPROM-AT24C64(HAL库)

一、AT24Cxx芯片引脚

二、新建STM32CubeMX

1.SYS

2.RCC

3.IIC

4.USART

5.Clock Configuration

6.Project Manager

三、添加程序

新建两个文件分别为EEPROM_IIC_AT24CXX.c和EEPROM_IIC_AT24CXX.h

EEPROM_IIC_AT24CXX.c

#include "EEPROM_IIC_AT24CXX.h"
#include <string.h>

/**
 * @brief        AT24C02任意地址写一个字节数据
 * @param        addr —— 写数据的地址(0-255)--本次使用AT24C64,写数据的地址(0-8189),不同芯片大小在EEPROM_IIC_AT24CXX.h中有定义
 * @param        dat  —— 存放写入数据的地址
 * @retval       成功 —— HAL_OK
*/
uint8_t At24c02_Write_Byte(uint16_t addr, uint8_t* dat)
{
    HAL_StatusTypeDef result;
    result = HAL_I2C_Mem_Write(&hi2c1, AT24CXX_ADDR_WRITE, addr, I2C_MEMADD_SIZE, dat, 1, 0xFFFF);
    HAL_Delay(5);    // 写一个字节,延迟一段时间,不能连续写
    return result;
}
 
/**
 * @brief        AT24C02任意地址读一个字节数据
 * @param        addr —— 读数据的地址(0-255)
 * @param        read_buf —— 存放读取数据的地址
 * @retval       成功 —— HAL_OK
*/
uint8_t At24c02_Read_Byte(uint16_t addr, uint8_t* read_buf)
{
    return HAL_I2C_Mem_Read(&hi2c1, AT24CXX_ADDR_READ, addr, I2C_MEMADD_SIZE, read_buf, 1, 0xFFFF);
}
 
/**
 * @brief        AT24C02任意地址连续写多个字节数据
 * @param        addr —— 写数据的地址(0-255)
 * @param        dat  —— 存放写入数据的地址
 * @retval       成功 —— HAL_OK
*/
uint8_t At24c02_Write_Amount_Byte(uint16_t addr, uint8_t* dat, uint16_t size)
{
    uint8_t i = 0;
    uint16_t cnt = 0;        // 写入字节计数
    HAL_StatusTypeDef result;    // 返回是否写入成功
 
    /* 对于起始地址,有两种情况,分别判断 */
    if(0 == addr % 8)
    {
        /* 起始地址刚好是页开始地址 */
        /* 对于写入的字节数,有两种情况,分别判断 */
        if(size <= 8)
        {
            // 写入的字节数不大于一页,直接写入
            result = HAL_I2C_Mem_Write(&hi2c1, AT24CXX_ADDR_WRITE, addr, I2C_MEMADD_SIZE, dat, size, 0xFFFF);
            HAL_Delay(20);    // 写完八个字节(最多八个字节),延迟久一点
            return result;
        }
        else
        {
            // 写入的字节数大于一页,先将整页循环写入
            for(i = 0; i < size/8; i++)
            {
                HAL_I2C_Mem_Write(&hi2c1, AT24CXX_ADDR_WRITE, addr, I2C_MEMADD_SIZE, &dat[cnt], 8, 0xFFFF);
                // 一次写入了八个字节,延迟久一点
                HAL_Delay(20);    // 写完八个字节,延迟久一点
                addr += 8;
                cnt += 8;
            }
            // 将剩余的字节写入
            result = HAL_I2C_Mem_Write(&hi2c1, AT24CXX_ADDR_WRITE, addr, I2C_MEMADD_SIZE, &dat[cnt], size - cnt, 0xFFFF);
            HAL_Delay(20);    // 写完八个字节(最多八个字节),延迟久一点
            return result;
        }
    }
    else
    {
        /* 起始地址偏离页开始地址 */
        /* 对于写入的字节数,有两种情况,分别判断 */
        if(size <= (8 - addr%8))
        {
            /* 在该页可以写完 */
            result = HAL_I2C_Mem_Write(&hi2c1, AT24CXX_ADDR_WRITE, addr, I2C_MEMADD_SIZE, dat, size, 0xFFFF);
            HAL_Delay(20);    // 写完八个字节(最多八个字节),延迟久一点
            return result;
        }
        else
        {
            /* 该页写不完 */
            // 先将该页写完
            cnt += 8 - addr%8;
            HAL_I2C_Mem_Write(&hi2c1, AT24CXX_ADDR_WRITE, addr, I2C_MEMADD_SIZE, dat, cnt, 0xFFFF);
            HAL_Delay(20);    // 写完八个字节(最多八个字节),延迟久一点
            addr += cnt;
 
            // 循环写整页数据
            for(i = 0;i < (size - cnt)/8; i++)
            {
                HAL_I2C_Mem_Write(&hi2c1, AT24CXX_ADDR_WRITE, addr, I2C_MEMADD_SIZE, &dat[cnt], 8, 0xFFFF);
                HAL_Delay(20);    // 写完八个字节,延迟久一点
                addr += 8;
                cnt += 8;
            }
            // 将剩下的字节写入
            result = HAL_I2C_Mem_Write(&hi2c1, AT24CXX_ADDR_WRITE, addr, I2C_MEMADD_SIZE, &dat[cnt], size - cnt, 0xFFFF);
            HAL_Delay(20);    // 写完八个字节(最多八个字节),延迟久一点
            return result;
        }            
    }
}
 
/**
 * @brief        AT24C02任意地址连续读多个字节数据
 * @param        addr —— 读数据的地址(0-255)
 * @param        dat  —— 存放读出数据的地址
 * @retval       成功 —— HAL_OK
*/
uint8_t At24c02_Read_Amount_Byte(uint16_t addr, uint8_t* recv_buf, uint16_t size)
{
    return HAL_I2C_Mem_Read(&hi2c1, AT24CXX_ADDR_READ, addr, I2C_MEMADD_SIZE, recv_buf, size, 0xFFFF);
}

EEPROM_IIC_AT24CXX.h

#include "main.h"
#include "i2c.h"

#define AT24CXX_ADDR_WRITE  0xA0    // 写命令
#define AT24CXX_ADDR_READ   0xA1    // 读命令

#define AT24C1		127
#define AT24C2		255
#define AT24C4		511
#define AT24C8		1023
#define AT24C16		2047
#define AT24C32		4095
#define AT24C64		8189
#define AT24C128	16383
#define AT24C256	32767

#define BufferSize 	AT24C64//芯片型号
  
// 根据BufferSize宏的值来设置I2C_MEMADD_SIZE
#if BufferSize == AT24C64  
    #define I2C_MEMADD_SIZE I2C_MEMADD_SIZE_16BIT  
#elif BufferSize == AT24C02  
    #define I2C_MEMADD_SIZE I2C_MEMADD_SIZE_8BIT  
#endif

uint8_t At24c02_Write_Byte(uint16_t addr, uint8_t* dat);
uint8_t At24c02_Read_Byte(uint16_t addr, uint8_t* read_buf);
uint8_t At24c02_Write_Amount_Byte(uint16_t addr, uint8_t* dat, uint16_t size);
uint8_t At24c02_Read_Amount_Byte(uint16_t addr, uint8_t* recv_buf, uint16_t size);

printf重定向

参考STM32(keil5)使用printf串口输出(微库法)、usb_printf实现USB虚拟串口输出

修改main.c

添加头文件

#include <stdio.h> 
#include "EEPROM_IIC_AT24CXX.h"

main中

  printf("\r\n***************I2C EEPROM Example*******************************\r\n");
	
//  uint32_t i;
//  uint8_t j;
//  for(i = 0; i < 256; i++)
//  {
//    WriteBuffer[i] = i;    /* WriteBuffer init */
//    printf("0x%02X ", WriteBuffer[i]);
//    if(i % 16 == 15)
//    {    
//      printf("\n\r");
//    }
//  }
//	
///* write date to EEPROM */
//  for (j = 0; j < 32; j++)
//  {
//    if(At24c02_Write_Byte(8*j,WriteBuffer+8*j) == HAL_OK)//根据芯片每页字节大小修改,如AT24C02即为I2C_MEMADD_SIZE_8BIT
//    {
//      printf("EEPROM 24C64 Write Test OK \r\n");
//    }
//    else
//    {
//      printf("\r\n EEPROM 24C64 Write Test False \r\n");
//    }
//  } 
//	
//  /* read date from EEPROM */
//  At24c02_Read_Amount_Byte(0, ReadBuffer, BufferSize);   //根据芯片每页字节大小修改,如AT24C02即为I2C_MEMADD_SIZE_8BIT
//  for(i = 0; i < 256; i++)
//  {
//    printf("0x%02X ",ReadBuffer[i]);
//    if(i%16 == 15)    
//    {
//      printf("\n\r");
//    }
//  }
//    
//  if(memcmp(WriteBuffer,ReadBuffer,255) == 0 ) /* check date */
//  {
//    printf("EEPROM 24C64 Read Test OK\r\n");
//  }
//  else
//  {
//    printf("\r\n EEPROM 24C64 Read Test False\r\n");
//  }

	// 单个字节 读写测试
	uint8_t simple_write_dat = 0xa5;    // 一个字节
	uint8_t simple_recv_buf = 0;

	if(HAL_OK == At24c02_Write_Byte(10, &simple_write_dat))
		{printf("Simple data write success \r\n");} 
	else 
		{printf("Simple data write fail \r\n");}
	
	HAL_Delay(50);      
	
	if(HAL_OK == At24c02_Read_Byte(10, &simple_recv_buf))
		{printf("Simple data read success, recv_buf = 0x%02X \r\n", simple_recv_buf);} 
		else 
			{printf("Simple data read fail \r\n");}
	printf("---------单个字节读写 测试结束------------\r\n");
	
	// 浮点数 读写测试
	union float_union
		{
			float float_write_dat;        // 浮点数占4个字节
			double double_write_dat;      // 双精度浮点数占8个字节
			uint8_t buf[8];               // 定义 8个字节 的空间
		};
	union float_union send_float_data;   // 用来发送
	union float_union rev_float_data;    // 用来接收
	
	// 测试浮点数
	send_float_data.float_write_dat = 3.1415f;
	if(HAL_OK == At24c02_Write_Amount_Byte(20, send_float_data.buf, 4))
		{printf("Float data write success \r\n");}
	else 
		{printf("Float data write fail \r\n");}
	HAL_Delay(50);
			
	if(HAL_OK == At24c02_Read_Amount_Byte(20, rev_float_data.buf, 4))
		{printf("Float data read success, recv_buf = %f \r\n", rev_float_data.float_write_dat);}// 默认输出六位小数
	else 
		{printf("Float data read fail \r\n");}
	
	// 测试双精度浮点数
	send_float_data.double_write_dat = 3.1415f;
	if(HAL_OK == At24c02_Write_Amount_Byte(20, send_float_data.buf, 8))
		{printf("Double data write success \r\n");} 
	else 
		{printf("Double data write fail \r\n");}
	HAL_Delay(50);
		
	if(HAL_OK == At24c02_Read_Amount_Byte(20, rev_float_data.buf, 8))
		{printf("Double data read success, recv_buf = %.15f \r\n", rev_float_data.double_write_dat);}// 最多15位小数
	else 
		{printf("Double data read fail \r\n");}
	printf("----------浮点数读写测试 测试结束----------- \r\n");
	
	// 连续数据读写测试
	uint8_t write_dat[22] = {0};        // 22个字节
	uint8_t recv_buf[22] = {0};
	
	printf("正在往数组中填充数据... \r\n");
	for(int i = 0; i < 22; i++)
	{
		write_dat[i] = i;
		printf("%02X ", write_dat[i]);
	}
	printf("\r\n 数组中数据填充完毕... \r\n");
	
	if(HAL_OK == At24c02_Write_Amount_Byte(0, write_dat, 22))
		{printf("24c02 write success \r\n");} 
	else 
		{printf("24c02 write fail \r\n");}
	
	HAL_Delay(50);
	
	if(HAL_OK == At24c02_Read_Amount_Byte(0, recv_buf, 22))
		{
			printf("read success \r\n");
			for(int i = 0; i < 22; i++) 
			{
				printf("0x%02X ", recv_buf[i]);
			}
			printf("\r\n");
		} 
	else 
		{printf("read fail\r\n");}
	printf("----------连续数据读写 测试结束----------- \r\n");

四、例程

例程1:

CubeMX配置STM32F103C6T6硬件IIC读写EEPROM-AT24C64(HAL库)

例程2:

CubeMX配置STM32F429VET6硬件IIC读写EEPROM-AT24C64(HAL库)

  • 15
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您可以使用STM32CubeMX配置STM32F103C8T6的OLED驱动代码。首先,您需要在STM32CubeMX中创建一个新的工程,并选择STM32F103C8T6作为目标芯片。然后,您可以打开I2C接口并生成代码。接下来,您需要对生成的代码进行一处修改,将i2c.c文件中的"GPIO_InitStruct.Pull = GPIO_NOPULL;"替换为"GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;"。这样就可以成功配置STM32F103C8T6的OLED驱动代码了。\[2\]如果您需要更详细的教程,您可以参考正点原子和小蜜蜂笔记在哔哩哔哩上的相关视频教程。\[3\] #### 引用[.reference_title] - *1* *2* [基于STM32CubeMXstm32f103c6t6液晶0.96OLED显示字母数字汉字图片显示](https://blog.csdn.net/veteran412/article/details/127540347)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [基于HAL库STM32F103C8T6+0.96寸四线OLED+IIC总线协议+STM32CubeMX(附百度网盘下载链接)](https://blog.csdn.net/weixin_45498562/article/details/124591964)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值