小工具知识网

当前位置: 首页 > 行业知识 > STM32G030C8T6:EEPROM读写实验(I2C通信)--M24C64

行业知识

STM32G030C8T6:EEPROM读写实验(I2C通信)--M24C64

2026-11-11 00:29:52 来源:互联网转载

本专栏记录STM32开发各个功能的详细过程,方便自己后续查看,当然也供正在入门STM32单片机的兄弟们参考;

本小节的目标是,系统主频64 MHZ,采用高速外部晶振,实现PB11,PB10 引脚模拟I2C 时序,对M24C08 的EEPROM 进行读。

原理:通过模拟I2C接(PB10:CLK,PB11:DTA)与M24C08 EEPROM进行读写实验。

涉及到的知识:配置I2C通信,STM32CubeMX的使用

文章目录

  • 1 新建工程
  • 2 配置SWD下载引脚
  • 3 配置RCC
  • 4 设置系统主频
  • 5 生成工程
  • 6 增加代码实现PB10,PB11 模拟I2C 时序,从而实现EEPROM数据读写

    1 新建工程

    点击File 菜单下的New Project

    选择芯片型号,如下图所示先输入芯片型号,目前这边输入STM32G030C8,

    双击选择,就确定了芯片型号,界面会变成如下图所示

    2 配置SWD下载引脚

    如下图所示,在Pinout&Configuration 栏目的System Core 下,先点击SYS,再勾选Serial Wire 框,

    配置好SWD 下载引脚设置:

    3 配置RCC

    如下图,先点击RCC,在HSE 配置中选择Crystal/Ceramic Resonator 外部晶振设

    4 设置系统主频

    如下图, 先点击Clock Configuration 栏目,按下图的1,2,3,4 步骤完成系统64MHZ 主频设置:

    5 生成工程

    按照下图的步骤,进行项目配置,项目名称和路径设置等,生成项目的类型选择STM32CubeIDE(我这里以STM32CubeIDE为例,如果你要试用keil5,那就选择MDK-RAM,如果要使用makefile,就选择Makefile),注意项目名称和路径不要有中文名;

    最后全部设置完毕后点击create code,生成项目代码:

    生成的工程如下图所示:

    6 增加代码实现PB10,PB11 模拟I2C 时序,从而实现EEPROM数据读写

    如下图所示,在Core/Src下面增加24C64.c 文件,里面是用I/O 口模拟I2C 总线实现EEPROM读写驱动。

    24C64.h:#ifndef M24C64_H#define M24C64_H#include "main.h"#define EE_ADDR 0xA0 // EEPROM地址,地址管脚全接地,为0xA0#define EE_SCL_PIN  GPIO_PIN_10   //模拟IIC的SCL信号#define EE_SDA_PIN  GPIO_PIN_11   //模拟IIC的SDA信号#define EE_IIC_SCL(val)         HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10,val)                    //SCL 输出高或者低#define EE_IIC_SDA(val)         HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11,val)                    //SDA 输出高或者低void EE_SDA_IN(void);  // PB11配置成输入void EE_SDA_OUT(void); // PB11配置成开漏输出void EE_SCK_OUT(void); // PB10配置成开漏输出unsigned char EE_READ_SDA(void); // 读DATA引脚状态void EE_IIC_Delay(uint16_t us); // IIC延时void EE_IIC_Init(void); // IIC初始化void EE_IIC_Start(void); // 开始void EE_IIC_Stop(void); // 停止uint8_t EE_IIC_WaitAck(void); // 等待应答void EE_IIC_Ack(void); // 发送应答void EE_IIC_NAck(void); // 发送非应答void EE_IIC_SendByte(uint8_t data); // 发送一个字节uint8_t EE_IIC_ReadByte(uint8_t ack); // 读取1字节// M24C64特定函数uint8_t EE_IIC_ReadByteFromSlave(uint8_t I2C_Addr, uint16_t reg, uint8_t *buf);uint8_t EE_IIC_SendByteToSlave(uint8_t I2C_Addr, uint16_t reg, uint8_t data);#endif // M24C64_H/*********************************************************************************************************      END FILE*********************************************************************************************************/
    24C08.c#include "24C64.h"void EE_SDA_IN(void) // PB11配置成输入{__HAL_RCC_GPIOB_CLK_ENABLE(); // GPIO时钟使能GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.Pin = GPIO_PIN_11;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);}void EE_SDA_OUT(void) // PB11配置成开漏输出{__HAL_RCC_GPIOB_CLK_ENABLE(); // GPIO时钟使能GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.Pin = GPIO_PIN_11;    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;    GPIO_InitStruct.Pull = GPIO_NOPULL;    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);}void EE_SCK_OUT(void) // PB10配置成开漏输出{__HAL_RCC_GPIOB_CLK_ENABLE(); // GPIO时钟使能GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.Pin = GPIO_PIN_10;    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;    GPIO_InitStruct.Pull = GPIO_NOPULL;    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);}// 读DATA引脚状态unsigned char EE_READ_SDA(void){return HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_11);}// IIC延时void EE_IIC_Delay(uint16_t us){uint16_t j;for (j = 0; j  250){EE_IIC_Stop();return 1;}}EE_IIC_SCL(0); // 时钟输出0return 0;}// 发送应答void EE_IIC_Ack(void){EE_IIC_SCL(0);EE_SDA_OUT();EE_IIC_SDA(0);EE_IIC_Delay(1);EE_IIC_SCL(1);EE_IIC_Delay(2);EE_IIC_SCL(0);}// 发送非应答void EE_IIC_NAck(void){EE_IIC_SCL(0);EE_SDA_OUT();EE_IIC_SDA(1);EE_IIC_Delay(1);EE_IIC_SCL(1);EE_IIC_Delay(1);EE_IIC_SCL(0);}// 发送一个字节void EE_IIC_SendByte(uint8_t data){uint8_t t;EE_SDA_OUT();EE_IIC_SCL(0); // 拉低时钟开始数据传输for (t = 0; t > 7); // 发送数据EE_IIC_Delay(1);EE_IIC_SCL(1);data uint8_t i, receive = 0;EE_SDA_IN(); // SDA设置为输入模式 等待接收从机返回数据for (i = 0; i  

    然后如下图所示,24C08.c 文件,主要是把SCL 引脚改成PB10,SDA引脚改成PB11,还有EEPROM 驱动所需的基本I/O 操作函数,还有实现时序所需的等待函数。

    然后打开main.c文件,按照下图操作添加代码:

    extern void EE_IIC_Init(void);extern uint8_t EE_EE_IIC_SendByteToSlave(uint8_t I2C_Addr,uint8_t reg,uint8_t data);extern uint8_t EE_IIC_ReadByteFromSlave(uint8_t I2C_Addr,uint8_t reg,uint8_t *buf);
    unsigned char EEDATA;//存放EEPROM读取出来的数据,1个字节
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);#if 1//M24C64代码  // 测试写入和读取EEPROMEE_IIC_Init();    uint16_t test_addr = 0x0000;    uint8_t test_data = 0x55;    uint8_t read_data = 0;    // 写入测试数据    EE_IIC_SendByteToSlave(EE_ADDR, test_addr, test_data);    HAL_Delay(10); // 确保写入完成    // 读取测试数据    EE_IIC_ReadByteFromSlave(EE_ADDR, test_addr, &read_data);#endif  /* USER CODE END 2 */  /* Infinite loop */  /* USER CODE BEGIN WHILE */  while (1)  {    /* USER CODE END WHILE */      // 循环检测读取的数据      if (read_data == test_data) {          // 成功读取      while(1)      {          HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);          HAL_Delay(50);      }      } else {          // 读取失败      while(1)      {          HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);          HAL_Delay(500);      }      }    /* USER CODE BEGIN 3 */  }  /* USER CODE END 3 */}

    然后编译,调试,查看EEDATA变量的值,结果如下图所示:

    我们写进去的值时0x55,最后读出来的值是85'U',查一下ASCII码:

    0x55对应的就是85'U',证明我们的结果是对的,证明此EEPROM读写实验成功。

    此时单片机上PB9对应的小灯在以50hz的频率在闪烁。

上一篇:微信视频教程,轻松打包分享,一键搞定!

下一篇:服务器文件怎么共享到本机?