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;
- }
- ////////////////////////////////////////////////////////////////////////////////
- // 对外服务函数定义结束 //
- ////////////////////////////////////////////////////////////////////////////////
- //------------------------------ 文件结束 ------------------------------//
复制代码 |