- /*------------------------------------------------------------------------------
- 〖说明〗24Cxx I2C EEPROM字节读写驱动程序,芯片A0-A1-A2要接GND(24C65接VCC,具体看DataSheet)。
- 现缺页写、页读,和CRC校验程序。以下程序经过50台验证,批量的效果有待考察。
- 为了安全起见,程序中很多NOP是冗余的,希望读者能进一步精简,但必须经过验证。
- Atmel 24C01 比较特殊,为简约型,为其单独编程.
- 51晶振为11.0592MHz
- 〖文件〗RW24CXX.c 2001/09/18
- --------------------------------------------------------------------------------*/
- /*---------------------------------------------------------------------------------------------------------------
- 调用方式:void WriteIIC_24CXX(enum EEPROMTYPE eepromtype,unsigned int address,unsigned char ddata) ﹫2001/09/18
- 函数说明:对于IIC芯片24CXX,在指定地址address写入一个字节ddata
- 调用方式:unsigned char ReadIIC_24CXX(enum EEPROMTYPE eepromtype,unsigned int address) ﹫2001/09/18
- 函数说明:读取IIC芯片24CXX,指定地址address的数据。
- -----------------------------------------------------------------------------------------------------------------*/
- #include "reg51.h"
- #include "intrins.h"
- sbit SCL= P2^7;
- sbit SDA= P2^6;
- enum EEPROMTYPE {IIC24C01,IIC24C01A,IIC24C02,IIC24C04,IIC24C08,IIC24C16,IIC24C32,IIC24C64,IIC24C128,IIC24C256};
- enum EEPROMTYPE eepromtype;
- delay()
- {
- unsigned int i=1200;
- while(i--);
- }
- /*----------------------------------------------------------------------------
- 调用方式:write_8bit(unsigned char ch) ﹫2001/03/23
- 函数说明:内函数,私有,用户不直接调用。
- -------------------------------------------------------------------------------*/
- void write_8bit(unsigned char ch)
- {
- unsigned char i=8;
- SCL=0;
- _nop_();_nop_();_nop_();_nop_();_nop_();
- while (i--)
- {
- SDA=(bit)(ch&0x80);
- _nop_();_nop_();_nop_();_nop_();_nop_();
- ch<<=1;
- SCL=1;
- _nop_();_nop_();_nop_();_nop_();_nop_();
- SCL=0;
- _nop_();_nop_();_nop_();_nop_();_nop_();
- }
- _nop_();_nop_();_nop_();_nop_();_nop_();
- _nop_();_nop_();_nop_();_nop_();_nop_();
- }
- /*------------------------------------------------------------------------------
- 调用方式:void ACK(void) ﹫2001/03/23
- 函数说明:内函数,私有,用户不直接调用。
- -------------------------------------------------------------------------------*/
- void ACK(void)
- {
- unsigned char time_1;
- SDA=1;
- SCL=0;
- _nop_();_nop_();_nop_();_nop_();_nop_();
- SCL=1;
- time_1=5;
- while(SDA) {if (!time_1) break;} //ACK
- SCL=0;
- _nop_();_nop_();_nop_();_nop_();_nop_();
- }
- void WriteIIC_24C01(unsigned char address,unsigned char ddata)
- {SCL=1;
- _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); //Tsu:STA
- SDA=0;
- _nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); //Thd:STA
- SCL=0; //START
- write_8bit( (address<<1) & 0xfe); //写页地址和操作方式,对于24C32-24C256,page不起作用
- ACK();
- write_8bit(ddata); //发送数据
- ACK();
- SDA=0;
- _nop_();SCL=1;_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
- SDA=1; //STOP
- delay();
- }
- /*---------------------------------------------------------------------------------------------------------------
- 调用方式:void WriteIIC_24CXX(enum EEPROMTYPE eepromtype,unsigned int address,unsigned char ddata) ﹫2001/09/18
- 函数说明:对于IIC芯片24CXX,在指定地址address写入一个字节ddata
- -----------------------------------------------------------------------------------------------------------------*/
- void WriteIIC_24CXX(enum EEPROMTYPE eepromtype,unsigned int address,unsigned char ddata)
- { unsigned char page,address_in_page;
- if(eepromtype==IIC24C01) //如果是24c01
- {
- WriteIIC_24C01(address,ddata);
- return;
- }
- page=(unsigned char)(address>>8) & 0x07;
- page=page<<1;
- address_in_page=(unsigned char)(address);
- SCL=1;
- _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); //Tsu:STA
- SDA=0;
- _nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); //Thd:STA
- SCL=0; //START
- write_8bit(0xa0 | page); //写页地址和操作方式,对于24C32-24C256,page不起作用
- ACK();
- if(eepromtype>IIC24C16) //如果是24C01-24C16,地址为一字节;24C32-24C256,地址为二字节
- {
- write_8bit(address>>8);
- ACK();
- }
- write_8bit(address_in_page);
- ACK();
- write_8bit(ddata);
- ACK();
- SDA=0;
- _nop_();SCL=1;_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
- SDA=1; //STOP
- delay();
- }
- unsigned char ReadIIC_24C01(unsigned char address)
- {
- unsigned char ddata=0;
- unsigned char i=8;
- SCL=1;
- _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); //Tsu:STA
- SDA=0;
- _nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); //Thd:STA
- SCL=0; //START
- write_8bit( (address<<1) | 0x01); //写页地址和操作方式
- ACK();
- while (i--)
- {
- SDA=1;
- ddata<<=1;
- SCL=0;
- _nop_();_nop_();_nop_();_nop_();_nop_();
- SCL=1;
- if (SDA) ddata|=0x01;
- }
- SCL=0;_nop_();SCL=1;_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
- SDA=0;_nop_();SCL=1;_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
- SDA=1; //STOP
- delay();
- return ddata;
- }
- /*----------------------------------------------------------------------------------------------------
- 调用方式:unsigned char ReadIIC_24CXX(enum EEPROMTYPE eepromtype,unsigned int address) ﹫2001/09/18
- 函数说明:读取IIC芯片24CXX,指定地址address的数据。
- ------------------------------------------------------------------------------------------------------*/
- unsigned char ReadIIC_24CXX(enum EEPROMTYPE eepromtype,unsigned int address)
- { unsigned char page,address_in_page;
- unsigned char ddata=0;
- unsigned char i=8;
- if(eepromtype==IIC24C01)
- {
- return( ReadIIC_24C01(address) );
- }
- page=(unsigned char)(address>>8) & 0x07;
- page=page<<1;
- address_in_page=(unsigned char)(address);
- SDA=0;_nop_();SCL=0; //START
- write_8bit(0xa0 | page); //写页地址和操作方式,对于24C32-24C256,page不起作用
- ACK();
- if(eepromtype>IIC24C16) //如果是24C32-24C256,地址为二字节,先送高位,后送低位
- {
- write_8bit(address>>8);
- ACK();
- }
- //如果是24C01-24C16,地址为一字节;
- write_8bit(address_in_page);
- ACK();//以上是一个“哑”写操作,相当于设置当前地址
- SCL=1;
- _nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); //Tsu:STA
- SDA=0;
- _nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); //Thd:STA
- SCL=0; //START
- write_8bit(0xa1); //写从地址,置为读模式
- ACK();
- while (i--)
- {
- SDA=1;
- ddata<<=1;
- SCL=0;_nop_();_nop_();_nop_();_nop_();_nop_();SCL=1;
- if (SDA) ddata|=0x01;
- }
- SCL=0;_nop_();SCL=1;_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
- SDA=0;_nop_();SCL=1;_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
- SDA=1; //STOP
- delay();
- return ddata;
- }
- /*分析:
- 该芯片采用传统的IIC口的规约形式,是一个标准的经典IIC封装。
- 注:使用该程序时注意改变芯片各个接口的修改。注意屏蔽主函数。
- */
- main()
- {
- unsigned int i;
- unsigned char kk,j[32];
- delay();
- kk=ReadIIC_24C01( 12 );
- WriteIIC_24C01(12,0x67);
- kk=ReadIIC_24C01(12);
- for(i=0;i<32;i++) j[i]=ReadIIC_24CXX(IIC24C01,i);
- for(i=0;i<32;i++) j[i]=i*2;
- for(i=0;i<32;i++) WriteIIC_24CXX(IIC24C01,i,0x55);
- for(i=0;i<32;i++) j[i]=0;
- for(i=0;i<32;i++) j[i]=ReadIIC_24CXX(IIC24C02,i);
- }