STM32
直播中

周煌煦

7年用户 1042经验值
私信 关注
[问答]

如何向基于STM32F103ZET6的AT24C02读写数据呢

如何向基于STM32F103ZET6的AT24C02读写数据呢?其代码该怎样去实现呢?

回帖(1)

龚羿峰

2021-12-14 13:39:00
  本程序编写基于秉火霸道STM32F103ZET6运行环境。
  
  1、看硬件原理图关于AT24C02的部分
  
  关于I2C协议,在以往的博客中讲得很详细,这里就不在多说。
  
  从该原理图,结合AT24C02的数据手册如下图片:
  
  很容易得到I2C的7位设备地址为1010 000,A2,A1,A0由硬件连接决定,如硬件原理图所示,A2、A1、A0都是接地,所以都为0。而
  当要向AT24C02写数据时,R/W位为0,则写地址为1010 0000,即是十六进制数:0xA0
  当要向AT24C02读数据时,R/W位为1,则读地址为1010 0001,即是十六进制数:0xA1
  2、建立STM32 cube工程
  2.1 首先配置i2c、调试串口、时钟
  
  设置I2C速度为标准模式
  通信速度为100000Hz
  地址为7bit模式,其余的默认设置即可。
  
  I2C对应的SCL和SDA分别为PB6和PB7。
  
  
  配置串口2为调试串口。
  
  配置时钟为64MHz
  2.2、生成工程
  
  3、编写AT24C02基本驱动代码
  参考AT24C02的官方数据手册,可以编写出一个读和一个写的数据接口,提供对AT24C02的基本读写能力。
  AT24C02.h
  #ifndef __AT24C02_H
  #define __AT24C02_H
  #include “main.h”
  /*
  * AT24C02 2kb = 2048bit = 2048/8 B = 256 B
  * 32 pages of 8 bytes each
  *
  * Device Address
  * 1 0 1 0 A2 A1 A0 R/W
  * 1 0 1 0 0 0 0 0 = 0XA0
  * 1 0 1 0 0 0 0 1 = 0XA1
  */
  //写地址
  #define AT24C02_WRITE_ADDRESS 0xA0
  //读地址
  #define AT24C02_READ_ADDRESS 0xA1
  //存储结构体(我们用来测试的)
  typedef struct EEPROM_ST
  {
  uint8_t init_flag ;
  uint8_t led_setting_status ;
  uint8_t buzzer_setting_status ;
  }EEPROM_DATA;
  extern EEPROM_DATA eerom_data ;
  void Default_Setting(void);
  //从AT24C02读取数据
  int AT24C02_Read(uint16_t ReadAddr, uint8_t *pBuffer, uint16_t NumToRead);
  //写数据到AT24C02
  int AT24C02_Write(uint16_t WriteAddr, uint8_t *pBuffer, uint16_t NumToWrite);
  #endif //__AT24C02_H
  AT24C02.c
  #include “AT24C02.h”
  EEPROM_DATA eerom_data;
  /*
  在AT24C02里面的指定地址开始读出指定个数的数据
  ReadAddr :开始读出的地址 对24c02为0~255
  pBuffer :数据数组首地址
  NumToRead:要读出数据的个数
  */
  int AT24C02_Read(uint16_t ReadAddr, uint8_t *pBuffer, uint16_t NumToRead)
  {
  HAL_StatusTypeDef ret = HAL_ERROR ;
  ret = HAL_I2C_Mem_Read(&hi2c1, AT24C02_READ_ADDRESS, ReadAddr, I2C_MEMADD_SIZE_8BIT, pBuffer, NumToRead, 1000);
  if(HAL_ERROR == ret)
  return -1 ;
  return HAL_OK ;
  }
  /*
  在AT24C02里面的指定地址开始写入指定个数的数据
  WriteAddr :开始写入的地址 对24c02为0~255
  pBuffer :数据数组首地址
  NumToWrite:要写入数据的个数
  */
  int AT24C02_Write(uint16_t WriteAddr, uint8_t *pBuffer, uint16_t NumToWrite)
  {
  uint16_t i = 0, temp = 0;
  HAL_StatusTypeDef ret = HAL_ERROR ;
  temp = NumToWrite / (unsigned short)0x08;
  for(i = 0; i 《 temp; i++)
  {
  ret = HAL_I2C_Mem_Write(&hi2c1, AT24C02_WRITE_ADDRESS, WriteAddr + (i * 8), I2C_MEMADD_SIZE_8BIT, pBuffer + (i * 8), 8, 1000);
  HAL_Delay(10);
  }
  temp = NumToWrite % (unsigned short)0x08;
  if(temp)
  {
  HAL_Delay(10);
  ret = HAL_I2C_Mem_Write(&hi2c1, AT24C02_WRITE_ADDRESS, WriteAddr + (i * 8), I2C_MEMADD_SIZE_8BIT, pBuffer + (i * 8), temp, 1000);
  }
  if(HAL_ERROR == ret)
  return -1 ;
  return HAL_OK ;
  }
  //默认设置参数
  void Default_Setting(void)
  {
  eerom_data.init_flag = 1 ;
  eerom_data.led_setting_status = 1 ;
  eerom_data.buzzer_setting_status = 0 ;
  }
  真实写主程序,验证AT24C02的读写功能:
  /**
  * @brief The application entry point.
  * @retval int
  */
  int main(void)
  {
  /* USER CODE BEGIN 1 */
  uint8_t Status = 0 ;
  EEPROM_DATA eeprom_data_copy ;
  /* USER CODE END 1 */
  /* MCU Configuration--------------------------------------------------------*/
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
  /* USER CODE BEGIN Init */
  /* USER CODE END Init */
  /* Configure the system clock */
  SystemClock_Config();
  /* USER CODE BEGIN SysInit */
  /* USER CODE END SysInit */
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C1_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
  printf(“这是一个EEPROM的实验。..n”);
  //设置默认参数
  Default_Setting();
  //将默认参数写入EEPROM,从0地址开始写入
  Status = AT24C02_Write(0, (uint8_t *)&eerom_data, sizeof(eerom_data));
  if(HAL_OK != Status)
  {
  printf(“数据写入EEPROM失败n”);
  return -1 ;
  }
  printf(“数据写入EEPROM成功n”);
  //从EEPROM中读取设置的默认参数,从0地址开始取出
  Status = AT24C02_Read(0, (uint8_t *)&eeprom_data_copy, sizeof(eeprom_data_copy));
  if(HAL_OK != Status)
  {
  printf(“读取EEPROM失败n”);
  return -1 ;
  }
  printf(“读取EEPROM成功n”);
  printf(“init_flag:%d led_setting_status:%d buzzer_setting_status:%dn”,eeprom_data_copy.init_flag,
  eeprom_data_copy.led_setting_status,eeprom_data_copy.buzzer_setting_status);
  /* USER CODE END 2 */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */
  /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
  }
  运行结果:
  
举报

更多回帖

发帖
×
20
完善资料,
赚取积分