我們在使用單片機存儲數據時,經常用到24c02
24C02是一個2Kbit的串行EEPROM存儲芯片,可存儲256個字節數據。工作電壓范圍為1.8V到6.0V,具有低功耗CMOS技術,自定時擦寫周期,1000000次編程/擦除周期,可保存數據100年。24C02有一個16字節的頁寫緩沖器和一個寫保護功能。通過I2C總線通訊讀寫芯片數據,通訊時鐘頻率可達400KHz。
可以通過存儲IC的型號來計算芯片的存儲容量是多大,比如24C02后面的02表示的是可存儲2Kbit的數據,轉換為字節的存儲量為21024/8 = 256byte;有比如24C04后面的04表示的是可存儲4Kbit的數據,轉換為字節的儲存量為41024/8 = 512byte;以此來類推其它型號的存儲空間。
芯片的尋址:AT24C設備地址為如下,前四位固定為1010,A2~A0為由管腳電平。AT24CXX EEPROM Board模塊中默認為接地。A2-A0=000,最后一位表示讀寫操作。所以AT24Cxx的讀地址為0xA1,寫地址為0xA0。
也就是說如果是寫24C02的時候,從器件地址為10100000(0xA0);讀24C02的時候,從器件地址為10100001(0xA1)。
片內地址尋址:
芯片尋址可對內部256B中的任一個進行讀/寫操作,其尋址范圍為00~FF,共256個尋址單位。具體解釋:由于24C02只有256個字節的存儲空間,所以只需要1個字節就可以尋址完24C02的存儲空間,但是無法尋址完更大容量的存儲IC,比如24C04的存儲容量是512字節,需要9個bit的地址位才能尋址完。由上圖可以看到,24C04的設備地址內是沒有A0參數的,被a8代替了,這個a8就是24C04的第9個bit的地址位,也就是說24C04的A0引腳是不起作用的,這樣也就造成了在I2C總線上只能同時掛載4個24C04芯片。其它存儲器如24C08、24C16也可以這么類推。
24C02的WP引腳是寫保護引腳,當WP引腳接高電平的時,24C02只能進行讀取操作,不能進行寫操作。只有當WP引腳懸空或接低電平時,24C02才能進行寫操作。 IIC 主設備/從設備:簡單介紹一下主從機區分,對于新手來說老是區分不開主從機還是很有利的,通常我們為了方便把IIC設備分為主設備和從設備,基本上誰控制時鐘線(即控制SCL的電平高低變換)誰就是主設備。
IIC主設備功能:主要產生時鐘,產生起始信號和停止信號
IIC從設備功能:可編程的IIC地址檢測,停止位檢測
IIC的協議層I2C 總線在傳送數據過程中共有三種類型信號, 它們分別是:開始信號、結束信號和應答信號。
開始信號:SCL 為高電平時,SDA 由高電平向低電平跳變,開始傳送數據。結束信號:SCL 為高電平時,SDA 由低電平向高電平跳變,結束傳送數據。應答信號:接收數據的 IC 在接收到 8bit 數據后,向發送數據的 IC 發出特定的低電平脈沖,表示已收到數據。CPU 向受控單元發出一個信號后,等待受控單元發出一個應答信號,CPU 接收到應答信號后,根據實際情況作出是否繼續傳遞信號的判斷。若未收到應答信號,由判斷為受控單元出現故障。
在SCL的高電平期間,SDA是不允許變化的;而只有在時鐘線SCL的低電平期間,SDA才能夠出現變化;
應答信號每當主機向從機發送完一個字節的數據,主機總是需要等待從機給出一個應答信號,以確認從機是否成功接收到了數據,
應答信號:主機SCL拉高,讀取從機SDA的電平,為低電平表示產生應答
應答信號為低電平時,規定為有效應答位(ACK,簡稱應答位),表示接收器已經成功地接收了該字節;應答信號為高電平時,規定為非應答位(NACK),一般表示接收器接收該字節沒有成功。
Start: IIC開始信號,表示開始傳輸。DEVICE_ADDRESS:: 從設備地址,就是7位從機地址R/W: W(write)為寫,R(read)為讀ACK: 應答信號WORD_ADDRESS : 從機中對應的寄存器地址 比方說訪問 OLED中的 某個寄存器DATA: 發送的數據STOP: 停止信號。結束IIC
主機要向從機寫數據時:
主機首先產生START信號然后緊跟著發送一個從機地址,這個地址共有7位,緊接著的第8位是數據方 向位(R/W),0表示主機發送數據(寫),1表示主機接收數據(讀)主機發送地址時,總線上的每個從機都將這7位地址碼與自己的地址進行比較,若相同,則認為自己正在被主機尋址,根據R/T位將自己確定為發送器和接收器這時候主機等待從機的應答信號(A)當主機收到應答信號時,發送要訪問從機的那個地址, 繼續等待從機的應答信號當主機收到應答信號時,發送N個字節的數據,繼續等待從機的N次應答信號,主機產生停止信號,結束傳送過程。
主機要從從機讀數據時
主機首先產生START信號然后緊跟著發送一個從機地址,注意此時該地址的第8位為0,表明是向從機寫命令,這時候主機等待從機的應答信號(ACK)當主機收到應答信號時,發送要訪問的地址,繼續等待從機的應答信號,當主機收到應答信號后,主機要改變通信模式(主機將由發送變為接收,從機將由接收變為發送)所以主機重新發送一個開始start信號,然后緊跟著發送一個從機地址,注意此時該地址的第8位為1,表明將主機設 置成接收模式開始讀取數據,這時候主機等待從機的應答信號,當主機收到應答信號時,就可以接收1個字節的數據,當接收完成后,主機發送非應答信號,表示不在接收數據主機進而產生停止信號,結束傳送過程。
向AT24C02中寫數據
MCU先發送一個開始信號(START)啟動總線接著跟上首字節,發送器件寫操作地址(DEVICE ADDRESS)+寫數據(0xA0)等待應答信號(ACK)發送數據的存儲地址。24C02一共有256個字節的存儲空間,地址從0x00~0xFF,想把數據存儲>在哪個位置,此刻寫的就是哪個地址。發送要存儲的數據第一字節、第二字節、…注意在寫數據的過程中,E2PROM每個字節都會>回應一個“應答位0”,老告訴我們寫E2PROM數據成功,如果沒有回應答位,說明寫入不成功。發送結束信號(STOP)停止總線注意:在寫數據的過程中,每成功寫入一個字節,E2PROM存儲空間的地址就會自動加1,當加到0xFF后,再寫一個字節,地址就會溢出又變成0x00。
寫數據的時候需要注意,E2PROM是先寫到緩沖區,然后再“搬運到”到掉電非易失區。所以這個過程需要一定的時間,AT24C02這個過程是不超過5ms!所以,當我們在寫多個字節時,寫入一個字節之后,再寫入下一個字節之前,必須延時5ms才可以
讀隨機地址的數據
1、MCU先發送一個開始信號(START)啟動總線2、接著跟上首字節,發送器件寫操作地址(DEVICE ADDRESS)+寫數據(0xA0)注意:這里寫操作是為了要把所要讀的數據的存儲地址先寫進去,告訴E2PROM要讀取哪個地址的數據。3、發送要讀取內存的地址(WORD ADDRESS),通知E2PROM讀取要哪個地址的信息。4、重新發送開始信號(START)5、發送設備讀操作地址(DEVICE ADDRESS)對E2PROM進行讀操作 (0xA1)6、E2PROM會自動向主機發送數據,主機讀取從器件發回的數據,在讀一個字節后,MCU會回應一個應答信號(ACK)后, E2PROM會繼續傳輸下一個地址的數據,MCU不斷回應應答信號可以不斷讀取內存的數據7、如果不想讀了,告訴E2PROM不想要數據了,就發送一個“非應答位NAK(1)”。發送結束信號(STOP)停止總線
連續讀數據
E2PROM支持連續寫操作,操作和單個字節類似,先發送設備寫操作地址(DEVICE ADDRESS),然后發送內存起始地址(WORD ADDRESS),MCU會回應一個應答信號(ACK)后,E2PROM會繼續傳輸下一個地址的數據,MCU不斷回應應答信號可以不斷讀取內存的數據。E2PROM的地址指針會自動遞增,數據會依次保存在內存中。不應答發送結束信號后終止傳輸。
下面開始著重寫24c02:
24C02有兩種工作模式:(1)、字節寫入模式:結合技術文檔我認為該模式是這樣工作的:首先是可以再任意的地址(0x00~0xFF)寫入一個字節,也可以在某一地址連續的寫入N字節,而且不需要翻頁,從技術手冊得知,答題時說字節寫入模式下,頁指針根寫入數據的多少來自動增加實現翻頁功能,不用自己在程序里邊實現;(2)、頁寫入模式:頁寫入模式下,手冊上寫著,一頁可以存8字節,當存儲的數據大于8時,則會覆蓋先前保存的數據,例如,有16個數據 uchar data[16]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15},從24C02的0x00地址開始存放,當存完一頁(8個)時,第9個數據會保存在0x00,覆蓋掉開始保存的1,后邊的數據一次類推,這樣的現象叫做“翻轉”,如果想寫完一頁后將剩余的數據保存在下一頁,頁指針需要自己來設定。
這個是多字節寫入,注意程序中注釋
按頁寫于單字節寫的最大區別在于,寫入數據的時序不同,單字節寫入是寫完一個字節之后就要主機停止信號,然后進行數據的擦寫周期,看按頁寫的時許圖可以知道,每次發送完一個字節之后只要跟一個應答就可以繼續寫入下一個字節,當寫滿8字節之后才需要停止信號進行數據的擦寫。
uint8_t I2C_EEPROM_BufferWrite(uint8_t *psrc_data,uint8_t adr,uint8_t nbyte)
{
uint8_t i;
i2c_Start();
i2c_SendByte(I2C_DeviceAddress); /* 發送設備地址+寫信號 */
if(i2c_WaitAck())
{
return 0;
}
i2c_SendByte(adr); //設置起始地址
i2c_WaitAck();
/*
寫串行EEPROM不像讀操作可以連續讀取很多字節,每次寫操作只能在同一個page。
對于24xx02,page size = 8
簡單的處理方法為:按字節寫操作模式,每寫1個字節,都發送地址
為了提高連續寫的效率: 本函數采用page wirte操作。
*/
for(i=0;i<nbyte;i++)
{
// i2c_Start();
//
// i2c_SendByte(I2C_DeviceAddress); /* 發送設備地址+寫信號 */
//
// if(i2c_WaitAck())
// {
// return 0;
// }
// i2c_SendByte(adr); //設置起始地址
// i2c_WaitAck();
i2c_SendByte(psrc_data[i]); //寫數據
if(i2c_WaitAck())
{
return 0;
}
// psrc_data++; //指向待寫數據的指針加1
adr++; //對24C08的操作地址加1
// delay(5000);
if(adr%8==0) //每頁8字節 //換頁
{
if(i==nbyte-1)
{
}
else
{
i2c_Stop();
delay(5000); //停止時間需超過5ms.
i2c_Start(); //地址為8倍數重新開始
i2c_SendByte(I2C_DeviceAddress); /* 發送設備地址+寫信號 */
i2c_WaitAck();
i2c_SendByte(adr); //設置起始地址
i2c_WaitAck();
}
}
// i2c_Stop();
delay(12000);
//注意:因為這里要等待EEPROMPROM寫完,可以采用查詢或延時方式(10ms)
// DelayMs(12); //寫入延時 12ms 寫周期大于10ms即可
}
i2c_Stop();
// delay(5000);
return 1;
}
在向 EEPROM 連續寫入多個字節的數據時,如果每寫一個字節都要等待的話,整體上的寫入效率就太低了。因此 EEPROM 的廠商就想了一個辦法,把 EEPROM 分頁管理。24C01.24C02 這兩個型號是8 字節一個頁,而 24C04、24C08、24C16是16 個字節一頁。例如AT24C02,一共是 256 個字節,8 個字節一頁,那么就一共有 32 頁分配好頁之后,如果我們在同一個頁內連續寫入幾個字節后,最后再發送停止位的時席.EEPROM 檢測到這個停止位后,就會一次性把這一頁的數據寫到非易失區域,就不需要像上節課那樣寫一個字節檢測一次了,并且頁寫入的時間也不會超過 5ms。如果我們寫入的數據跨頁了,那么寫完了一頁之后,我們要發送一個停止位,然后等待并且檢測 EEPROM 的空閑模式,一直等到把上一頁數據完全寫到非易失區域后,再進行下一頁的寫入,這樣就可以在很大程度上提高數據的寫入效率