STM32驅動AT24CXX系列芯片


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










 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM