21.4.1
硬件設(shè)計(jì)
野火啟明6M5開(kāi)發(fā)板的EEPROM電路圖如圖所示:

圖22?13a EEPROM硬件連接圖
野火啟明4M2開(kāi)發(fā)板的EEPROM電路圖如圖所示:

圖22?13b EEPROM硬件連接圖
野火啟明2L1開(kāi)發(fā)板的EEPROM電路圖如圖所示:

圖22?13c EEPROM硬件連接圖
EEPROM芯片連接到MCU的引腳如下表所示。
表2:EEPROM引腳

21.4.2
軟件設(shè)計(jì)
使用瑞薩官方提供的FPS庫(kù)進(jìn)行編程,瑞薩官方提供的FPS庫(kù)具有方便、快捷、簡(jiǎn)潔的特性。
21.4.2.1
新建工程
因?yàn)楸菊鹿?jié)的EEPROM相關(guān)實(shí)驗(yàn)例程需要用到板子上的串口功能,因此我們可以直接以前面的“19_UART_Receive_Send”工程為基礎(chǔ)進(jìn)行修改。
對(duì)于e2studio開(kāi)發(fā)環(huán)境:拷貝一份我們之前的e2s工程“19_UART_Receive_Send”“22_EEPROM_Hardware”,然后將工程文件夾重命名為“16_ICU_External_IRQ”,最后再將它導(dǎo)入到我們的e2studio工作空間中。
對(duì)于Keil開(kāi)發(fā)環(huán)境:拷貝一份我們之前的Keil工程“19_UART_Receive_Send”“22_EEPROM_Hardware”,然后將工程文件夾重命名為“16_ICU_External_IRQ”,并進(jìn)入該文件夾里面雙擊Keil工程文件,打開(kāi)該工程。
21.4.2.2
FSP配置
新建工程后,我們先打開(kāi)“22_EEPROM_Hardware”項(xiàng)目的FSP配置界面進(jìn)行配置。新建工程后,
在FSP配置界面里面我們依次點(diǎn)擊“Stacks”->“NewStack”->“Connectivity”->“I2CMaster”來(lái)配置IIC模塊。如圖22_14。

圖22-14 加入IIC
按照?qǐng)D片順序依次進(jìn)行點(diǎn)擊然后點(diǎn)擊“I2CMaster”在左下角的屬性界面里進(jìn)行配置。如圖22_15。

圖22-15 配置圖
配置完成之后可以按下快捷鍵“Ctrl+S”保存,最后點(diǎn)右上角的“GenerateProjectContent”按鈕,讓軟件自動(dòng)生成配置代碼即可。
21.4.2.3
R_IIC_MASTER_Write函數(shù)
列表1:代碼清單22_1:
R_IIC_MASTER_Write結(jié)構(gòu)體
左右滑動(dòng)查看完整內(nèi)容
fsp_err_tR_IIC_MASTER_Write(i2c_master_ctrl_t*constp_api_ctrl,uint8_t? →*constp_src,uint32_tconst bytes,boolconst restart)
當(dāng)我們調(diào)用該函數(shù),在數(shù)據(jù)傳輸?shù)拈_(kāi)始時(shí)會(huì)發(fā)送從設(shè)備的地址位。之后根據(jù)p_src數(shù)組發(fā)送第一個(gè)位在數(shù)據(jù)位,傳輸?shù)倪^(guò)程中硬件會(huì)自動(dòng)發(fā)送確認(rèn)位和結(jié)束位。傳輸數(shù)據(jù)的長(zhǎng)度與bytes有關(guān),完成之后restart來(lái)決定此次通信之后是否通過(guò)發(fā)出重復(fù)的START條件來(lái)保持總線。
注
在調(diào)用這個(gè)函數(shù)之后我們需要延時(shí)一段時(shí)間或者使用回調(diào)函數(shù)判斷,之后再調(diào)用下一段IIC函數(shù),詳細(xì)的可以看下面IIC的寫(xiě)入代碼,原因是因?yàn)楫?dāng)你使用了R_IIC_MASTER_Write函數(shù)之后,IIC通信還未完成,如果你再次調(diào)用其他的IIC函數(shù)就會(huì)覆蓋掉第一次執(zhí)行的函數(shù),從而出現(xiàn)時(shí)序錯(cuò)誤。
21.4.2.4
R_IIC_MASTER_Read函數(shù)
列表2:代碼清單22_2:
R_IIC_MASTER_Read結(jié)構(gòu)體
左右滑動(dòng)查看完整內(nèi)容
fsp_err_tR_IIC_MASTER_Read(i2c_master_ctrl_t*constp_api_ctrl,uint8_t*? →constp_dest,uint32_tconst bytes,boolconst restart)
當(dāng)我們調(diào)用該函數(shù),在數(shù)據(jù)傳輸?shù)拈_(kāi)始時(shí)會(huì)發(fā)送從設(shè)備的地址位。之后根據(jù)p_src數(shù)組保存第一個(gè)獲取的數(shù)據(jù),傳輸?shù)倪^(guò)程中硬件會(huì)自動(dòng)加載應(yīng)答位和結(jié)束位。傳輸數(shù)據(jù)的長(zhǎng)度與bytes有關(guān),完成之后restart來(lái)決定此次通信之后是否通過(guò)發(fā)出重復(fù)的START條件來(lái)保持總線。
注
該函數(shù)與之前的R_IIC_MASTER_Write函數(shù)一樣在使用之后需要需要延時(shí)一段時(shí)間或者使用回調(diào)函數(shù)判斷。
21.4.2.5. 向EEPROM寫(xiě)入一個(gè)字節(jié)
初始化好I2C外設(shè)后,就可以使用I2C通訊了,更具上面兩個(gè)函數(shù)的介紹我們就可以寫(xiě)出EEPROM的寫(xiě)入以及讀取函數(shù)。我們看看如何向EEPROM寫(xiě)入一個(gè)字節(jié)的數(shù)據(jù),見(jiàn)代碼清單22_3。
代碼清單 22_3:EEPROM寫(xiě)入一個(gè)字節(jié)函數(shù)
/** * @brief 以單字節(jié)的方式到I2C EEPROM中 * @param * @arg address:寫(xiě)地址 * @arg byte:寫(xiě)的數(shù)據(jù) * @retval 無(wú) */ void I2C_EE_ByteWrite(unsigned char address, unsigned char byte) { iic_complete = false; unsigned char send_buffer[2] = {}; send_buffer[0] = address; send_buffer[1] = byte; R_IIC_MASTER_Write(&EEPROM_ctrl, &send_buffer[0], 2, false); //每當(dāng)寫(xiě)完數(shù)據(jù) false 總線拉高 while ((I2C_MASTER_EVENT_TX_COMPLETE != g_i2c_callback_event) && timeout_ms) { R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS); timeout_ms--; } timeout_ms = 500; }
這里我們只是簡(jiǎn)單調(diào)用庫(kù)函數(shù)R_IIC_MASTER_Write就可以實(shí)現(xiàn),通過(guò)封裝一次使用更為方便。
在這個(gè)通訊過(guò)程中,RA6M5實(shí)際上通過(guò)I2C向EEPROM發(fā)送了兩個(gè)數(shù)據(jù), 但為何第一個(gè)數(shù)據(jù)被解釋為EEPROM的內(nèi)存地址? 這是由EEPROM的自己定義的單字節(jié)寫(xiě)入時(shí)序,見(jiàn)圖22_16.

圖 22?16 EEPROM單字節(jié)寫(xiě)入時(shí)序(摘自《AT24C02》規(guī)格書(shū))
EEPROM的單字節(jié)時(shí)序規(guī)定,向它寫(xiě)入數(shù)據(jù)的時(shí)候,第一個(gè)字節(jié)為內(nèi)存地址,第二個(gè)字節(jié)是要寫(xiě)入的數(shù)據(jù)內(nèi)容。所以我們需要理解:命令、地址的本質(zhì)都是數(shù)據(jù),對(duì)數(shù)據(jù)的解釋不同,它就有了不同的功能。
21.4.2.6. EEPROM的頁(yè)寫(xiě)入
在以上的數(shù)據(jù)通訊中,每寫(xiě)入一個(gè)數(shù)據(jù)都需要向EEPROM發(fā)送寫(xiě)入的地址,我們希望向連續(xù)地址寫(xiě)入多個(gè)數(shù)據(jù)的時(shí)候,只要告訴EEPROM第一個(gè)內(nèi)存地址address1,后面的數(shù)據(jù)按次序?qū)懭氲絘ddress2、address3… 這樣可以節(jié)省通訊的內(nèi)容,加快速度。為應(yīng)對(duì)這種需求,EEPROM定義了一種頁(yè)寫(xiě)入時(shí)序,見(jiàn)圖22_17。

圖 22?17 EEPROM頁(yè)寫(xiě)入時(shí)序(摘自《AT24C02》規(guī)格書(shū))
根據(jù)頁(yè)寫(xiě)入時(shí)序,第一個(gè)數(shù)據(jù)被解釋為要寫(xiě)入的內(nèi)存地址address1,后續(xù)可連續(xù)發(fā)送n個(gè)數(shù)據(jù), 這些數(shù)據(jù)會(huì)依次寫(xiě)入到內(nèi)存中。其中AT24C02型號(hào)的芯片頁(yè)寫(xiě)入時(shí)序最多可以一次發(fā)送8個(gè)數(shù)據(jù)(即n = 8 ),該值也稱為頁(yè)大小,某些型號(hào)的芯片每個(gè)頁(yè)寫(xiě)入時(shí)序最多可傳輸16個(gè)數(shù)據(jù)。EEPROM的頁(yè)寫(xiě)入代碼實(shí)現(xiàn) 見(jiàn)代碼清單22_4。
代碼清單 22?4 EEPROM的頁(yè)寫(xiě)入
/**
* @brief 將緩沖區(qū)中的數(shù)據(jù)以頁(yè)寫(xiě)入的方式寫(xiě)到I2C EEPROM中
* @param
* @arg ptr_write:緩沖區(qū)指針
* @arg WriteAddr:寫(xiě)地址
* @arg len:寫(xiě)的長(zhǎng)度
* @retval 無(wú)
*/
void I2C_EE_Writepage(unsigned char* ptr_write , unsigned char WriteAddr,unsigned char len) //頁(yè)寫(xiě)入 page 0~31
{
unsigned char send_buffer[9] = {};
send_buffer[0] = WriteAddr;
for(unsigned char i = 0;i
}
21.4.2.7. 多字節(jié)寫(xiě)入
多次寫(xiě)入數(shù)據(jù)時(shí),利用EEPROM的頁(yè)寫(xiě)入方式,避免單字節(jié)讀寫(xiě)時(shí)候的等待。多個(gè)數(shù)據(jù)寫(xiě)入過(guò)程 見(jiàn)代碼清單22_5。
代碼清單 22?5 多字節(jié)寫(xiě)入
/**
* @brief 將緩沖區(qū)中的數(shù)據(jù)寫(xiě)到I2C EEPROM中
* @param
* @arg pBuffer:緩沖區(qū)指針
* @arg WriteAddr:寫(xiě)地址
* @arg NumByteToWrite:寫(xiě)的字節(jié)數(shù)
* @retval 無(wú)
*/
void I2C_EE_BufferWrite(uint8_t* pBuffer, uint8_t WriteAddr,uint16_t NumByteToWrite)
{
uint8_t NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0;
Addr = WriteAddr % EEPROM_PAGESIZE;
count = EEPROM_PAGESIZE - Addr;
NumOfPage = NumByteToWrite / EEPROM_PAGESIZE;
NumOfSingle = NumByteToWrite % EEPROM_PAGESIZE;
/* If WriteAddr is I2C_PageSize aligned */
if (Addr == 0) {
/* If NumByteToWrite < I2C_PageSize */
if (NumOfPage == 0) {
I2C_EE_Writepage(pBuffer, WriteAddr, NumOfSingle);
}
/* If NumByteToWrite > I2C_PageSize */
else {
while (NumOfPage--) {
I2C_EE_Writepage(pBuffer, WriteAddr, EEPROM_PAGESIZE);
WriteAddr += EEPROM_PAGESIZE;
pBuffer += EEPROM_PAGESIZE;
}
if (NumOfSingle!=0) {
I2C_EE_Writepage(pBuffer, WriteAddr, NumOfSingle);
}
}
}
/* If WriteAddr is not I2C_PageSize aligned */
else {
/* If NumByteToWrite < I2C_PageSize */
if (NumOfPage== 0) {
I2C_EE_Writepage(pBuffer, WriteAddr, NumOfSingle);
}
/* If NumByteToWrite > I2C_PageSize */
else {
NumByteToWrite -= count;
NumOfPage = NumByteToWrite / EEPROM_PAGESIZE;
NumOfSingle = NumByteToWrite % EEPROM_PAGESIZE;
if (count != 0) {
I2C_EE_Writepage(pBuffer, WriteAddr, count);
WriteAddr += count;
pBuffer += count;
}
while (NumOfPage--) {
I2C_EE_Writepage(pBuffer, WriteAddr, EEPROM_PAGESIZE);
WriteAddr += EEPROM_PAGESIZE;
pBuffer += EEPROM_PAGESIZE;
}
if (NumOfSingle != 0) {
I2C_EE_Writepage(pBuffer, WriteAddr, NumOfSingle);
}
}
}
}
21.4.2.8. EEPROM讀取函數(shù)
從EEPROM讀取數(shù)據(jù)是一個(gè)復(fù)合的I2C時(shí)序,它實(shí)際上包含一個(gè)寫(xiě)過(guò)程和一個(gè)讀過(guò)程, 見(jiàn)圖22_18。

圖 22?18 EEPROM數(shù)據(jù)讀取時(shí)序
讀時(shí)序的第一個(gè)通訊過(guò)程中,使用I2C發(fā)送設(shè)備地址尋址(寫(xiě)方向),接著發(fā)送要讀取的“內(nèi)存地址”;第二個(gè)通訊過(guò)程中, 再次使用I2C發(fā)送設(shè)備地址尋址,但這個(gè)時(shí)候的數(shù)據(jù)方向是讀方向;在這個(gè)過(guò)程之后,EEPROM會(huì)向主機(jī)返回從“內(nèi)存地址”開(kāi)始的數(shù)據(jù), 一個(gè)字節(jié)一個(gè)字節(jié)地傳輸,只要主機(jī)的響應(yīng)為“應(yīng)答信號(hào)”,它就會(huì)一直傳輸下去,主機(jī)想結(jié)束傳輸時(shí),就發(fā)送“非應(yīng)答信號(hào)”, 并以“停止信號(hào)”結(jié)束通訊,作為從機(jī)的EEPROM也會(huì)停止傳輸。FSP庫(kù)已經(jīng)幫我們實(shí)現(xiàn)了這一個(gè)過(guò)程, 我們只是簡(jiǎn)單封裝一下就可以直接使用,實(shí)現(xiàn)代碼見(jiàn)代碼清單22_6。
代碼清單 22_6:EEPROM讀取函數(shù)
/**
* @brief 讀取I2C EEPROM數(shù)據(jù)
* @param
* @arg ptr_read:讀取緩沖區(qū)指針
* @arg address:地址
* @arg byte:讀取的字節(jié)數(shù)
* @retval 無(wú)
*/
void I2C_EE_BufferRead(unsigned char* ptr_read,unsigned char address,unsigned char byte)
{
unsigned char send_buffer[2] = {};
unsigned char read_buffer[1] = {};
send_buffer[0] = address;
R_IIC_MASTER_Write(&EEPROM_ctrl, &send_buffer[0], 1, true);
while ((I2C_MASTER_EVENT_TX_COMPLETE != g_i2c_callback_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_IIC_MASTER_Read(&EEPROM_ctrl, ptr_read, byte, false);
}
這個(gè)函數(shù)是在指定的地址讀取一個(gè)字節(jié)的數(shù)據(jù),第一個(gè)變量EEPROM的地址,最后會(huì)返回一個(gè)整型的數(shù)據(jù)。如果不想使用printf函數(shù)可以將其進(jìn)行注釋,但需要適當(dāng)增加延時(shí)時(shí)間。 這里代碼非常簡(jiǎn)單,我們只需要確定I2C的地址、數(shù)據(jù)格式、數(shù)據(jù)存儲(chǔ)指針、數(shù)據(jù)大小、超時(shí)設(shè)置,就可以把想要的數(shù)據(jù)讀回來(lái)。
21.4.2.9. EEPROM測(cè)試函數(shù)
代碼清單 22_7:EEPROM測(cè)試函數(shù)
/**
* @brief I2C(AT24C02)讀寫(xiě)測(cè)試
* @param 無(wú)
* @retval 正常返回1 ,不正常返回0
*/
uint8_t I2C_Test(void)
{
uint16_t i;
unsigned char DATA_Size = 30;
unsigned char I2c_Buf_Write[33] = {};
unsigned char I2c_Buf_Read[33] = {};
//將I2c_Buf_Write中順序遞增的數(shù)據(jù)寫(xiě)入EERPOM中
printf("寫(xiě)入的數(shù)據(jù)\r\n");
for ( i=0; i
}
21.4.2.10. 主函數(shù)
代碼清單 22_8:主函數(shù)
void hal_entry(void)
{
I2C_EE_Init();
Debug_UART4_Init();
printf("歡迎使用野火 RA6M5 開(kāi)發(fā)板。\r\n");
printf("這是一個(gè)I2C外設(shè)(AT24C02)讀寫(xiě)測(cè)試?yán)?\r\n");
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_SECONDS);
while (1)
{
I2C_EE_Writedrase();
if (I2C_Test() ==1) {
LED_GREEN;
} else {
LED_RED;
}
while(1);
}
#if BSP_TZ_SECURE_BUILD
/* Enter non-secure code */
R_BSP_NonSecureEnter();
#endif
}
21.4.3. 下載驗(yàn)證
保證開(kāi)發(fā)板相關(guān)硬件連接正確,用Type-C線連接開(kāi)發(fā)板“USB TO UART”接口跟電腦, 在電腦端打開(kāi)串口調(diào)試助手,把編譯好的程序下載到開(kāi)發(fā)板, 此時(shí)串口調(diào)試助手即可收到開(kāi)發(fā)板發(fā)過(guò)來(lái)的數(shù)據(jù)。 在串口調(diào)試助手可看到EEPROM測(cè)試的調(diào)試信息。如下圖所示:

-
瑞薩
+關(guān)注
關(guān)注
37文章
22481瀏覽量
90845 -
EEPROM
+關(guān)注
關(guān)注
9文章
1137瀏覽量
86020 -
I2C
+關(guān)注
關(guān)注
28文章
1556瀏覽量
131211 -
開(kāi)發(fā)板
+關(guān)注
關(guān)注
26文章
6289瀏覽量
118023
原文標(biāo)題:I2C讀寫(xiě)EEPROM實(shí)驗(yàn)——瑞薩RA系列FSP庫(kù)開(kāi)發(fā)實(shí)戰(zhàn)指南(67)
文章出處:【微信號(hào):瑞薩嵌入式小百科,微信公眾號(hào):瑞薩嵌入式小百科】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
瑞薩RA系列FSP庫(kù)開(kāi)發(fā)實(shí)戰(zhàn)指南之瑞薩RA6M5的I2C特性及架構(gòu)
STM32CubeMx入門(mén)教程(7):I2C的讀寫(xiě)應(yīng)用
瑞薩e2studio(1)----瑞薩芯片之搭建FSP環(huán)境
【瑞薩RA6E2地奇星開(kāi)發(fā)板試用】開(kāi)發(fā)板介紹及環(huán)境搭建
I2C協(xié)議以及I2C讀寫(xiě)EEPROM
【瑞薩RA4系列開(kāi)發(fā)板體驗(yàn)】開(kāi)發(fā)環(huán)境搭建和新手點(diǎn)燈指南
【瑞薩RA4系列開(kāi)發(fā)板體驗(yàn)】體驗(yàn)過(guò)程
【野火啟明6M5開(kāi)發(fā)板體驗(yàn)】開(kāi)箱+認(rèn)識(shí)開(kāi)發(fā)板+資料
I2C總線實(shí)驗(yàn)(實(shí)時(shí)時(shí)鐘、EEPROM和ZLG7290的實(shí)驗(yàn)
I2C—讀寫(xiě)EEPROM
STM32F10x _硬件I2C讀寫(xiě)EEPROM(標(biāo)準(zhǔn)外設(shè)庫(kù)版本)
STM32學(xué)習(xí)之I2C協(xié)議(讀寫(xiě)EEPROM)
瑞薩RA系列FSP庫(kù)開(kāi)發(fā)實(shí)戰(zhàn)指南之I2C讀寫(xiě)EEPROM實(shí)驗(yàn)
評(píng)論