STM32F10x_硬體I2C讀寫EEPROM(標準外設庫版本)

2021-03-02 strongerHuang

Ⅰ、寫在前面

上一篇文章是「STM32F10x_模擬I2C讀寫EEPROM」,講述使用IO口模擬I2C總線通信,對EEPROM(AT24Xxx)進行讀寫操作的過程。

上一篇文章主要內容:I2C協議、模擬I2C底層驅動、EEPROM(AT24Xxx)單字節讀寫操作。

本文主要內容:STM32硬體I2C詳細配置、EEPROM(AT24Xxx)多字節讀寫操作、ST官方I2C存在問題。

 

實例實驗效果:

1、多字節讀寫:任意地址(66), 寫入任意長度(129)、讀取並列印出來

2、單字節讀寫:任意地址(0),寫入1位元組數據、 讀取並列印出來


實驗說明:

1.多字節讀寫

實驗為什麼是從66地址寫? 為什麼是寫入129位元組?

答案:驗證對EEPROM多字節「非標準地址、長度」讀寫的準確性。

我是使用AT24C128晶片,頁大小是64位元組,我從66地址,就是驗證非標準地址(如:0、64、128等)開始讀寫; 寫入長度129位元組也是驗證非標準長度(如:64、128、256等)的讀寫。

2.單字節讀寫

我這樣實驗的目的,相信大家都能理解。驗證每一次寫入字節數據 和讀出的數據是都一致。

 

關於本文的更多詳情請往下看。

 

Ⅱ、實例工程下載

筆者針對於初學者提供的例程都是去掉了許多不必要的功能,精簡了官方的代碼,對初學者一看就明白,以簡單明了的工程供大家學習。

筆者提供的實例工程都是在板子上經過多次測試並沒有問題才上傳至360雲盤,歡迎下載測試、參照學習。

 

提供下載的軟體工程是基於Keil(MDK-ARM) V5版本、STM32F103ZE晶片,但F1其他型號也適用(適用F1其他型號: 關注微信,回復「修改型號」)。

 

STM32F10x_硬體I2C讀寫EEPROM(標準外設庫版本)實例原始碼工程:

http://yunpan.cn/c6b8d4mCTPpCj  訪問密碼 a371

 

STM32F107VC_硬體I2C讀寫EEPROM(標準外設庫版本)實例原始碼工程:

http://yunpan.cn/c6b8HGnAGG4Mf  訪問密碼 2a18

 

I2C EEPROM(AT24xx)資料:

https://yunpan.cn/c667rIDPgvwTf  訪問密碼 1099

 

STM32F1資料:

https://yunpan.cn/crBUdUGdYKam2  訪問密碼 ca90

 

Ⅲ、硬體I2C配置

硬體I2C的配置其實很簡單,RCC時鐘、GPIO、I2C配置等。筆者以F1標準外設庫(同時也建議初學者使用官方的標準外設庫)為基礎建立的工程,主要以庫的方式來講述(若您的F1晶片與提供工程不一樣,可微信回復「修改型號」)。

1.RCC時鐘源


該函數位於bsp.c文件下面;

RCC是很多初學者,甚至已經工作的朋友容易遺漏的地方,有很多朋友覺得它使用的外設不正常,很大部分是沒有配置RCC導致的。

 

重點注意:

A.外設RCC時鐘的配置要在其外設初始化的前面;

 

B.匹配對應時鐘。

比如:RCC_APB2外設不要配置在RCC_APB1時鐘裡面

【如:RCC_APB1PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);這樣能編譯通過,但這是錯誤的代碼】

 

2. I2C引腳配置


該函數位於i2c_ee.c文件下面;

1.使用硬體I2C:GPIO_Mode_AF_OD復用開漏模式

2.由於使用硬體I2C,不像使用模擬I2C使用IO操作,所以這裡引腳定義的比較「死」GPIO_Pin_6 | GPIO_Pin_7。

如果你使用I2C2或者引腳映射,這裡的引腳也要跟著改變。

 

3. I2C配置


該函數位於i2c_ee.c文件下面;

 

這個函數才是本文的重點

1.I2C模式:I2C_Mode = I2C_Mode_I2C;

硬體有多種模式:

I2C_Mode_I2C: I2C模式

I2C_Mode_SMBusDevice: SMBus設備(叢機)模式

I2C_Mode_SMBusHost: 主機模式

 

2.I2C佔空比:I2C_DutyCycle = I2C_DutyCycle_2;

這個參數在快速I2C模式下有效,也就是速度大於100KHz。

I2C_DutyCycle_2:2比1佔空比

I2C_DutyCycle_16_9:16比9佔空比

感興趣的朋友可以把時鐘配置高於100KHz(如:400KHz),用示波器測一下SCL引腳,可以看得出來佔空比不一樣。

 

3.I2C設備地址:I2C_OwnAddress1 = EEPROM_DEV_ADDR;

這個參數是第一個設備(從機)的地址,EEPROM_DEV_ADDR是我們自己宏定義的設備地址。

 

4.I2C應答:I2C_Ack = I2C_Ack_Enable;

這個參數的含義請結合上一篇文章「I2C協議」來理解。

 

5.地址位數:I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

這個參數就是設備地址位數,需要和後面函數「I2C_Send7bitAddress」一致。

 

6.I2C速度:I2C_ClockSpeed = I2C_SPEED;

這個參數很好理解,I2C_SPEED是我們宏定義的值「100000」,也就是100KHz的意思。

 

Ⅳ、硬體I2C讀寫EEPROM配置

上一篇文章簡單提及了一下EEPROM單字節的讀寫,提供了多字節讀寫實例,但沒有具體描述多字節的具體操作。

下面將詳細描述一下單字節讀寫多字節讀寫的操作。請下載「I2C EEPROM資料」和「實例工程」作為參考。

 

在對EEPROM(AT24Cxx)讀寫操作之前需要理解兩個參數(可見原始碼i2c_ee.h文件):

A.「數據字」地址長度:也就是存數據的地址有多少位。具體分類(見數據手冊)如下:

 8位: AT24C01、AT24C02

16位: AT24C04、AT24C08、AT24C16、AT24C32、AT24C64、AT24C128、AT24C256、AT24C512

 

B.頁長度:在進行連續寫的時候,最長可寫一頁,寫完這一頁之後需要指定下一頁地址才行,否則會在上一頁循環寫。具體分類(見數據手冊)如下:

  8位元組: AT24C01、AT24C02

 16位元組: AT24C04、AT24C08、AT24C16

 32位元組: AT24C32、AT24C64

 64位元組: AT24C128、AT24C256

128位元組: AT24C512

 

1. 單字節寫

時序圖:


截圖來自「AT24C128C數據手冊」,單字節寫主要分5個步驟

1.開始

2.設備地址/寫

3.數據地址

4.寫一字節數據

5.停止

 

源程序:


在操作硬體I2之前需要檢測I2C是否處於「忙」狀態。數據地址根據長度不同而寫入的不同。

 

 

2. 單字節讀(隨機)

時序圖:


截圖來自「AT24C128C數據手冊」,單字節讀(也是隨機讀)主要分7個步驟

1.開始

2.設備地址/寫

3.數據地址

4.重新開始

5.設備地址/讀

6.讀一字節數據

7.停止

 

源程序:


這裡就提醒一點,單字節讀和多字節讀的應答位,由於不連續讀,這裡產生非應答

 

3. 頁寫

時序圖:


截圖來自「AT24C128C數據手冊」,頁寫單字節寫的區別在於「連續寫」。

注意:這裡頁寫的意思是在指向地址的頁寫數據,也就是EEPROM內部「地址指針」指向的地址所在頁。每次寫之前我們都要將「地址指針」指向一個地址(見下面源程序),寫的過程中,一旦寫到最後一個字節,將會回到該頁首地址繼續寫下去,因此,寫完該頁,我們需要重新將「地址指針」指向下一頁首地址。

【晶片頁的大小根據晶片不同而不同,見本章開頭描述】

 

源程序:


寫最後一字節獨立出來是有原因的:防止HardFault_Handler。

 

 

4. 多字節寫

源程序:


「多字節寫」是基於「頁寫」的基礎上寫的,從上面頁寫的描述(寫到該頁最後一字節會回到該頁首地址)可以知道多字節寫是要考慮很多情況的,否則會破壞其他數據。

上面源程序截取了簡單的一部分:開始寫的地址剛好位於該頁首地址這種情況。在頁首地址開始寫數據情況下,要判斷需要寫的數據的大小是否有多頁。

 

上面這種情況是比較簡單的一種,還有其他情況,我不在這裡講述,希望初學的你多去理解一下,這也是參考ST官方的思路,而且有利於你們編程的思想

 

5. 多字節讀

時序圖:


截圖來自「AT24C128C數據手冊」,多字節讀需要注意應答

 

多字節讀到最後一位數據之前,必須產生應答位,而最後一位產生非應答位。請結合下面源程序理解。

 

源程序:


單字節讀比:前面第1步到第5步都是一樣的,重點請看第6步,這裡產生的應答需要注意。

 

Ⅴ、ST官方I2C讀寫問題

說到ST的I2C這個問題,網上有很多人說也存在嚴重的I2C問題,我個人倒不覺得存在太大問題(或許是我研究的還不夠)。

我從開始至今,使用ST晶片I2C也做過幾個項目(控制EEPROM、時鐘晶片、溫度傳感器、觸摸晶片),項目中也使用多個中斷,我至今還沒有發現它的問題。我只知道ST提供的標準外設庫例程有些地方不嚴謹或不規範,我也從沒使用ST官方的例程(當然,我自己寫的例程很多思路是參考ST的)。

 

我個人觀點:有問題比不可怕,可怕的是不知道如何去解決問題。由於我沒有真正的發現I2C硬體真實存在的問題,可以參考一下官方提到是資料,可以下載(第二節)我整理的STM32F1資料 「STM32F10xxCDE勘誤手冊V14(英文)2015-11」查看。

 

1.官方標準外設庫例程介紹

標準庫例程關於I2C讀寫EEPROM0的例程很多都一樣或類似(F1、F2、F4等),感興趣的可以下載查看。但是,都存在不規範的地方。

 

2.標準庫I2C例程介紹

我大概說一下這個標準庫I2C例程中讀寫相關函數吧。

位置位於STM32F10x_StdPeriph_Lib_V3.5.0\Utilities\STM32_EVAL\Common:

stm32_eval_i2c_ee.c

 

A.sEE_ReadBuffer讀函數

A1.同樣注釋,不同語句,寫地址之後的標誌處理;(見265行處)


這個地方其實是處理一下標誌位,我也測試過,使用兩種語句都可以通過的。只是提出來以下是,我個人舉得更應該使用「I2C_EVENT_MASTER_BYTE_TRANSMITTED」(在我的例程中也是使用這個)。

 

A2.讀數據之前,發送停止條件;(見316行處)


這個地方經過我反覆測試,沒有測試通過(也就是在讀之前發送停止條件)。 我個人覺得這是程序上的一個BUG.

 

B.sEE_WriteBuffer寫函數

寫頁函數暫時還沒有發現什麼問題,但在綜合的寫函數(多字節寫)中發現了一個問題(如下圖),這個地方的count永遠都不可能等於0,而這裡加了一個判斷條件。


 

 

Ⅵ、說明

EEPROM的讀寫操作按照I2C標準協議通信,請參看數據手冊,有助於提高對I2C的理解。

以上總結僅供參考,若有不對之處,敬請諒解。

 

、最後

更多精彩文章我將第一時間在微信公眾號裡面分享,對本文有什麼疑問可微信留言。

本著免費分享的原則,方便大家手機學習知識,定期在微信平臺分享技術知識。如果你覺得分享的內容對你有用,又想了解更多相關的文章,請用微信搜索「EmbeddDeveloper」 或者掃描下面二維碼、關注,將有更多精彩內容等著你。

 

贊是一種鼓勵、分享是最好的支持留言說出你想說的話!!!

相關焦點

  • STM32 之一 HAL庫、標準外設庫、LL庫
    可以說HAL庫就是用來取代之前的標準外設庫的。相比標準外設庫,STM32Cube HAL庫表現出更高的抽象整合水平,HAL API集中關注各外設的公共函數功能,這樣便於定義一套通用的用戶友好的API函數接口,從而可以輕鬆實現從一個STM32產品移植到另一個不同的STM32系列產品。HAL庫是ST未來主推的庫,從前年開始ST新出的晶片已經沒有STD庫了,比如F7系列。
  • STM32啟動文件初探之startup_stm32f10x_hd.s(Reset_Handler函數)
    該文件主要實現目的:設置初始SP設置初始PC=Reset_Handler設置向量表入口地址,並初始化向量表調用SystemInit,把系統時鐘配製成72M,SystemInit在庫文件system_stm32f10.c定義調轉到標號_main,最終來到C程序文件
  • STM32CubeMx入門教程(7) I2C的讀寫應用
    不帶讀寫方向的使用左移得到的地址為0b10100000->0xA0, 讀地址為:0xA1,寫地址為0xA0;注意:(1) 操作ATC02的時候,多字節寫入的時候沒寫入一個字節,延時最小5ms, 多字節讀的時候沒有要求
  • STM32開發筆記3: STM32F407定時器2-5的使用方法
    _t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00;  uint32_t tmpreg = 0x00, pinmask = 0x00;  /* 斷言,用於檢查輸入的參數是否正確 */  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));  assert_param(IS_GPIO_MODE
  • Linux驅動之I2C總線
    Static structi2c_board_info eeprom[] = {I2C_BOARD_INFO(「at24c02」,0x50)};說明:I2C_BOARD_INFO:用於初始化i2c_board_info的type和addrat24c02:用於匹配,跟i2c_driver的id_table的name匹配,最終會賦值給i2c_client的name。
  • STM32開發筆記74: STM32L0低功耗喚醒後的時鐘選擇
    _t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00;  uint32_t tmpreg = 0x00, pinmask = 0x00;  /* 斷言,用於檢查輸入的參數是否正確 */  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));  assert_param(IS_GPIO_MODE
  • STM32中使用HAL庫重定向printf()函數
    );   return ch;}在keil中勾選使用C庫I-CUBE-OCTMI 軟體包是一個運行在STM32 超低功耗MCU上的自我維護系統,系統 發表於 2020-12-09 STM32——流水燈 stm32f10x_conf.h
  • stm32CubeMx CAN 發送數據
    , 0x60, 0x00, 0x55, 0x55, 0x08, 0x00};uint32_t TxMailbox; uint32_t std_id = 0x601;  TxHeader.RTR = CAN_RTR_DATA;TxHeader.IDE = CAN_ID_STD;            TxHeader.StdId
  • STM32F103C8T6引腳功能分布
    如:bootloader地址:0x08000000UL   大小:10K——0x2800——STM32的內置flash應用程式地址:0x08002800UL   大小:45K——0xB400——STM32的內置flash升級信息表:0x720000UL   大小:8K——0x2000——外置flash 發表於 2020-12-06
  • 如何利用STM32CubeMX來自動生成STM32代碼
    STD 庫和 HAL 庫之分  最早意法半導體推出的適配 STM32 的固件庫被稱為「STD 庫」(標準庫),我們用的最多的「STD 庫」要屬適配在 STM32F1 上面的「STM32F10x_StdPeriph_Lib_V3.5.0
  • 關於在ARM MDK 中使用STM32F4xx 硬體浮點單元
    前言有工程師反應說Keil 下無法使用STM32F4xx 硬體浮點單元, 導致當運算浮點時運算時間過長,還有一些人反應不知如何使用晶片晶片內部的複雜數學運算,比如三角函數運算。針對這個部分本文將詳細介紹如何使用硬體浮點單元以及相關數學運算。
  • 關於ARM MDK使用STM32F4xx 硬體浮點單元的話題
    前言有工程師反應說Keil 下無法使用STM32F4">STM32F4xx 硬體浮點單元, 導致當運算浮點時運算時間過長,還有一些人反應不知如何使用晶片晶片內部的複雜數學運算,比如三角函數運算。針對這個部分本文將詳細介紹如何使用硬體浮點單元以及相關數學運算。
  • 關於stm32f1ox.h頭文件啟動代碼與編譯器裡的宏定義
    今天調試stm32f107vc發現他的外部時鐘竟是25M,和之前的stm32f103rbt6的8M晶振有所區別。在此總結一下自己的發現。stm32f107vc屬於互聯性器件,他的啟動文件應該是.cl。
  • STM32F10x互補輸出TIM_OutputState,TIM_OutputNState的意思
    開啟OCN輸出到對應的 引腳 關鍵字:STM32F10x  互補輸出  TIM 編輯:什麼魚 引用地址:http://news.eeworld.com.cn/mcu/ic462887.html