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++;
}
}
