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時序

下一篇:《》

回目錄:《目錄

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章