AT24Cxx系列EEPROM是由美國Mcrochip公司出品,1-512K位的支持I2C總線數據傳送協議的串行CMOS E2PROM,可用電擦除,可編程自定時寫周期(包括自動擦除時間不超過10ms,典型時間為5ms)的。串行E2PROM一般具有兩種寫入方式,一種是字節寫入方式,還有另一種頁寫入方式。允許在一個寫周期內同時對1個字節到一頁的若干字節的編程寫入,1頁的大小取決於芯片內頁寄存器的大小。其中,AT24C01具有8字節數據的頁面寫能力,AT24C02/04/08/16具有16字節數據的頁面寫能力,AT24C32/64具有32字節數據的頁面寫能力
AT24CXX的驅動是基於IIC的,在基本的IIC上加入了一些通訊協議,具體如下
1.隨機寫
主器件發送起始命令和從器件地址
信息(R/W 位置 0)給從器件,主器件在收到從器件產生應答信號后,主器件發送 1 個 8 位字節地
址寫入 AT24C01/02/04/08/16 的地址指針,對於 AT24C31/64/128/256 來說,所不同的是主器件發
送兩個 8 位地址字寫入 AT24C32/64/128/256 的地址指針。主器件在收到從器件的另一個應答信號
后,再發送數據到被尋址的存儲單元。AT24Cxx 再次應答,並在主器件產生停止信號后開始內部
數據的擦寫,在內部擦寫過程中,AT24Cxx 不再應答主器件的任何請求
2.頁寫
。在頁寫模式下,AT24C01/02/04/08/16/32/64/128/256
可一次寫入 8 /16/16/16/16/32/32/64/64 個字節數據。頁寫操作的啟動和字節寫一樣,不同的是在
於傳送了一字節數據后並不產生停止信號。主器件被允許發送 P(AT24C01:P=7;
AT24C02/04/08/16: P=15;AT24C32/64:P=31;AT24C128/256:P=63)個額外的字節。每發送
一個字節數據后 AT24Cxx 產生一個應答位, 且內部低位地址加 1,高位保持不變。如果在發送停
止信號之前主器件發送超過 P+1 個字節,地址計數器將自動翻轉,先前寫入的數據被覆蓋。 接
收到 P+1 字節數據和主器件發送的停止信號后,AT24Cxx 啟動內部寫周期將數據寫到數據區。 所
有接收的數據在一個寫周期內寫入 AT24Cxx
3.立即讀
也就是說,立即讀取讀取的是存儲器內部指針的當前數據,不需要我們設定地址
4.隨機讀
隨機讀操作允許主器件對寄存器的任
意字 節進行讀操作,主器件首先通過發送起始信號、從器件地址和它想讀取的字節數據的地
址執行一個偽寫操作。在 AT24Cxx 應答之后,主器件重新發送起始信號和從器件地址,此時
R/W 位置 1, AT24CXX 響應並發送應答信號,然后輸出所要求的一個 8 位字節數據,主器件
不發送應答信號但產生一個停止信號。
隨機讀需要設定需要讀的地址,然后有一次偽寫入過程,這個偽寫入是為了修改存儲器內部的工作指針
5.順序讀
。順序讀操作可通過立即讀或選擇性讀操作啟
動。在 AT24Cxx 發送完一個 8 位字節數據后,主器件產生一個應答信號來響應,告知 AT24CXX
主器件要求更多的數據,對應每個主機產生的應答信號 AT24Cxx 將發送一個 8 位數據字節。當
主器件不發送應答信號而發送停止位時結束此操作。 從 AT24Cxx 輸出的數據按順序由 N 到 N+1
輸出。讀操作時地址計數器在 AT24Cxx 整個地址內增加,這樣整個寄存器區域在可在一個讀操
作內全部讀出。當讀取的字節超過 E(AT24C01,E=127;AT24C02,E=255;AT24C04,E=511;
AT24C08,E=1023;AT24C16,E=2047;AT24C32,E=4095;AT24C64,E=8191;AT24C128,
E=16383;AT24C256,E=32767)計數器將翻轉到零並繼續輸出數據字節
順序讀其實就是在前兩個的基礎上,一個數據讀完了不發送noack二十發送ACK這樣就可以一直讀下去,需要自己計數因為存儲器內部指針會自動循環的
所以只要按照時序圖的標准來祝賀IIC基礎驅動,就能實現一個存儲器的驅動了
代碼如下
#ifndef __24CXX_H #define __24CXX_H #include "iic.h" #include "delay.h" #define AT24C01 127 #define AT24C02 255 #define AT24C04 511 #define AT24C08 1023 #define AT24C16 2047 #define AT24C32 4095 #define AT24C64 8191 #define AT24C128 16383 #define AT24C256 32767 #define EE_TYPE AT24C02 #define AT_ADDR 0xa0 #define AT_CHECK_ADDR 0X00 #define AT_CHECK_VALUE 0X52 u8 At24cxxReadOneByte(u16 ReadAddr); //指定地址讀取一個字節 void At24cxxWriteOneByte(u16 WriteAddr,u8 DataToWrite); //指定地址寫入一個字節 void At24cxxWriteLenByte(u16 WriteAddr,u32 DataToWrite,u8 Len);//指定地址開始寫入指定長度的數據 u32 At24cxxReadLenByte(u16 ReadAddr,u8 Len); //指定地址開始讀取指定長度數據 void At24cxxWrite(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite); //從指定地址開始寫入指定長度的數據 void At24cxxRead(u16 ReadAddr,u8 *pBuffer,u16 NumToRead); //從指定地址開始讀出指定長度的數據 u8 At24cxxCheck(void); //檢查器件 void At24cxxInit(void); //初始化IIC #endif
#include "24cxx.h" //初始化IIC接口 void At24cxxInit(void) { IIcInit(); } //在AT24CXX指定地址讀出一個數據 //ReadAddr:開始讀數的地址 //返回值 :讀到的數據 u8 At24cxxReadOneByte(u16 ReadAddr) { u8 temp=0; IIcStart(); if(EE_TYPE>AT24C16) { IIcSendByte(AT_ADDR); //發送寫命令 IIcWaitAck(); IIcSendByte(ReadAddr>>8);//發送高地址 }else IIcSendByte(AT_ADDR+((ReadAddr/256)<<1)); //發送器件地址0XA0,寫數據 IIcWaitAck(); IIcSendByte(ReadAddr%256); //發送低地址 IIcWaitAck(); IIcStart(); IIcSendByte(AT_ADDR+1); //進入接收模式 IIcWaitAck(); temp=IIcReadByte(0); IIcStop();//產生一個停止條件 return temp; } //在AT24CXX指定地址寫入一個數據 //WriteAddr :寫入數據的目的地址 //DataToWrite:要寫入的數據 void At24cxxWriteOneByte(u16 WriteAddr,u8 DataToWrite) { IIcStart(); if(EE_TYPE>AT24C16) { IIcSendByte(AT_ADDR); //發送寫命令 IIcWaitAck(); IIcSendByte(WriteAddr>>8);//發送高地址 }else IIcSendByte(AT_ADDR+((WriteAddr/256)<<1)); //發送器件地址0XA0,寫數據 IIcWaitAck(); IIcSendByte(WriteAddr%256); //發送低地址 IIcWaitAck(); IIcSendByte(DataToWrite); //發送字節 IIcWaitAck(); IIcStop();//產生一個停止條件 DelayMs(10); } //在AT24CXX里面的指定地址開始寫入長度為Len的數據 //該函數用於寫入16bit或者32bit的數據. //WriteAddr :開始寫入的地址 //DataToWrite:數據數組首地址 //Len :要寫入數據的長度2,4 void At24cxxWriteLenByte(u16 WriteAddr,u32 DataToWrite,u8 Len) { u8 t; for(t=0;t<Len;t++) { At24cxxWriteOneByte(WriteAddr+t,(DataToWrite>>(8*t))&0xff); } } //在AT24CXX里面的指定地址開始讀出長度為Len的數據 //該函數用於讀出16bit或者32bit的數據. //ReadAddr :開始讀出的地址 //返回值 :數據 //Len :要讀出數據的長度2,4 u32 At24cxxReadLenByte(u16 ReadAddr,u8 Len) { u8 t; u32 temp=0; for(t=0;t<Len;t++) { temp<<=8; temp+=At24cxxReadOneByte(ReadAddr+Len-t-1); } return temp; } //檢查AT24CXX是否正常 //這里用了24XX的最后一個地址(255)來存儲標志字. //如果用其他24C系列,這個地址要修改 //返回1:檢測失敗 //返回0:檢測成功 u8 At24cxxCheck(void) { u8 temp; temp=At24cxxReadOneByte(AT_CHECK_ADDR);//避免每次開機都寫AT24CXX if(temp==AT_CHECK_VALUE)return 0; else//排除第一次初始化的情況 { At24cxxWriteOneByte(AT_CHECK_ADDR,AT_CHECK_VALUE); temp=At24cxxReadOneByte(AT_CHECK_ADDR); if(temp==AT_CHECK_VALUE)return 0; } return 1; } //在AT24CXX里面的指定地址開始讀出指定個數的數據 //ReadAddr :開始讀出的地址 對24c02為0~255 //pBuffer :數據數組首地址 //NumToRead:要讀出數據的個數 void At24cxxRead(u16 ReadAddr,u8 *pBuffer,u16 NumToRead) { while(NumToRead) { *pBuffer++=At24cxxReadOneByte(ReadAddr++); NumToRead--; } } //在AT24CXX里面的指定地址開始寫入指定個數的數據 //WriteAddr :開始寫入的地址 對24c02為0~255 //pBuffer :數據數組首地址 //NumToWrite:要寫入數據的個數 void At24cxxWrite(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite) { while(NumToWrite--) { At24cxxWriteOneByte(WriteAddr,*pBuffer); WriteAddr++; pBuffer++; } }