STM32 使用硬件I2C接口读写EEPROM

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

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

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

我们先来招聘一个职位:

岗位职责:

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

任职要求:

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

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

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

STM32 使用硬件I2C接口读写EEPROM_第1张图片

 

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

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

STM32 使用硬件I2C接口读写EEPROM_第2张图片

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

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

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

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

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

STM32 使用硬件I2C接口读写EEPROM_第3张图片

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

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()。

STM32 使用硬件I2C接口读写EEPROM_第4张图片

 

接下来,

在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

STM32 使用硬件I2C接口读写EEPROM_第5张图片

读字节:

@cmd 0x1 0 0

@cmd 0x1 0 1

@cmd 0x1 0 2

STM32 使用硬件I2C接口读写EEPROM_第6张图片

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

@cmd 0x1 3 0x3 14

 

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

@cmd 0x1 1 0x0 18

STM32 使用硬件I2C接口读写EEPROM_第7张图片

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

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

 

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

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

     密码:07on

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

    

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

下一篇:《》

回目录:《目录》

你可能感兴趣的:(单片机)