|
作者:未知 文章来源:网络 点击数:
990 更新时间:2007-9-3 21:48:58 |
/*------------------------------------------------------------------------------ 〖说明〗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); } |