ChipAT24Cxx.C文件:
- /*
- ********************************************************************************
- *
- *
- *
- *
- * (c) Copyright 2012, All Rights Reserved
- *
- * 開發環境 : Keil4
- * 文件名 : ChipAT24Cxx.C
- * 程序員 : 3htech
- * 開發時間 : 20110907--20110907
- * 描述 : EEPROM芯片AT24Cxx驅動。 其他與AT24C比完全兼容的EEPROM芯片也可使用本驅動。
- * :不支持不同容量的EEPROM混用,同容量的EEPROM可以一起使用。
- * 生存條件 : 類型重定義,還需要一個毫秒級精確延時函數Delay_MS();
- *-------------------------------------------------------------------------------
- * 修 改 :
- * 日 期 :
- * 描 述 :
- *-------------------------------------------------------------------------------
- ********************************************************************************
- */
- //------------------------------ 程序開關 ------------------------------//
- // 無
- //------------------------------ 系統頭文件包含 ------------------------------//
- // 無
- //----------------------------- 自定義頭文件包含 -----------------------------//
- #include"ChipAT24Cxx.H"
- //------------------------------ 全局變量定義 ------------------------------//
- // NULL
- //------------------------------- 宏定義 ---------------------------------//
- //----------------------------------------------------------------------------//
- //宏名 :IIC_ADDR_AT24CXX
- //功能 :AT24Cxx的IIC地址。僅限本文件使用。
- //重要說明:AT24Cxx的IIC地址只有高4位有效。
- //----------------------------------------------------------------------------//
- #define IIC_ADDR_AT24CXX 0xA0
- //----------------------------------------------------------------------------//
- //宏名 :AT24CXX_MAX_SIZE
- //功能 :AT24Cxx的容量,以字節數為單位。僅限本文件使用。
- //重要說明:該宏受.H文件中“移植修改”部分的控制。這里請不要改動。
- //----------------------------------------------------------------------------//
- #if defined(AT24C01)
- #define AT24CXX_MAX_SIZE 0x0080 // AT24C01含有1K/8即128個字節
- #elif defined(AT24C02)
- #define AT24CXX_MAX_SIZE 0x0100 // AT24C02含有2K/8即256個字節
- #elif defined(AT24C04)
- #define AT24CXX_MAX_SIZE 0x0200 // AT24C04含有4K/8即512個字節
- #elif defined(AT24C08)
- #define AT24CXX_MAX_SIZE 0x0400 // AT24C08含有8K/8即1K個字節
- #elif defined(AT24C16)
- #define AT24CXX_MAX_SIZE 0x0800 // AT24C16含有16K/8即2K個字節
- #elif defined(AT24C32)
- #define AT24CXX_MAX_SIZE 0x1000 // AT24C32含有32K/8即4K個字節
- #elif defined(AT24C64)
- #define AT24CXX_MAX_SIZE 0x2000 // AT24C64含有64K/8即8K個字節
- #elif defined(AT24C128)
- #define AT24CXX_MAX_SIZE 0x4000 // AT24C128含有128K/8即16K個字節
- #elif defined(AT24C256)
- #define AT24CXX_MAX_SIZE 0x8000 // AT24C256含有256K/8即32K個字節
- #endif
- //----------------------------------------------------------------------------//
- //宏名 :AT24CXX_PAGEBUF_SIZE
- //功能 :AT24Cxx頁寫緩沖器大小。僅限本文件使用。
- //重要說明:該宏受H中移植修改”部分的控制。這里請不要改動。
- //----------------------------------------------------------------------------//
- #if defined(AT24C01)
- #define AT24CXX_PAGEBUF_SIZE 8 // AT24C01頁寫緩沖器大小為8B
- #elif defined(AT24C02)
- #define AT24CXX_PAGEBUF_SIZE 8 // AT24C02頁寫緩沖器大小為8B
- #elif defined(AT24C04)
- #define AT24CXX_PAGEBUF_SIZE 16 // AT24C04頁寫緩沖器大小為16B
- #elif defined(AT24C08)
- #define AT24CXX_PAGEBUF_SIZE 16 // AT24C08頁寫緩沖器大小為16B
- #elif defined(AT24C16)
- #define AT24CXX_PAGEBUF_SIZE 16 // AT24C16頁寫緩沖器大小為16B
- #elif defined(AT24C32)
- #define AT24CXX_PAGEBUF_SIZE 32 // AT24C32頁寫緩沖器大小為32B
- #elif defined(AT24C64)
- #define AT24CXX_PAGEBUF_SIZE 32 // AT24C64頁寫緩沖器大小為32B
- #elif defined(AT24C128)
- #define AT24CXX_PAGEBUF_SIZE 64 // AT24C128頁寫緩沖器大小為64B
- #elif defined(AT24C256)
- #define AT24CXX_PAGEBUF_SIZE 64 // AT24C256頁寫緩沖器大小為64B
- #endif
- ////////////////////////////////////////////////////////////////////////////////
- // 本文件專用函數定義 //
- ////////////////////////////////////////////////////////////////////////////////
- //----------------------------------------------------------------------------//
- // 檢測AT24Cxx內部頁寫(擦寫)是否完成函數(僅限本文件使用)
- //函數名稱:AT24Cxx_Finish_PageWrite
- //函數功能:檢測AT24Cxx內部是否頁寫(擦寫)完畢。一個頁寫的內部擦寫時間小于10ms。
- //入口參數:無。
- //出口參數:0,擦寫完畢;1,所用時間超過一頁最大擦寫時間,無應答(芯片或已損壞)。
- //重要說明:本函數只供寫操作函數AT24CxxWrStr()調用。
- // 用于在頁寫后對AT24Cxx進行檢測,以判斷其內部是否擦寫完畢。
- //----------------------------------------------------------------------------//
- static uint8 AT24Cxx_Finish_PageWrite(void)
- {
- uint8 TimeFlow; // 時間計數器
- uint8 TmpAddr;
- uint8 ErrFlg; // 0 = 正確,1 = 出錯。
- // 初始化局部變量。
- TmpAddr = IIC_ADDR_AT24CXX; // EEPROM的IIC地址。
- ErrFlg = 0;
- // 一個頁寫的內部擦寫時間小于10ms,這里檢查20次延時已經到了20ms。若還沒寫完,
- // 則說可能寫入失敗。
- ErrFlg = 1;
- for(TimeFlow = 0; TimeFlow < 20; TimeFlow++)
- {
- // 向IIC總線只發送其IIC地址(一字節),并判斷是否有回應
- if(0 == IIC_MCU_Send_Str(&TmpAddr,1, &TmpAddr, 0))
- {
- ErrFlg = 0; // 有回應說明擦寫已經完成。
- break;
- }
- AT24Cxx_Delay_1ms(); // 延時1ms
- }
- // 返回出錯信息。0 = 擦寫完成,1 = 失敗。
- return ErrFlg;
- }
- //----------------------------------------------------------------------------//
- // AT24Cxx溢出檢測函數(僅限本文件使用)
- //函數名稱:AT24Cxx_OverFlow_Check
- //函數功能:檢測AT24Cxx是否會發生地址溢出(或翻轉)。
- // 通過檢測EEPROM從當前地址開始的剩余字節數(AT24CXX_MAX_SIZE-Addr)和
- // 數據字節數DatSize的大小,來判斷是否會發生溢出。當(AT24CXX_MAX_SIZE-Addr)
- // 小于DatSize時,溢出、返回1;否則不溢出,返回0。
- //入口參數:Addr,AT24Cxx需要操作的起始字節地址。與A2 A1 A0無關。
- // DatSize,需要操作數據的字節數
- //出口參數:1,會發生溢出;0,不會發生溢出。
- //重要說明:本函數只用于AT24Cxx發送和接收函數,用于在實際操作前進行溢出檢測。
- //----------------------------------------------------------------------------//
- static uint8 AT24Cxx_OverFlow_Check(uint16 Addr, uint16 DatSize)
- {
- uint8 ErrFlg; // 0 = 正確,1 = 出錯。
- // 初始化局部變量。
- ErrFlg = 0;
- // 當前地址已經大于了EEPROM的容量,會發生溢出。
- if(Addr > AT24CXX_MAX_SIZE)
- {
- ErrFlg = 1;
- }
- // EEPROM剩余字節數比需要操作的字節數小,會發生溢出
- else if((AT24CXX_MAX_SIZE - Addr) < DatSize)
- {
- ErrFlg = 1;
- }
- // 返回出錯信息。
- return ErrFlg;
- }
- //-------------------------------------------------------------------------------//
- // AT24Cxx地址整理函數(僅限本文件使用)
- //函數名稱:AT24Cxx_Make_Addr
- //函數功能:把A2 A1 A0以及字節地址整理成發送格式,然后存放到PAddrBuf數組中。
- // PAddrBuf數組需要3個字節的長度。
- //入口參數:
- // A2A1A0:對應芯片A2 A1 A0引腳,低3位有效(高位被忽略)。
- // Addr :對24Cxx進行操作的起始地址。
- // *PAddrBuf:處理后數據存放的地址。
- //出口參數:PAddrBuf數組中有效的字節數。即進行讀寫前發送的字節數。其中第1個字節是
- // IIC地址和A2 A1 A0(或是a_n)的組合,第2個字節是字節地址,第3個字節(若是
- // 有的話)是字節地址。
- //重要說明:本函數不支持不同類型的IIC器件一起使用。
- //-------------------------------------------------------------------------------//
- static uint8 AT24Cxx_Make_Addr(uint8 A2A1A0, uint16 Addr, uint8 *PAddrBuf)
- {
- uint8 AvailableLength = 0;
- #if defined(AT24C01) // 可級聯8個器件,7位字節地址,2字節發送。
- // PAddrBuf[0]中存放的是(二進制表示)1 0 1 0 A2 A1 A0 0。
- // PAddrBuf[1]中存放的是(二進制表示)0 a6 a5 a4 a3 a2 a1 a0。
- // 操作數分別是 1 0 1 0 A2 A1 A0 0
- PAddrBuf[0] = IIC_ADDR_AT24CXX | ((A2A1A0 << 1) & 0x0E);
- PAddrBuf[1] = (uint8)(Addr & 0x7F);
- AvailableLength = 2;
- #elif defined(AT24C02) // 可級聯8個器件,8位字節地址,2字節發送。
- // PAddrBuf[0]中存放的是(二進制表示)1 0 1 0 A2 A1 A0 0。
- // PAddrBuf[1]中存放的是(二進制表示)a7 a6 a5 a4 a3 a2 a1 a0。
- // 操作數分別是 1 0 1 0 A2 A1 A0 0
- PAddrBuf[0] = IIC_ADDR_AT24CXX | ((A2A1A0 << 1) & 0x0E);
- PAddrBuf[1] = (uint8)(Addr & 0xFF);
- AvailableLength = 2;
- #elif defined(AT24C04) // 可級聯4個器件,9位字節地址,2字節發送。
- // PAddrBuf[0]中存放的是(二進制表示)1 0 1 0 A1 A0 a8 0。
- // PAddrBuf[1]中存放的是(二進制表示)a7 a6 a5 a4 a3 a2 a1 a0。
- // 操作數分別是 1 0 1 0 A1 A0 a8 0
- PAddrBuf[0] = IIC_ADDR_AT24CXX | ((A2A1A0 << 2) & 0x0C) | (uint8)((Addr >> 7) & 0x02);
- PAddrBuf[1] = (uint8)(Addr & 0xFF);
- AvailableLength = 2;
- #elif defined(AT24C08) // 可級聯2個器件,10位字節地址,2字節發送。
- // PAddrBuf[0]中存放的是(二進制表示)1 0 1 0 A0 a9 a8 0。
- // PAddrBuf[1]中存放的是(二進制表示)a7 a6 a5 a4 a3 a2 a1 a0。
- // 操作數分別是 1 0 1 0 A0 a9 a8 0
- PAddrBuf[0] = IIC_ADDR_AT24CXX | ((A2A1A0 << 3) & 0x08) | (uint8)((Addr >> 7) & 0x06);
- PAddrBuf[1] = (uint8)(Addr & 0xFF);
- AvailableLength = 2;
- #elif defined(AT24C16) // 不可級聯,11位字節地址,2字節發送。
- // PAddrBuf[0]中存放的是(二進制表示)1 0 1 0 a10 a9 a8 0。
- // PAddrBuf[1]中存放的是(二進制表示)a7 a6 a5 a4 a3 a2 a1 a0。
- // 操作數分別是 1 0 1 0 a10 a9 a8 0
- PAddrBuf[0] = IIC_ADDR_AT24Cxx | (uint8)((Addr >> 7) & 0x0E);
- PAddrBuf[1] = (uint8)(Addr & 0xFF);
- A2A1A0 = 0; // 故意使用A2A1A0一次,以避免Keil的警告信息
- AvailableLength = 2;
- #elif defined(AT24C32) // 可級聯8個器件,12位字節地址,3字節發送。
- // PAddrBuf[0]中存放的是(二進制表示)1 0 1 0 A2 A1 A0 0。
- // PAddrBuf[1]中存放的是(二進制表示)0 0 0 0 a11 a10 a9 a8。
- // PAddrBuf[2]中存放的是(二進制表示)a7 a6 a5 a4 a3 a2 a1 a0。
- // 操作數分別是 1 0 1 0 A2 A1 A0 0
- PAddrBuf[0] = IIC_ADDR_AT24CXX | ((A2A1A0 << 1) & 0x0E);
- PAddrBuf[1] = (uint8)((Addr >> 8) & 0x0F);
- PAddrBuf[2] = (uint8)(Addr & 0xFF);
- AvailableLength = 3;
- #elif defined(AT24C64) // 可級聯8個器件,13位字節地址,3字節發送。
- // PAddrBuf[0]中存放的是(二進制表示)1 0 1 0 A2 A1 A0 0。
- // PAddrBuf[1]中存放的是(二進制表示)0 0 0 a12 a11 a10 a9 a8。
- // PAddrBuf[2]中存放的是(二進制表示)a7 a6 a5 a4 a3 a2 a1 a0。
- // 操作數分別是 1 0 1 0 A2 A1 A0 0
- PAddrBuf[0] = IIC_ADDR_AT24CXX | ((A2A1A0 << 1) & 0x0E);
- PAddrBuf[1] = (uint8)((Addr >> 8) & 0x1F);
- PAddrBuf[2] = (uint8)(Addr & 0xFF);
- AvailableLength = 3;
- #elif defined(AT24C128) // 可級聯8個器件,14位字節地址,3字節發送。
- // PAddrBuf[0]中存放的是(二進制表示)1 0 1 0 A2 A1 A0 0。
- // PAddrBuf[1]中存放的是(二進制表示)0 0 a13 a12 a11 a10 a9 a8。
- // PAddrBuf[2]中存放的是(二進制表示)a7 a6 a5 a4 a3 a2 a1 a0。
- PAddrBuf[0] = IIC_ADDR_AT24CXX | ((A2A1A0 << 1) & 0x0E);
- PAddrBuf[1] = (uint8)((Addr >> 8) & 0x3F);
- PAddrBuf[2] = (uint8)(Addr & 0xFF);
- A2A1A0 = 0; // 故意使用A2A1A0一次,以避免Keil的警告信息
- AvailableLength = 3;
- #elif defined(AT24C256) //可級聯8個器件,15位字節地址,3字節發送。
- // PAddrBuf[0]中存放的是(二進制表示)1 0 1 0 A2 A1 A0 0。
- // PAddrBuf[1]中存放的是(二進制表示)0 a14 a13 a12 a11 a10 a9 a8。
- // PAddrBuf[2]中存放的是(二進制表示)a7 a6 a5 a4 a3 a2 a1 a0。
- // 操作數分別是 1 0 1 0 0 A1 A0 0
- PAddrBuf[0] = IIC_ADDR_AT24CXX | ((A2A1A0 << 1) & 0x0E);
- PAddrBuf[1] = (uint8)((Addr >> 8) & 0x7F);
- PAddrBuf[2] = (uint8)(Addr & 0xFF);
- AvailableLength = 3;
- #endif
- //返回PAddrBuf數組中的有效字節數
- return AvailableLength;
- }
- ////////////////////////////////////////////////////////////////////////////////
- // 本文件專用函數定義結束 //
- ////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////
- // 對外服務函數定義 //
- ////////////////////////////////////////////////////////////////////////////////
- //----------------------------------------------------------------------------//
- // 允許寫入和禁止寫入函數(對外接口)
- //函數名稱:
- //函數功能:允許寫入和禁止寫入。
- //入口參數:無
- //出口參數:無
- //重要說明:沒有啟用寫保護功能時,本函數不會進行編譯。
- //----------------------------------------------------------------------------//
- #if (1 == AT24CXX_WP_ENABLE)
- extern void AT24Cxx_Write_Enable(void) // 允許寫入。
- {
- AT24Cxx_WP = 0;
- }
- extern void AT24Cxx_Write_Disable(void) // 禁止寫入。
- {
- AT24Cxx_WP = 1;
- }
- #endif
- //----------------------------------------------------------------------------//
- // 從AT24Cxx中讀取多字節數據函數(對外接口)
- //函數名稱:AT24Cxx_Read_Str
- //函數功能:從Addr指定的地址開始讀取AT24Cxx,一共讀取Num個字節,數據讀出后存放在
- // PDat數組中。
- //入口參數:
- // A2A1A0:對應芯片A2 A1 A0引腳,低3位有效(高位被忽略).
- // Addr:對24Cxx進行讀操作的起始地址。
- // *PDat:數據讀取后存放的首地址
- // Num :要讀取的字節數
- //出口參數:0 = 成功,1 = 失敗。
- //重要說明:1.讀取的第一個字節放在PDat[0]中,第二個放在PDat[1]中,以此類推。
- // :2.若EEPROM剩余空間不足,函數報錯。
- //----------------------------------------------------------------------------//
- extern uint8 AT24Cxx_Read_Str(uint8 A2A1A0, uint16 Addr, uint8 *PDat, uint16 Num)
- {
- uint8 ErrFlg; // 0 = 正確,1 = 錯誤。
- uint8 AddrBuf[3]; // 該數組用于接收AT24CxxDivideAddr()函數分解后的地址信息。
- uint8 AddrLength; // 該變量用于指示AddrBuf數組中有效的字節數。
- // 局部變量初始化。
- ErrFlg = 0;
- // 忽略A2A1A0的高位。
- A2A1A0 &= 0x07;
- // 溢出檢測
- ErrFlg = AT24Cxx_OverFlow_Check(Addr, Num);
- // 把地址整理成發送格式。并獲取地址字節數。
- AddrLength = AT24Cxx_Make_Addr(A2A1A0, Addr, AddrBuf);
- // 讀取數據。
- if(0 == ErrFlg)
- {
- ErrFlg = IIC_MCU_Rcv_Str(AddrBuf, AddrLength, PDat, Num);
- }
- // 返回出錯信息。
- return ErrFlg;
- }
- //-------------------------------------------------------------------------------//
- // 向AT24Cxx寫入多字節數據函數(對外接口)
- //函數名稱:AT24Cxx_Write_Str
- //函數功能:向AT24Cxx中寫入多字節。寫入的起始地址由Addr確定,數據存放的首地址在PDat中存
- // 放,寫入的字節數是Num(16位無符號數)。
- //入口參數:
- // A2A1A0:對應芯片A2 A1 A0引腳,低3位有效(高位被忽略).
- // Addr:對24Cxx進行寫操作的起始地址。
- // *PDat:發送的數據存放的首地址
- // Num :發送的字節數
- //出口參數:0 = 成功,1 = 失敗。
- //重要說明:1.先發送PDat[0],再發送PDat[1],以此類推。
- // :2.若EEPROM剩余空間不足,函數報錯。
- // :3.若啟用了寫保護功能,必須先使寫保護失效,否則無法進行寫入。
- //-------------------------------------------------------------------------------//
- extern uint8 AT24Cxx_Write_Str(uint8 A2A1A0, uint16 Addr, uint8 *PDat, uint16 Num)
- {
- uint8 ErrFlg; // 0 = 正確,1 = 錯誤。
- uint8 AddrBuf[3]; // 該數組用于接收AT24CxxDivideAddr()函數分解后的地址信息。
- uint8 AddrLength; // 該變量用于指示AddrBuf數組中有效的字節數。
- uint8 PageRemainSize; // 該變量用于指示當前頁剩余字節數據
- // 局部變量初始化。
- ErrFlg = 0;
- PageRemainSize = 0;
- // 忽略A2A1A0的高位。
- A2A1A0 &= 0x07;
- // 溢出檢測
- ErrFlg = AT24Cxx_OverFlow_Check(Addr, Num);
- // 當前頁剩余字節數賦給該PageRemainSize變量
- PageRemainSize = AT24CXX_PAGEBUF_SIZE - Addr % AT24CXX_PAGEBUF_SIZE;
- // 如果當前EEPROM寫保護,則返回錯誤。
- #if (1 == AT24CXX_WP_ENABLE)
- if( 1== AT24Cxx_WP)
- {
- ErrFlg = 1;
- }
- #endif
- // -------------寫入的字節小于等于當前頁的剩余字節------------------
- if(Num <= PageRemainSize)
- {
- if(0 == ErrFlg)
- {
- // 把地址整理成發送格式。并獲取地址字節數。
- AddrLength = AT24Cxx_Make_Addr(A2A1A0, Addr, AddrBuf);
- // 發送數據。一次寫入所有字節,即Num個字節
- ErrFlg |= IIC_MCU_Send_Str(AddrBuf, AddrLength, PDat, Num);
- // 等待AT24Cxx擦寫完畢
- ErrFlg |= AT24Cxx_Finish_PageWrite();
- }
- }
- // --------------寫入的字節數大于當前頁的剩余字節數-----------------
- else
- {
- ////// 先寫當前頁 //////
- if(0 == ErrFlg)
- {
- // 把地址整理成發送格式。并獲取地址字節數。
- AddrLength = AT24Cxx_Make_Addr(A2A1A0, Addr, AddrBuf);
- // 寫當前頁剩余字節。
- ErrFlg |= IIC_MCU_Send_Str(AddrBuf, AddrLength, PDat, PageRemainSize);
- // 等待AT24Cxx擦寫完畢
- ErrFlg |= AT24Cxx_Finish_PageWrite();
- // 改變相應的變量的值,為下次發送做準備
- Addr += PageRemainSize; // AT24Cxx寫入地址增加
- PDat += PageRemainSize; // 存放數據的地址增加
- Num -= PageRemainSize; // 需要寫入的字節數減少
- }// if(0 == ErrFlg)
- ////// 寫當前頁完畢 //////
- ////// 寫中間整頁 //////
- while(Num > AT24CXX_PAGEBUF_SIZE) // 這里不可使用>=號,否則會死循環。
- {
- // 寫入時出錯,立即中止寫入操作。
- if(1 == ErrFlg)
- {
- break;
- }
- // 把地址整理成發送格式。并獲取地址字節數。
- AddrLength = AT24Cxx_Make_Addr(A2A1A0, Addr, AddrBuf);
- // 發送數據。整頁寫,即一次寫AT24CXX_PAGEBUF_SIZE個字節。
- ErrFlg |= IIC_MCU_Send_Str(AddrBuf, AddrLength, PDat, AT24CXX_PAGEBUF_SIZE);
- // 等待AT24Cxx擦寫完畢
- ErrFlg |= AT24Cxx_Finish_PageWrite();
- // 改變相應的變量的值,為下次發送做準備
- Addr += AT24CXX_PAGEBUF_SIZE; // AT24Cxx寫入地址增加
- PDat += AT24CXX_PAGEBUF_SIZE; // 存放數據的地址增加
- Num -= AT24CXX_PAGEBUF_SIZE; // 需要寫入的字節數減少
- }// while(Num > AT24CXX_PAGEBUF_SIZE)
- //////寫中間整頁完畢//////
- ////// 寫最后一頁 //////
- if(0 == ErrFlg)
- {
- // 把地址整理成發送格式。并獲取地址字節數。
- AddrLength = AT24Cxx_Make_Addr(A2A1A0, Addr, AddrBuf);
- // 寫當最后一頁剩余字節。
- ErrFlg |= IIC_MCU_Send_Str(AddrBuf, AddrLength, PDat, Num);
- // 等待AT24Cxx擦寫完畢
- ErrFlg |= AT24Cxx_Finish_PageWrite();
- }// if(0 == ErrFlg)
- //////寫最后一頁完畢//////
- }// if(Num <= PageRemainSize)
- // 返回出錯信息。
- return ErrFlg;
- }
- ////////////////////////////////////////////////////////////////////////////////
- // 對外服務函數定義結束 //
- ////////////////////////////////////////////////////////////////////////////////
- //------------------------------ 文件結束 ------------------------------//
復制代碼 |