部落客福利:100G+電子設計學習資源包!
http://mp.weixin.qq.com/mp/homepage?__biz=MzU3OTczMzk5Mg==&hid=7&sn=ad5d5d0f15df84f4a92ebf72f88d4ee8&scene=18#wechat_redirect --------------------------------------------------------------------------------------------------------------------------
24C02:256 個位元組的 EEPROM。一般情況下,EEPROM 擁有 30 萬到 100 萬次的壽命。基于 I2C 通信協定的器件。I2C 是一個通信協定,它擁有嚴密的通信時序邏輯要求,而EEPROM 是一個器件,隻是這個器件采樣了 I2C 協定的接口與單片機相連而已,二者并沒有必然的聯系,EEPROM 可以用其它接口, I2C 也可以用在其它很多器件上。
1、EEPROM寫資料流程
第一步,首先是 I2C 的起始信号,接着跟上首位元組,也就是我們前邊講的 I2C 的器件地
址,并且在讀寫方向上選擇“寫”操作。
第二步,發送資料的存儲位址。24C02一共 256 個位元組的存儲空間,位址從 0x00~0xFF,我們想把資料存儲在哪個位置,此刻寫的就是哪個位址。
第三步,發送要存儲的資料第一個位元組、第二個位元組„„注意在寫資料的過程中,
EEPROM 每個位元組都會回應一個“應答位 0”,來告訴我們寫 EEPROM 資料成功,如果沒有回應答位,說明寫入不成功。
在寫資料的過程中,每成功寫入一個位元組,EEPROM 存儲空間的位址就會自動加 1,當加到 0xFF 後,再寫一個位元組,位址會溢出又變成了 0x00。
2、EEPROM讀資料流程
第一步,首先是 I2C 的起始信号,接着跟上首位元組,也就是我們前邊講的 I2C 的器件位址,并且在讀寫方向上選擇“寫”操作。這個地方可能有同學會詫異,我們明明是讀資料為何方向也要選“寫”呢?剛才說過了,24C02 一共有 256 個位址,我們選擇寫操作,是為了把所要讀的資料的存儲位址先寫進去,告訴 EEPROM 我們要讀取哪個位址的資料。這就如同我們打電話,先撥總機号碼(EEPROM 器件位址),而後還要繼續撥分機号碼(資料位址),而撥分機号碼這個動作,主機仍然是發送方,方向依然是“寫”。
第二步,發送要讀取的資料的位址,注意是位址而非存在EEPROM 中的資料,通知EEPROM 我要哪個分機的資訊
第三步,重新發送 I2C 起始信号和器件位址,并且在方向位選擇“讀”操作。
這三步當中,每一個位元組實際上都是在“寫”,是以每一個位元組EEPROM 都會回應一個“應答位 0”。
第四步,讀取從器件發回的資料,讀一個位元組,如果還想繼續讀下一個位元組,就發送一個“應答位ACK(0)”,如果不想讀了,告訴 EEPROM,我不想要資料了,别再發資料了,那就發送一個“非應答位NAK(1)”。
和寫操作規則一樣,我們每讀一個位元組,位址會自動加 1,那如果我們想繼續往下讀,給EEPROM 一個 ACK(0)低電平,那再繼續給 SCL 完整的時序,EEPROM 會繼續往外送資料。如果我們不想讀了,要告訴 EEPROM 不要資料了,那我們直接給一個NAK(1)高電平即可。這個地方大家要從邏輯上了解透徹,不能簡單的靠死記硬背了,一定要了解明白。梳理一下幾個要點:
A、在本例中單片機是主機,24C02 是從機;
B、無論是讀是寫, SCL 始終都是由主機控制的;
C、寫的時候應答信号由從機給出,表示從機是否正确接收了資料;
#include <reg52.h>
extern void I2CStart();
extern void I2CStop();
extern unsigned char I2CReadACK();
extern unsigned char I2CReadNAK();
extern bit I2CWrite(unsigned char dat);
/* E2讀取函數,buf-資料接收指針,addr-E2中的起始位址,len-讀取長度 */
void E2Read(unsigned char *buf, unsigned char addr, unsigned char len)
{
do //用尋址操作查詢目前是否可進行讀寫操作
{
I2CStart();
if(I2CWrite(0x50 << 1)) //應答則跳出循環,非應答則進行下一次查詢
{
break;
}
I2CStop();
}
while(1);
I2CWrite(addr); //寫入起始位址
I2CStart(); //發送重複啟動信号
I2CWrite((0x50 << 1) | 0x01); //尋址器件,後續為讀操作
while (len > 1) //連續讀取len-1個位元組
{
*buf++ = I2CReadACK(); //最後位元組之前為讀取操作+應答
len--;
}
*buf = I2CReadNAK(); //最後一個位元組為讀取操作+非應答
I2CStop();
}
/* E2寫入函數,buf-源資料指針,addr-E2中的起始位址,len-寫入長度 */
void E2Write(unsigned char *buf, unsigned char addr, unsigned char len)
{
while (len > 0)
{
//等待上次寫入操作完成
do //用尋址操作查詢目前是否可進行讀寫操作
{
I2CStart();
if(I2CWrite(0x50 << 1)) //應答則跳出循環,非應答則進行下一次查詢
{
break;
}
I2CStop();
}
while(1);
//按頁寫模式連續寫入位元組
I2CWrite(addr); //寫入起始位址
while(len > 0)
{
I2CWrite(*buf++); //寫入一個位元組資料
len--; //待寫入長度計數遞減
addr++; //E2位址遞增
if ((addr & 0x07) == 0) //檢查位址是否到達頁邊界,24C02每頁8位元組,
{
//是以檢測低3位是否為零即可
break; //到達頁邊界時,跳出循環,結束本次寫操作
}
}
I2CStop();
}
}