STM32F10x_硬體I2C讀寫EEPROM(標準外設庫版本)
Ⅰ、寫在前面
上一篇文章是“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(標準外設庫版本)例項原始碼工程:
STM32F107VC_硬體I2C讀寫EEPROM(標準外設庫版本)例項原始碼工程:
I2C EEPROM(AT24xx)資料:
STM32F1資料:
Ⅲ、硬體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” 或者掃描下面二維碼、關注,將有更多精彩內容等著你。