“RA MCU眾測(cè)寶典”IIC專題繼續(xù)深耕!上一期我們用【RA-Eco-RA2E1】開(kāi)發(fā)板實(shí)現(xiàn)了IIC通信的OLED顯示。這次我們把目光轉(zhuǎn)向?qū)嵱玫拇鎯?chǔ)場(chǎng)景——基于【RA-Eco-RA4M2】開(kāi)發(fā)板,用I2C協(xié)議讀取EEPROM數(shù)據(jù)。
瑞薩嵌入式小百科將帶著大家從I2C總線原理、EEPROM(AT24C02)特性,到FSP中I2C的引腳配置、參數(shù)設(shè)置,再到字節(jié)寫(xiě)、頁(yè)寫(xiě)、順序讀等核心操作的代碼實(shí)現(xiàn),一起解鎖“掉電不丟失”的存儲(chǔ)通信技能,看看I2C如何高效實(shí)現(xiàn)外設(shè)數(shù)據(jù)交互。
開(kāi)啟寶典
開(kāi)發(fā)環(huán)境
IDE:MKD 5.38a
Renesas RA Smart Configurator:v5.1.0
開(kāi)發(fā)板:RA-Eco-RA4M2
MCU:R7FA4M2AD3CFP
01
I2C工作原理
1.1
I2C串行總線概述
I2C總線是PHLIPS公司推出的一種雙線式半雙工串行總線,是具備多主機(jī)系統(tǒng)所需的總線裁決和高低速器件同步功能的高性能串行總線。用于連接微控器及外圍設(shè)備。I2C總線只有兩根雙向信號(hào)線。一根是數(shù)據(jù)線SDA,另一根是時(shí)鐘線SCL。
物理層
它只使用兩條總線線路:一條雙向串行數(shù)據(jù)線(SDA),一條串行時(shí)鐘線(SCL)。見(jiàn)圖1。
每個(gè)連接到總線的設(shè)備都有一個(gè)獨(dú)立的地址,主機(jī)可以利用這個(gè)地址進(jìn)行不同設(shè)備之間的訪問(wèn)。
多主機(jī)同時(shí)使用總線時(shí),為了防止數(shù)據(jù)沖突,會(huì)利用仲裁方式?jīng)Q定由哪個(gè)設(shè)備占用總線。
具有三種傳輸模式:標(biāo)準(zhǔn)模式的傳輸速率為100 Kbit/s,快速模式為400 Kbit/s,高速模式下可達(dá)3.4 Mbit/s,但目前大多I2C設(shè)備尚不支持高速模式。
片上的濾波器可以濾去總線數(shù)據(jù)線上的毛刺波以保證數(shù)據(jù)完整。
連接到相同總線的IC數(shù)量受到總線的最大電容400 pF限制

I2C總線通過(guò)上拉電阻接正電源。當(dāng)總線空閑時(shí),兩根線均為高電平。連到總線上的任一器件輸出的低電平,都將使總線的信號(hào)變低,即各器件的SDA及SCL都是線“與”關(guān)系。
每個(gè)接到I2C總線上的器件都有唯一的地址。主機(jī)與其它器件間的數(shù)據(jù)傳送可以是由主機(jī)發(fā)送數(shù)據(jù)到其它器件,這時(shí)主機(jī)即為發(fā)送器。由總線上接收數(shù)據(jù)的器件則為接收器。
在多主機(jī)系統(tǒng)中,可能同時(shí)有幾個(gè)主機(jī)企圖啟動(dòng)總線傳送數(shù)據(jù)。為了避免混亂,I2C總線要通過(guò)總線仲裁,以決定由哪一臺(tái)主機(jī)控制總線。
協(xié)議層
I2C的協(xié)議包括起始和停止條件、數(shù)據(jù)有效性、響應(yīng)、仲裁、時(shí)鐘同步和地址廣播等環(huán)節(jié),由于我們使用的是RA4M2集成的硬件I2C接口,并不需要用軟件去模擬SDA和SCL線的時(shí)序。

S:傳輸開(kāi)始信號(hào),此時(shí)連接到I2C總線上的所有從機(jī)都會(huì)接收到這個(gè)信號(hào)。
SLAVE_ADDRESS:從機(jī)地址,此地址可以使7位或者10位,當(dāng)主機(jī)廣播的地址與某個(gè)設(shè)備相同地址時(shí),這個(gè)設(shè)備就被選中了。
:傳輸方向選擇位,1為讀,0為寫(xiě)。
:應(yīng)答或非應(yīng)答信號(hào)。
P:停止傳輸信號(hào)。
這兩幅圖表示的是主機(jī)和從機(jī)通信時(shí)SDA線的數(shù)據(jù)包序列。
其中S表示由主機(jī)的I2C接口產(chǎn)生的傳輸起始信號(hào)(S),這時(shí)連接到I2C總線上的所有從機(jī)都會(huì)接收到這個(gè)信號(hào)。
起始信號(hào)產(chǎn)生后,所有從機(jī)就開(kāi)始等待主機(jī)緊接下來(lái)廣播的從機(jī)地址信號(hào)(SLAVE_ADDRESS),在I2C總線上,每個(gè)設(shè)備的地址都是唯一的。當(dāng)主機(jī)廣播的地址與某個(gè)設(shè)備地址相同時(shí),這個(gè)設(shè)備就被選中了,沒(méi)被選中的設(shè)備將會(huì)忽略之后的數(shù)據(jù)信號(hào)。根據(jù)I2C協(xié)議,這個(gè)從機(jī)地址可以是7位或10位。
在地址位之后,是傳輸方向的選擇位,該位為0時(shí),表示后面的數(shù)據(jù)傳輸方向是由主機(jī)傳輸至從機(jī)。該位為1時(shí),則相反。
從機(jī)接收到匹配的地址后,主機(jī)或從機(jī)會(huì)返回一個(gè)應(yīng)答(A)或非應(yīng)答信號(hào),只有接收到應(yīng)答信號(hào)后,主機(jī)才能繼續(xù)發(fā)送或接收數(shù)據(jù)。
若配置的方向傳輸位為寫(xiě)數(shù)據(jù),廣播完地址,接收到應(yīng)答信號(hào)后,主機(jī)開(kāi)始正式向從機(jī)傳輸數(shù)據(jù)(DATA),數(shù)據(jù)包的大小為8位。主機(jī)每發(fā)送完一個(gè)數(shù)據(jù),都要等待從機(jī)的應(yīng)答信號(hào)(A),重復(fù)這個(gè)過(guò)程,可以向從機(jī)傳輸N個(gè)數(shù)據(jù),這個(gè)N沒(méi)有大小限制。當(dāng)數(shù)據(jù)傳輸結(jié)束時(shí),主機(jī)向從機(jī)發(fā)送一個(gè)停止傳輸信號(hào)(P),表示不再傳輸數(shù)據(jù)。
若配置的方向傳輸位為讀數(shù)據(jù),廣播完地址,接收到應(yīng)答信號(hào)后,從機(jī)開(kāi)始向主機(jī)返回?cái)?shù)據(jù)(DATA),數(shù)據(jù)包大小也為8位。從機(jī)每發(fā)送完一個(gè)數(shù)據(jù),都會(huì)等待主機(jī)的應(yīng)答信號(hào)(A),重復(fù)這個(gè)過(guò)程,可以返回N個(gè)數(shù)據(jù),這個(gè)N也沒(méi)有大小限制。當(dāng)主機(jī)希望停止接收數(shù)據(jù)時(shí),就向從機(jī)返回一個(gè)非應(yīng)答信號(hào),則從機(jī)自動(dòng)停止數(shù)據(jù)傳輸。
02
RA4M2的I2C架構(gòu)及特性
瑞薩RA4M2有兩個(gè)I2C通道,I2C模塊符合變更提供NXPI2C總線接口功能。
2.1
I2C接口特性
RA4M2的芯片均有多達(dá)兩個(gè)的I2C總線接口。
能夠工作于多主模式或從模式,分別為主接收器、主發(fā)送器、從接收器及從發(fā)送器。
支持標(biāo)準(zhǔn)模式100 Kbit/s和快速模式400 Kbit/s,不支持高速模式。
支持7位或10位尋址。
內(nèi)置了硬件CRC發(fā)生器/校驗(yàn)器。
I2C的接收和發(fā)送都可以使用DMA操作。
支持系統(tǒng)管理總線(SMBus)2.0版。
2.2
I2C架構(gòu)
I2C的所有硬件架構(gòu)就是根據(jù)SCL線和SDA線展開(kāi)的(其中SMBALERT線用于SMBus)。
SCL線的時(shí)序即為I2C協(xié)議中的時(shí)鐘信號(hào),它由I2C 接口根據(jù)時(shí)鐘控制寄存器(CCR)控制,控制的參數(shù)主要為時(shí)鐘頻率。而SDA線的信號(hào)則通過(guò)一系列數(shù)據(jù)控制架構(gòu),在將要發(fā)送的數(shù)據(jù)的基礎(chǔ)上,根據(jù)協(xié)議添加各種起始信號(hào)、應(yīng)答信號(hào)、地址信號(hào),實(shí)現(xiàn)以I2C協(xié)議的方式發(fā)送出去。讀取數(shù)據(jù)時(shí)則從SDA線上的信號(hào)中取出接收到的數(shù)據(jù)值。發(fā)送和接收的數(shù)據(jù)都被保存在數(shù)據(jù)寄存器上。

Figure2?1 I2C架構(gòu)圖
03
I2C總線的數(shù)據(jù)傳送
3.1
數(shù)據(jù)位的有效性規(guī)定
I2C總線進(jìn)行數(shù)據(jù)傳送時(shí),時(shí)鐘信號(hào)為高電平期間,數(shù)據(jù)線上的數(shù)據(jù)必須保持穩(wěn)定,只有在時(shí)鐘線上的信號(hào)為低電平期間,數(shù)據(jù)線上的高電平或低電平狀態(tài)才允許變化。

3.2
起始和終止信號(hào)
SCL線為高電平期間,SDA線由高電平向低電平的變化表示起始信號(hào);SCL線為高電平期間,SDA線由低電平向高電平的變化表示終止信號(hào)。

起始和終止信號(hào)都是由主機(jī)發(fā)出的,在起始信號(hào)產(chǎn)生后,總線就處于被占用的狀態(tài);在終止信號(hào)產(chǎn)生后,總線就處于空閑狀態(tài)。連接到I2C總線上的器件,若具有I2C總線的硬件接口,則很容易檢測(cè)到起始和終止信號(hào)。每當(dāng)發(fā)送器件傳輸完一個(gè)字節(jié)的數(shù)據(jù)后,后面必須緊跟一個(gè)校驗(yàn)位,這個(gè)校驗(yàn)位是接收端通過(guò)控制SDA(數(shù)據(jù)線)來(lái)實(shí)現(xiàn)的,以提醒發(fā)送端數(shù)據(jù)我這邊已經(jīng)接收完成,數(shù)據(jù)傳送可以繼續(xù)進(jìn)行。
3.3
數(shù)據(jù)傳送格式
字節(jié)傳送與應(yīng)答
每一個(gè)字節(jié)必須保證是8位長(zhǎng)度。數(shù)據(jù)傳送時(shí),先傳送最高位(MSB),每一個(gè)被傳送的字節(jié)后面都必須跟隨一位應(yīng)答位(即一幀共有9位)。

由于某種原因從機(jī)不對(duì)主機(jī)尋址信號(hào)應(yīng)答時(shí)(如從機(jī)正在進(jìn)行實(shí)時(shí)性的處理工作而無(wú)法接收總線上的數(shù)據(jù)),它必須將數(shù)據(jù)線置于高電平,而由主機(jī)產(chǎn)生一個(gè)終止信號(hào)以結(jié)束總線的數(shù)據(jù)傳送。
如果從機(jī)對(duì)主機(jī)進(jìn)行了應(yīng)答,但在數(shù)據(jù)傳送一段時(shí)間后無(wú)法繼續(xù)接收更多的數(shù)據(jù)時(shí),從機(jī)可以通過(guò)對(duì)無(wú)法接收的第一個(gè)數(shù)據(jù)字節(jié)的“非應(yīng)答”通知主機(jī),主機(jī)則應(yīng)發(fā)出終止信號(hào)以結(jié)束數(shù)據(jù)的繼續(xù)傳送。
當(dāng)主機(jī)接收數(shù)據(jù)時(shí),它收到最后一個(gè)數(shù)據(jù)字節(jié)后,必須向從機(jī)發(fā)出一個(gè)結(jié)束傳送的信號(hào)。這個(gè)信號(hào)是由對(duì)從機(jī)的“非應(yīng)答”來(lái)實(shí)現(xiàn)的。然后,從機(jī)釋放SDA線,以允許主機(jī)產(chǎn)生終止信號(hào)。
總線的尋址
I2C總線協(xié)議有明確的規(guī)定:采用7位的尋址字節(jié)(尋址字節(jié)是起始信號(hào)后的第一個(gè)字節(jié))。

3.4
尋址字節(jié)的位定義
D7~D1位組成從機(jī)的地址。D0位是數(shù)據(jù)傳送方向位,為“0”時(shí)表示主機(jī)向從機(jī)寫(xiě)數(shù)據(jù),為“1”時(shí)表示主機(jī)由從機(jī)讀數(shù)據(jù)。
主機(jī)發(fā)送地址時(shí),總線上的每個(gè)從機(jī)都將這7位地址碼與自己的地址進(jìn)行比較,如果相同,則認(rèn)為自己正被主機(jī)尋址,根據(jù)R/T位將自己確定為發(fā)送器或接收器。
從機(jī)的地址由固定部分和可編程部分組成。在一個(gè)系統(tǒng)中可能希望接入多個(gè)相同的從機(jī),從機(jī)地址中可編程部分決定了可接入總線該類器件的最大數(shù)目。如一個(gè)從機(jī)的7位尋址位有4位是固定位,3位是可編程位,這時(shí)僅能尋址8個(gè)同樣的器件,即可以有8個(gè)同樣的器件接入到該I2C總線系統(tǒng)中。
數(shù)據(jù)幀格式
I2C總線上傳送的數(shù)據(jù)信號(hào)是廣義的,既包括地址信號(hào),又包括真正的數(shù)據(jù)信號(hào)。
在起始信號(hào)后必須傳送一個(gè)從機(jī)的地址(7位),第8位是數(shù)據(jù)的傳送方向位(R/T),用“0”表示主機(jī)發(fā)送數(shù)據(jù)(T),“1”表示主機(jī)接收數(shù)據(jù)(R)。每次數(shù)據(jù)傳送總是由主機(jī)產(chǎn)生的終止信號(hào)結(jié)束。但是,若主機(jī)希望繼續(xù)占用總線進(jìn)行新的數(shù)據(jù)傳送,則可以不產(chǎn)生終止信號(hào),馬上再次發(fā)出起始信號(hào)對(duì)另一從機(jī)進(jìn)行尋址。
在總線的一次數(shù)據(jù)傳送過(guò)程中,可以有以下幾種組合方式:
A)主機(jī)向從機(jī)發(fā)送數(shù)據(jù),數(shù)據(jù)傳送方向在整個(gè)過(guò)程中不變;

注:
有陰影部分表示數(shù)據(jù)由主機(jī)向從機(jī)傳送,無(wú)陰影部分則表示數(shù)據(jù)由從機(jī)向主機(jī)傳送。A表示應(yīng)答,A表示非應(yīng)答(高電平)。S表示起始信號(hào),P表示終止信號(hào)。
B)主機(jī)在第一個(gè)字節(jié)后,立即從從機(jī)讀數(shù)據(jù)。

C)在傳送過(guò)程中,當(dāng)需要改變傳送方向時(shí),起始信號(hào)和從機(jī)地址都被重復(fù)產(chǎn)生一次,但兩次讀/寫(xiě)方向位正好反相。

4
EEPROM存儲(chǔ)器原理
EEPROM是一種掉電后數(shù)據(jù)不丟失的存儲(chǔ)器,常用來(lái)存儲(chǔ)一些配置信息,以便系統(tǒng)重新上電的時(shí)候加載。EEPROM芯片最常用的通訊方式就是I2C協(xié)議,本文將要講解EEPROM的讀寫(xiě)操作。
4.1
AT24Cxx概述
AT24C01/02/04/08/16是一個(gè)1K/2K/4K/8K/16K位串行CMOS,EEPROM內(nèi)部含有128/256/512/1024/2048個(gè)8位字節(jié)CATALYST公司的先進(jìn)CMOS技術(shù)實(shí)質(zhì)上減少了器件的功耗,AT24C01/02有一個(gè)8字節(jié)頁(yè)寫(xiě)緩沖器AT24C04/08/16有一個(gè)16字節(jié)頁(yè)寫(xiě)緩沖器,該器件通過(guò)I2C總線接口進(jìn)行操作有一個(gè)專門的寫(xiě)保護(hù)功能。AT24C01/02每頁(yè)有8個(gè)字節(jié),分別為16/32頁(yè);AT24C04/08/16每頁(yè)有16個(gè)字節(jié),分別為32/64/128頁(yè)。
工作特點(diǎn)
與400KHz I2C總線兼容
1.8到6.0伏工作電壓范圍
低功耗CMOS技術(shù)
寫(xiě)保護(hù)功能當(dāng)WP為高電平時(shí)進(jìn)入寫(xiě)保護(hù)狀態(tài)
頁(yè)寫(xiě)緩沖器
自定時(shí)擦寫(xiě)周期
100萬(wàn)次編程/擦除周期
可保存數(shù)據(jù)100年
8腳DIP SOIC或TSSOP封裝
溫度范圍商業(yè)級(jí)和工業(yè)級(jí)
AT24Cxx的引腳定義如下:

Note:
For use of 5-lead SOT23,the software A2,A1, and A0 bits in the device address word must be set to zero toproperly communicate.
Table?引腳說(shuō)明

4.2
AT24Cxx總線時(shí)序
AT24Cxx的I2C總線時(shí)序如下:

其讀寫(xiě)周期的的電壓范圍如下:

寫(xiě)周期時(shí)間是指從一個(gè)寫(xiě)時(shí)序的有效停止信號(hào)到內(nèi)部編程/擦除周期結(jié)束的這一段時(shí)間。在寫(xiě)周期期間,總線接口電路禁能,SDA保持為高電平,器件不響應(yīng)外部操作。
4.3
AT24Cxx器件尋址
主器件通過(guò)發(fā)送一個(gè)起始信號(hào)啟動(dòng)發(fā)送過(guò)程,然后發(fā)送它所要尋址的從器件的地址。8位從器件地址的高4位固定為(1010)。接下來(lái)的3位(A2、A1、A0)為器件的地址位,用來(lái)定義哪個(gè)器件以及器件的哪個(gè)部分被主器件訪問(wèn),上述8個(gè)AT24C01/02,4個(gè)AT24C04,2個(gè)AT24C08,1個(gè)AT24C16可單獨(dú)被系統(tǒng)尋址。從器件8位地址的最低位,作為讀寫(xiě)控制位?!?”表示對(duì)從器件進(jìn)行讀操作,“0”表示對(duì)從器件進(jìn)行寫(xiě)操作。在主器件發(fā)送起始信號(hào)和從器件地址字節(jié)后,AT24C01/02/04/08/16監(jiān)視總線并當(dāng)其地址與發(fā)送的從地址相符時(shí)響應(yīng)一個(gè)應(yīng)答信號(hào)(通過(guò)SDA線)。AT24C01/02/04/08/16再根據(jù)讀寫(xiě)控制位(R/W)的狀態(tài)進(jìn)行讀或?qū)懖僮鳌?/p>

字節(jié)寫(xiě)
在字節(jié)寫(xiě)模式下,主器件發(fā)送起始命令和從器件地址信息(R/W)位置發(fā)給從器件,在從器件產(chǎn)生應(yīng)答信號(hào)后,主器件發(fā)送AT24Cxx的字節(jié)地址,主器件在收到從器件的另一個(gè)應(yīng)答信號(hào)后,再發(fā)送數(shù)據(jù)到被尋址的存儲(chǔ)單元。AT24Cxx再次應(yīng)答,并在主器件產(chǎn)生停止信號(hào)后開(kāi)始內(nèi)部數(shù)據(jù)的擦寫(xiě),在內(nèi)部擦寫(xiě)過(guò)程中,AT24Cxx不再應(yīng)答主器件的任何請(qǐng)求。

頁(yè)寫(xiě)
用頁(yè)寫(xiě),AT24C01/02可一次寫(xiě)入8個(gè)字節(jié)數(shù)據(jù),AT24C04/08/16可以一次寫(xiě)入16個(gè)字節(jié)的數(shù)據(jù)。__頁(yè)寫(xiě)操作的啟動(dòng)和字節(jié)寫(xiě)一樣,不同在于傳送了一字節(jié)數(shù)據(jù)后并不產(chǎn)生停止信號(hào)。__主器件被允許發(fā)送P(AT24C01:P=7;AT24C02/04/08/16:P=15)個(gè)額外的字節(jié)。每發(fā)送一個(gè)字節(jié)數(shù)據(jù)后AT24Cxx產(chǎn)生一個(gè)應(yīng)答位并將字節(jié)地址低位加1,高位保持不變。
如果在發(fā)送停止信號(hào)之前主器件發(fā)送超過(guò)P+1個(gè)字節(jié),地址計(jì)數(shù)器將自動(dòng)翻轉(zhuǎn),先前寫(xiě)入的數(shù)據(jù)被覆蓋。
接收到P+1字節(jié)數(shù)據(jù)和主器件發(fā)送的停止信號(hào)后,AT24Cxx啟動(dòng)內(nèi)部寫(xiě)周期將數(shù)據(jù)寫(xiě)到數(shù)據(jù)區(qū)。所有接收的數(shù)據(jù)在一個(gè)寫(xiě)周期內(nèi)寫(xiě)入AT24Cxx。

讀字節(jié)
讀操作允許主器件對(duì)寄存器的任意字節(jié)進(jìn)行讀操作,主器件首先通過(guò)發(fā)送起始信號(hào)、從器件地址和它想讀取的字節(jié)數(shù)據(jù)的地址執(zhí)行一個(gè)寫(xiě)操作。在AT24Cxx應(yīng)答之后,主器件重新發(fā)送起始信號(hào)和從器件地址,此時(shí)R/W位置1,AT24Cxx響應(yīng)并發(fā)送應(yīng)答信號(hào),然后輸出所要求的一個(gè)8位字節(jié)數(shù)據(jù),主器件不發(fā)送應(yīng)答信號(hào)但產(chǎn)生一個(gè)停止信號(hào)。

順序讀
在AT24Cxx發(fā)送完一個(gè)8位字節(jié)數(shù)據(jù)后,主器件產(chǎn)生一個(gè)應(yīng)答信號(hào)來(lái)響應(yīng),告知AT24Cxx主器件要求更多的數(shù)據(jù),對(duì)應(yīng)每個(gè)主機(jī)產(chǎn)生的應(yīng)答信號(hào)AT24Cxx將發(fā)送一個(gè)8位數(shù)據(jù)字節(jié)。當(dāng)主器件不發(fā)送應(yīng)答信號(hào)而發(fā)送停止位時(shí)結(jié)束此操作。
從AT24Cxx輸出的數(shù)據(jù)按順序由N到N+1輸出。讀操作時(shí)地址計(jì)數(shù)器在AT24Cxx整個(gè)地址內(nèi)增加,這樣整個(gè)寄存器區(qū)域可在一個(gè)讀操作內(nèi)全部讀出,當(dāng)讀取的字節(jié)超過(guò)E(對(duì)于24WC01,E=127;對(duì)24C02,E=255;對(duì)24C04,E=511;對(duì)24C08,E=1023;對(duì)24C16,E=2047)計(jì)數(shù)器將翻轉(zhuǎn)到零并繼續(xù)輸出數(shù)據(jù)字節(jié)。

典型應(yīng)用
ATC02的典型電路如下:

根據(jù)AT24C02的芯片資料,我們會(huì)發(fā)現(xiàn)AT24C02有三個(gè)地址A0,A1,A2。同時(shí),我們會(huì)在資料的Device Address介紹發(fā)現(xiàn)I2C器件一共有七位地址碼,還有一位是讀/寫(xiě)(R/W)操作位,而在AT24C02的前四位已經(jīng)固定為1010。R/W為1則為讀操作,為0則為寫(xiě)操作。R/W位我們要設(shè)置為0(寫(xiě)操作)。
規(guī)則為:
1010(A0)(A1)(A2)(R/W)
1
例子1:
那么對(duì)應(yīng)的A0,A1,A2都是接的VCC,所以為A0=1,A1=1,A2=1;可以知道AT24C02的從設(shè)備寫(xiě)地址為10101110(0xae),讀設(shè)備地址為10101111(0xaf)。
2
例子2:
那么對(duì)應(yīng)的A0,A1,A2都是接的GND,所以為A0=0,A1=0,A2=0;可以知道AT24C02的從設(shè)備寫(xiě)地址為10100000(0xa0),讀設(shè)備地址為10100001(0xa1)。
05
硬件設(shè)計(jì)
本文是使用I2C協(xié)議對(duì)EEPROM進(jìn)行讀寫(xiě)操作,具體的硬件連接如下。

按照我們此處的連接,A0/A1/A2均為0,所以EEPROM的7位設(shè)備地址是:1010 000b,即 0x50。
06
I2C讀寫(xiě)EEPROM
6.1
RA Smart Configurator配置I2C
打開(kāi)RA Smart Configurator,根據(jù)硬件連接,I2C使用的是I2C3,因此在配置界面里面依次打開(kāi)“Pins->Peripherals->Connectivity:SCI>SCI3”配置SCI模塊,選擇開(kāi)發(fā)板所用的I2C引腳,這里SCL和SDA分別接的是P408和P409引腳。

接下來(lái)就是添加I2C的stack。

接下來(lái)需要配置I2C的參數(shù)。

這里可以設(shè)置I2C的參數(shù),我這里設(shè)置I2C的變量名、通道以及從機(jī)地址,I2C的編號(hào)和Channel編號(hào)是一一對(duì)應(yīng)的,因此需要設(shè)置為3,回調(diào)函數(shù)依據(jù)C語(yǔ)言命名規(guī)范任意編譯一個(gè)就行。
值得注意的是,這里的從機(jī)地址是7位,代碼中自動(dòng)左移了。然后讓軟件自動(dòng)生成配置代碼即可。
6.2
基于I2C的EEPROM讀寫(xiě)實(shí)現(xiàn)
R_SCI_I2C_Open()函數(shù)為執(zhí)行IIC初始化,開(kāi)啟配置如下所示。
左右滑動(dòng)查看完整內(nèi)容
/* Initialize the I2C module */err = R_SCI_I2C_Open(&g_i2c3_ctrl, &g_i2c3_cfg);/* Handle any errors. This function should be defined by the user. */assert(FSP_SUCCESS == err);
R_SCI_I2C_Write()函數(shù)是向IIC設(shè)備中寫(xiě)入數(shù)據(jù),寫(xiě)入格式如下所示。
左右滑動(dòng)查看完整內(nèi)容
err = R_SCI_I2C_Write(&g_i2c_device_ctrl_1, &g_i2c_tx_buffer[0], I2C_BUFFER_SIZE_BYTES,false);assert(FSP_SUCCESS == err);
R_SCI_I2C_Read()函數(shù)是向IIC設(shè)備中寫(xiě)入數(shù)據(jù),寫(xiě)入格式如下所示。
左右滑動(dòng)查看完整內(nèi)容
err = R_SCI_I2C_Read(&g_i2c_device_ctrl_1, &g_i2c_rx_buffer[0], I2C_BUFFER_SIZE_BYTES,false);assert(FSP_SUCCESS == err);
sci_i2c_master_callback()回調(diào)函數(shù)用于數(shù)據(jù)是否發(fā)送完畢,可以查看是否獲取到I2C_MASTER_EVENT_TX_COMPLETE字段。
左右滑動(dòng)查看完整內(nèi)容
i2c_master_event_ti2c_event = I2C_MASTER_EVENT_ABORTED;voidsci_i2c_master_callback(i2c_master_callback_args_t*p_args){ i2c_event = I2C_MASTER_EVENT_ABORTED; if(NULL!= p_args) { /* capture callback event for validating the i2c transfer event*/ i2c_event = p_args->event; }}
主要配置I2C模式、低電平占空比、I2C尋址模式以及通信速率,最后使能I2C設(shè)備。
初始化完成后就是對(duì)AT24C02的讀寫(xiě)操作,嚴(yán)格按照相應(yīng)的時(shí)序操作就行。
6.2.1字節(jié)寫(xiě)
在字節(jié)寫(xiě)模式下,向AT24C02中寫(xiě)數(shù)據(jù)時(shí)序如下:

操作時(shí)序如下:
MCU先發(fā)送一個(gè)開(kāi)始信號(hào)(START)啟動(dòng)總線
接著跟上首字節(jié),發(fā)送器件寫(xiě)操作地址(DEVICE ADDRESS)+寫(xiě)數(shù)據(jù)(0xA0)
等待應(yīng)答信號(hào)(ACK)
發(fā)送數(shù)據(jù)的存儲(chǔ)地址。24C02一共有256個(gè)字節(jié)的存儲(chǔ)空間,地址從0x00~0xFF,想把數(shù)據(jù)存儲(chǔ)在哪個(gè)位置,此刻寫(xiě)的就是哪個(gè)地址。
發(fā)送要存儲(chǔ)的數(shù)據(jù),在寫(xiě)數(shù)據(jù)的過(guò)程中,AT24C02會(huì)回應(yīng)一個(gè)“應(yīng)答位0”,則表明寫(xiě)AT24C02數(shù)據(jù)成功,如果沒(méi)有回應(yīng)答位,說(shuō)明寫(xiě)入不成功。
發(fā)送結(jié)束信號(hào)(STOP)停止總線。
代碼很簡(jiǎn)單,跟著時(shí)序來(lái)就行。
左右滑動(dòng)查看完整內(nèi)容
/** *@brief 以單字節(jié)的方式到 I2C EEPROM 中 *@param address: 寫(xiě)地址 *@param byte: 寫(xiě)的數(shù)據(jù) *@retval None */voidBSP_I2C_EE_ByteWrite(unsignedchar address, unsignedchar byte){ unsignedchar send_buffer[2] = {}; send_buffer[0] = address; send_buffer[1] = byte; R_SCI_I2C_Write(&g_i2c3_ctrl, &send_buffer[0],2,false);//每當(dāng)寫(xiě)完數(shù)據(jù) false 總線拉高
while((I2C_MASTER_EVENT_TX_COMPLETE!= i2c_event) && timeout_ms) { R_BSP_SoftwareDelay(1U,BSP_DELAY_UNITS_MILLISECONDS); timeout_ms--; } timeout_ms =500;}
6.2.2頁(yè)寫(xiě)
用頁(yè)寫(xiě),AT24C01可一次寫(xiě)入8個(gè)字節(jié)數(shù)據(jù),AT24C02/04/08/16可以一次寫(xiě)入16個(gè)字節(jié)的數(shù)據(jù)。__頁(yè)寫(xiě)操作的啟動(dòng)和字節(jié)寫(xiě)一樣,不同在于傳送了一字節(jié)數(shù)據(jù)后并不產(chǎn)生停止信號(hào)。__每發(fā)送一個(gè)字節(jié)數(shù)據(jù)后AT24Cxx產(chǎn)生一個(gè)應(yīng)答位并將字節(jié)地址低位加1,高位保持不變。
如果在發(fā)送停止信號(hào)之前主器件發(fā)送超過(guò)P+1個(gè)字節(jié),地址計(jì)數(shù)器將自動(dòng)翻轉(zhuǎn),先前寫(xiě)入的數(shù)據(jù)被覆蓋。
接收到P+1字節(jié)數(shù)據(jù)和主器件發(fā)送的停止信號(hào)后,AT24Cxx啟動(dòng)內(nèi)部寫(xiě)周期將數(shù)據(jù)寫(xiě)到數(shù)據(jù)區(qū)。所有接收的數(shù)據(jù)在一個(gè)寫(xiě)周期內(nèi)寫(xiě)入AT24Cxx。

代碼很簡(jiǎn)單,和字節(jié)寫(xiě)不同的是,數(shù)據(jù)會(huì)一直發(fā),直到主機(jī)發(fā)送停止信號(hào)。
左右滑動(dòng)查看完整內(nèi)容
/** * [url=home.php?mod=space&uid=2666770]@Brief[/url] 將緩沖區(qū)中的數(shù)據(jù)以頁(yè)寫(xiě)入的方式寫(xiě)到 I2C EEPROM 中 * [url=home.php?mod=space&uid=3142012]@param[/url] ptr_write: 緩沖區(qū)指針 *@param WriteAddr: 寫(xiě)地址 *@param len: 寫(xiě)的長(zhǎng)度 *@retvalNone */voidBSP_I2C_EE_Writepage(unsignedchar* ptr_write , unsignedchar WriteAddr, unsignedchar len){ unsignedchar send_buffer[9] = {}; send_buffer[0] =WriteAddr;
for(unsignedchar i =0;i
6.2.3任意寫(xiě)
在實(shí)際過(guò)程中,我們經(jīng)常需要任意寫(xiě)數(shù)據(jù),這里就調(diào)用頁(yè)寫(xiě)的操作,來(lái)實(shí)現(xiàn)任意字節(jié)的寫(xiě)操作。
左右滑動(dòng)查看完整內(nèi)容
/** *@brief 將緩沖區(qū)中的數(shù)據(jù)寫(xiě)到 I2C EEPROM 中 *@param pBuffer: 緩沖區(qū)指針 *@param WriteAddr: 寫(xiě)地址 *@param NumByteToWrite: 寫(xiě)的字節(jié)數(shù) *@retvalNone */voidBSP_I2C_EE_BufferWrite(uint8_t* pBuffer, uint8_t WriteAddr, uint16_t NumByteToWrite){ uint8_tNumOfPage=0,NumOfSingle=0,Addr=0, count =0; Addr=WriteAddr%EEPROM_PAGESIZE; count =EEPROM_PAGESIZE-Addr; NumOfPage= (uint8_t)(NumByteToWrite/EEPROM_PAGESIZE); NumOfSingle=NumByteToWrite%EEPROM_PAGESIZE;
/* If WriteAddr is I2C_PageSize aligned */ if(Addr==0) { /* If NumByteToWrite < I2C_PageSize */? ? ? ? if?(NumOfPage?==?0)? ? ? ? {? ? ? ? ? ? BSP_I2C_EE_Writepage(pBuffer,?WriteAddr,?NumOfSingle);? ? ? ? }? ? ? ? /* If NumByteToWrite > I2C_PageSize */ else { while(NumOfPage--) { BSP_I2C_EE_Writepage(pBuffer,WriteAddr,EEPROM_PAGESIZE); WriteAddr+=EEPROM_PAGESIZE; pBuffer +=EEPROM_PAGESIZE; } if(NumOfSingle!=0) { BSP_I2C_EE_Writepage(pBuffer,WriteAddr,NumOfSingle); } } } /* If WriteAddr is not I2C_PageSize aligned */ else { /* If NumByteToWrite < I2C_PageSize */? ? ? ? if?(NumOfPage==?0)? ? ? ? {? ? ? ? ? ? BSP_I2C_EE_Writepage(pBuffer,?WriteAddr,?NumOfSingle);? ? ? ? }? ? ? ? /* If NumByteToWrite > I2C_PageSize */ else { NumByteToWrite-= count; NumOfPage= (uint8_t)(NumByteToWrite/EEPROM_PAGESIZE); NumOfSingle=NumByteToWrite%EEPROM_PAGESIZE; if(count !=0) { BSP_I2C_EE_Writepage(pBuffer,WriteAddr, count); WriteAddr+= count; pBuffer += count; } while(NumOfPage--) { BSP_I2C_EE_Writepage(pBuffer,WriteAddr,EEPROM_PAGESIZE); WriteAddr+=EEPROM_PAGESIZE; pBuffer +=EEPROM_PAGESIZE; } if(NumOfSingle!=0) { BSP_I2C_EE_Writepage(pBuffer,WriteAddr,NumOfSingle); } } }}
主要分為兩種情況,寫(xiě)的地址正好是一頁(yè)的開(kāi)始,另外一種是在一頁(yè)的中間。不管如何,始終遵循的原則就是最大智能寫(xiě)一頁(yè),可以從一頁(yè)的中間開(kāi)始。
6.2.4讀字節(jié)
讀操作允許主器件對(duì)寄存器的任意字節(jié)進(jìn)行讀操作,主器件首先通過(guò)發(fā)送起始信號(hào)、從器件地址和它想讀取的字節(jié)數(shù)據(jù)的地址執(zhí)行一個(gè)寫(xiě)操作。在AT24Cxx應(yīng)答之后,主器件重新發(fā)送起始信號(hào)和從器件地址,此時(shí)R/W位置1,AT24Cxx響應(yīng)并發(fā)送應(yīng)答信號(hào),然后輸出所要求的一個(gè)8位字節(jié)數(shù)據(jù),主器件不發(fā)送應(yīng)答信號(hào)但產(chǎn)生一個(gè)停止信號(hào)。

讀取字節(jié)的時(shí)序如下:
MCU先發(fā)送一個(gè)開(kāi)始信號(hào)(START)啟動(dòng)總線
接著跟上首字節(jié),發(fā)送器件寫(xiě)操作地址(DEVICE ADDRESS)+寫(xiě)數(shù)據(jù)(0xA0)
注意:這里寫(xiě)操作是為了要把所要讀的數(shù)據(jù)的存儲(chǔ)地址先寫(xiě)進(jìn)去,告訴AT24Cxx要讀取哪個(gè)地址的數(shù)據(jù)。
發(fā)送要讀取內(nèi)存的地址(WORD ADDRESS),通知AT24Cxx讀取要哪個(gè)地址的信息。
重新發(fā)送開(kāi)始信號(hào)(START)。
發(fā)送設(shè)備讀操作地址(DEVICE ADDRESS)對(duì)AT24Cxx進(jìn)行讀操作 (0xA1)。
AT24Cxx會(huì)自動(dòng)向主機(jī)發(fā)送數(shù)據(jù),主機(jī)讀取從器件發(fā)回的數(shù)據(jù),在讀一個(gè)字節(jié)后,MCU會(huì)回應(yīng)一個(gè)應(yīng)答信號(hào)(ACK)。
發(fā)送一個(gè)“非應(yīng)答位NAK(1)”。發(fā)送結(jié)束信號(hào)(STOP)停止總線。
6.2.5順序讀
在AT24Cxx發(fā)送完一個(gè)8位字節(jié)數(shù)據(jù)后,主器件產(chǎn)生一個(gè)應(yīng)答信號(hào)來(lái)響應(yīng),告知AT24Cxx主器件要求更多的數(shù)據(jù),對(duì)應(yīng)每個(gè)主機(jī)產(chǎn)生的應(yīng)答信號(hào)AT24Cxx將發(fā)送一個(gè)8位數(shù)據(jù)字節(jié)。當(dāng)主器件不發(fā)送應(yīng)答信號(hào)而發(fā)送停止位時(shí)結(jié)束此操作。
從AT24Cxx輸出的數(shù)據(jù)按順序由N到N+1輸出。讀操作時(shí)地址計(jì)數(shù)器在AT24Cxx整個(gè)地址內(nèi)增加,這樣整個(gè)寄存器區(qū)域可在一個(gè)讀操作內(nèi)全部讀出,當(dāng)讀取的字節(jié)超過(guò)E(對(duì)于24WC01,E=127;對(duì)24C02,E=255;對(duì)24C04,E=511;對(duì)24C08,E=1023;對(duì)24C16,E=2047)計(jì)數(shù)器將翻轉(zhuǎn)到零并繼續(xù)輸出數(shù)據(jù)字節(jié)。

我們常用的方式就是連續(xù)讀取,代碼很簡(jiǎn)單。
左右滑動(dòng)查看完整內(nèi)容
/** *@brief 讀取 I2C EEPROM 數(shù)據(jù) *@param ptr_read: 讀取緩沖區(qū)指針 *@param address: 地址 *@param byte: 讀取的字節(jié)數(shù) *@retvalNone */voidBSP_I2C_EE_BufferRead(unsignedchar* ptr_read,unsignedchar address,unsignedchar byte){ unsignedchar send_buffer[2] = {}; send_buffer[0] = address; R_SCI_I2C_Write(&g_i2c3_ctrl, &send_buffer[0],1,true); while((I2C_MASTER_EVENT_TX_COMPLETE!= i2c_event) && timeout_ms) { R_BSP_SoftwareDelay(400U,BSP_DELAY_UNITS_MICROSECONDS); timeout_ms--; } timeout_ms =500; R_BSP_SoftwareDelay(250U,BSP_DELAY_UNITS_MICROSECONDS); R_SCI_I2C_Read(&g_i2c3_ctrl, ptr_read, byte,false);}
最后看下hal_entry()函數(shù)吧。
左右滑動(dòng)查看完整內(nèi)容
voidhal_entry(void){ R_SCI_UART_Open (g_uart9.p_ctrl, g_uart9.p_cfg);
/* Initialize the I2C module */ R_SCI_I2C_Open(&g_i2c3_ctrl, &g_i2c3_cfg);
BSP_I2C_Test(); /*TODO:add your own code here */ while(1) { R_BSP_SoftwareDelay(500, BSP_DELAY_UNITS_MILLISECONDS); }#ifBSP_TZ_SECURE_BUILD /* Enter non-secure code */ R_BSP_NonSecureEnter();#endif}
首先對(duì)I2C初始化,然后就進(jìn)行EEPROM的讀寫(xiě)測(cè)試。
BSP_I2C_Test()函數(shù)如下:
左右滑動(dòng)查看完整內(nèi)容
/** * @brief I2C(AT24C02) 讀寫(xiě)測(cè)試 * @param None * @retval 正常返回 1 ,不正常返回 0 */uint8_tBSP_I2C_Test(void){ uint8_ti; uint8_tDATA_Size =16; uint8_tI2c_Buf_Write[32] = {}; uint8_tI2c_Buf_Read[32] = {}; //將 I2c_Buf_Write 中順序遞增的數(shù)據(jù)寫(xiě)入 EERPOM 中 printf("Write data:\r\n"); for( i=0; i
6.3
實(shí)現(xiàn)現(xiàn)象
接上AT24C02模塊,打開(kāi)串口助手,打印信息如下:

Figure6?8 實(shí)驗(yàn)現(xiàn)象
從打印信息可以看出,I2C讀寫(xiě)AT24C02成功。
從OLED顯示到EEPROM讀寫(xiě),我們摸清了雙線通信的實(shí)用技巧。下一期將要解鎖嵌入式開(kāi)發(fā)中“高速高效的通信技能”——SPI專題。如果你在實(shí)操中遇到了地址匹配、時(shí)序調(diào)試等問(wèn)題,歡迎在評(píng)論區(qū)分享交流。
-
mcu
+關(guān)注
關(guān)注
147文章
18917瀏覽量
397886 -
通信
+關(guān)注
關(guān)注
18文章
6389瀏覽量
140036 -
EEPROM
+關(guān)注
關(guān)注
9文章
1137瀏覽量
86018 -
RA
+關(guān)注
關(guān)注
0文章
32瀏覽量
25300
發(fā)布評(píng)論請(qǐng)先 登錄
瑞薩RA2L1 MCU e2 studio和FSP的使用指南
瑞薩RA MCU眾測(cè)寶典 SysTick之RA0E1定時(shí)器點(diǎn)燈
【Renesas RA6M4開(kāi)發(fā)板之I2C讀取BMP180氣壓溫度】
RA MCU眾測(cè)寶典 | ADC/DAC之【RA2L1】DAC電壓輸出及ADC電壓采集實(shí)驗(yàn)
RA MCU眾測(cè)寶典 | SPI驅(qū)動(dòng)TFT屏幕
【RA-Eco-RA4M2開(kāi)發(fā)板評(píng)測(cè)】I2C讀取EEPROM(二)
使用硬件模塊實(shí)現(xiàn)8051 MCU與I2C?串行EEPROM的接口
STM32學(xué)習(xí)之I2C協(xié)議(讀寫(xiě)EEPROM)
【Renesas RA6M4開(kāi)發(fā)板之I2C讀取mpu6050】
RA MCU眾測(cè)寶典 | IIC之【RA2E1】IIC通信的OLED顯示
RA MCU眾測(cè)寶典 | 在瑞薩CPKCOR-RA8D1B核心板上實(shí)現(xiàn)QSPI讀取外部Flash
RA MCU眾測(cè)寶典 | I2C讀取EEPROM
評(píng)論