STM32 使用硬件I2C接口读写EEPROM

CPU作为老板,发钱需要自己转帐,收钱需要自己看信息,是一种悲哀。

上一篇《STM32 使用IO口模拟I2C时序》,我们讲述了“论老板如何自己发钱和收钱”。

这一篇《STM32 使用硬件I2C接口读写EEPROM》,我们来讲述“论老板如何雇佣员工帮忙发钱和收钱”。

我们先来招聘一个职位:

岗位职责:

1、自动产生I2C时序,向其他芯片发送(发钱)或者接收(收钱)数据。

任职要求:

1、CPU只需发指令便行,无须关心时序。(老板只要告诉发多少钱就行了,不需要知道怎么发)。

经过层层筛选,I2C bus interface 刚好符合这个要求,他的简历在 RM0033文档 553页,记得多读读喔。

它还能与搬砖小能手DMA配合,把钱当砖头搬,相当强大。

 

这就是业内人称:硬件I2C,它会自动产生SCL/SDA的时序,不需要通过CPU对IO口拉高拉低。

接下来,写代码了,Stm32Cube这一块,就不再多叙述,简单说一下就行了。

对EEPROM操作,速度,选择100K就够了,如果要选择更牛逼的速度,要把Speed Mode变成Fast Mode。

这里值得一提的是,为什么有个Slave Features呢?

因为Stm32的I2C也可以做从设备,让另一个MCU做主设备,对它进行操作。在这里,我们是对EEPROM操作,是做主设备,这个Slave,就不用管它。

另外,不建议Mcu间的通信用I2C,一般用RS232/RS485,简单通用。

还有,Stm32 I2C同样是支持DMA方式的,我们这里,就不用DMA了。

生成代码,看看都生成了些啥?

i2c.c/i2c.h 文件,还有在main里面调用 MX_I2C1_Init() 配置I2C

我们把它添加到上一篇的工程里,同样用@cmd命令测试它。

PS: stm32cube生成代码时,自已添加修改的代码,会被覆盖。这让人很恼火。解决方法有4个:

1. 在项目初期,规划好所有用到的外设,一次性配置好;

2. 将自己的代码添加在  /* USER CODE BEGIN */和/* USER CODE END*/之间(这让人更恼火,还让不让人自由自在地写代码了?程序员追求自由自在的心灵,叔可忍,婶不可忍!);

3. 自己调用HAL库配置(要stm32cube干嘛?总得做点事吧?);

4. 用stm32cube配置好,生成代码后,把相关的代码拷到对应的项目上(我就是这么做的。)。

对了,记得务必要把i2c.c加进编译里面,加在User里面。

对了,记得务必要把stm32_hal_i2c.c也加进编译里面,加在 Drivers里面。

对了,还要把 stm32f2xx_hal_conf.h里面的 #define HAL_I2C_MODULE_ENABLED 打开。  

对了,还要记得io口__HAL_RCC_GPIOB_CLK_ENABLE()。

 

接下来,

在main里面,#include "i2c.h"

在初始化代码里增加  MX_I2C1_Init();

  /* Initialize all configured peripherals */

  MX_GPIO_Init();

  MX_DMA_Init();

  MX_UART4_Init();

  MX_TIM1_Init();

  MX_TIM2_Init();

  /* USER CODE BEGIN 2 */

    USR_UartInit();

//    IOI2C_GpioInit();                // 上一节的IO口,要去掉啊。

    MX_I2C1_Init();                    // 看这里,看这里!

接下来,调用这两个函数,一个是写,一个是读。

HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)

HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);

上一节的工程基础上,在at24c02.c/at24c02.h 里,把 I2C 读写的接口改一下:

static uint8_t I2C_READBUF(uint8_t *pAddr, uint8_t *pData, uint16_t len)

{

    // return IOI2C_ReadBlock(AT24C02_DEVICE, pAddr, 1, pData, len);


    uint16_t addr = *pAddr;

    if(HAL_I2C_Mem_Read(&hi2c1, AT24C02_DEVICE|I2C_RD, addr, I2C_MEMADD_SIZE_8BIT, pData, len, 500) != HAL_OK)

        return IOI2C_BUSY;


    return IOI2C_OK;

}


static uint8_t I2C_WRITEBUF(uint8_t *pAddr, uint8_t *pData, uint16_t len)

{

    // return IOI2C_WriteBlock(AT24C02_DEVICE, pAddr, 1, pData, len);


    uint16_t addr = *pAddr;

    if(HAL_I2C_Mem_Write(&hi2c1, AT24C02_DEVICE|I2C_WR, addr, I2C_MEMADD_SIZE_8BIT, pData, len, 500) != HAL_OK)

        return IOI2C_BUSY;


    return IOI2C_OK;

}

编译、烧录、运行、测试:

写字节:

@cmd 0x1 2 0 0x13

@cmd 0x1 2 1 0x14

@cmd 0x1 2 2 0x34

读字节:

@cmd 0x1 0 0

@cmd 0x1 0 1

@cmd 0x1 0 2

3. 写一串,就往0x3存储单元写14个字节吧。

@cmd 0x1 3 0x3 14

 

4、读一串,就从0x0读18个字节吧。

@cmd 0x1 1 0x0 18

0x13、0x14、0x34,是写字节时写进去的;

0x3~0x10,是写一串的时候写进去的,刚好14个字节。

 

     整个工程及代码呢,请上百度网盘上下载:

     链接:https://pan.baidu.com/s/19usUcgZPX8cCRTKt_NPcfg

     密码:07on

     文件夹:\Stm32CubeMx\Code\I2c.rar

    

上一篇:《STM32 使用IO口模拟I2C时序

下一篇:《》

回目录:《目录

  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
1. 硬件连接 首先,我们需要将EEPROM连接到STM32微控制器的I2C总线上。在本示例中,我们将使用STM32F4Discovery开发板,并将EEPROM连接到其I2C1总线。以下是硬件连接图: ![image.png](attachment:image.png) 2. STM32CubeIDE设置 在STM32CubeIDE中,我们需要启用I2C总线并配置它。以下是步骤: - 打开STM32CubeIDE并创建一个新项目。 - 选择“STM32F4xx”系列微控制器和您的开发板型号。 - 启用I2C总线。在“Pinout & Configuration”选项卡中,选择“I2C1”并启用它。 - 配置I2C总线。在“Configuration”选项卡中,选择“I2C1”并进行必要的配置,例如时钟速度和地址模式等。 3. 代码实现 现在,我们可以开始编代码来EEPROM。以下是基本的代码框架: ```c #include "stm32f4xx_hal.h" #include "stdio.h" I2C_HandleTypeDef hi2c1; #define EEPROM_ADDR 0xA0 void EEPROM_Write(uint16_t addr, uint8_t data); uint8_t EEPROM_Read(uint16_t addr); int main(void) { HAL_Init(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_I2C1_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF4_I2C1; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); hi2c1.Instance = I2C1; hi2c1.Init.ClockSpeed = 100000; hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; hi2c1.Init.OwnAddress1 = 0; hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c1.Init.OwnAddress2 = 0; hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; if (HAL_I2C_Init(&hi2c1) != HAL_OK) { Error_Handler(); } uint8_t data = 0x55; EEPROM_Write(0x0001, data); uint8_t read_data = EEPROM_Read(0x0001); while (1) { } } void EEPROM_Write(uint16_t addr, uint8_t data) { uint8_t tx_data[3] = {addr >> 8, addr & 0xFF, data}; HAL_I2C_Master_Transmit(&hi2c1, EEPROM_ADDR, tx_data, 3, 1000); } uint8_t EEPROM_Read(uint16_t addr) { uint8_t tx_data[2] = {addr >> 8, addr & 0xFF}; uint8_t rx_data[1]; HAL_I2C_Master_Transmit(&hi2c1, EEPROM_ADDR, tx_data, 2, 1000); HAL_I2C_Master_Receive(&hi2c1, EEPROM_ADDR, rx_data, 1, 1000); return rx_data[0]; } ``` 在此示例中,我们定义了两个函数:`EEPROM_Write()`和`EEPROM_Read()`。`EEPROM_Write()`函数将一个字节EEPROM,`EEPROM_Read()`函数从EEPROM取一个字节。这两个函数使用STM32 HAL库中的I2C主机传输函数。 4. 测试 现在,我们可以将代码下载到STM32F4Discovery开发板上并测试代码。在本示例中,我们将向地址0x0001入0x55,并从该地址取数据。如果一切正常,我们应该能够入的数据(0x55)。 以上就是使用STM32CubeIDE进行I2C接口EEPROM的步骤和代码示例。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值