/* 在buf1中填入需要写入的内容,buf2的大小可根据需要定义。
addr可根据使用的芯片选择,可从任何位置读写,只要在该芯片的范围内。
enumer=ATxxx,根据使用的芯片赋值。各函数中的形式参数不需改变。
本程序只要在调用的程序中定义实际参数即可,下述各子程序不必改动。*/
#include
#include
#define ERROR 10 //允许ERROR的最大次数
sbit SDA=P0^0;
sbit SCL=P0^1;
enum eepromtype {AT2401,AT2402,AT2404,AT2408,AT2416,AT2432,AT2464,AT24128,AT24256};/*器件的型号*/
enum eepromtype enumer; //定义一个枚举变量
//unsigned char code buf1 []={1,3,5,7,9,10,11,12,13,15}; /* 发送缓冲区 */
unsigned char buf2 [10]; /* 接收缓冲区 */
unsigned char code buf1[256]={0x1B,0xAC,0x07,0x08,0xC0,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAC,0x07,0xAE,0x07,
0xB2,0x07,0xB8,0x07,0xBA,0x07,0xBC,0x07,0xBE,0x07,0xC0,0x07,
0xC2,0x07,0xC6,0x07,0xC8,0x07,0xDE,0x07,0x1C,0x08,0x42,0x08,
0x52,0x08,0x62,0x08,0x6C,0x08,0x6E,0x08,0x77,0x08,0x81,0x08,
0x82,0x08,0x92,0x08,0x95,0x08,0x98,0x08,0xB6,0x08,0xBC,0x08,
0xCB,0x08,0xDB,0x08,0xEE,0x08,0x46,0x09,0xC0,0x06,0xD0,0x06,
0xE0,0x06,0xF0,0x06,0x00,0x07,0x10,0x07,0x40,0x09,0x60,0x08,
0x40,0x0A,0x80,0x08,0x50,0x0A,0x60,0x0A,0x80,0x0B,0xA0,0x0B,
0xC0,0x0B,0xD0,0x0B,0xF0,0x0B,0x90,0x0B,0x00,0x0C,0xE0,0x0D,
0xF0,0x0D,0x10,0x0E,0x20,0x0E,0x30,0x0E,0x40,0x0E,0x50,0x0E,
0xA0,0x08,0xF0,0x09,0x00,0x0B,0xE0,0x0B,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0XFF
};
/* ----- AT24C01~AT24C256 的读写程序 ------ */
bit RW24xx(unsigned char *DataBuff,unsigned char Length,unsigned int Addr,unsigned char Control,enum eepromtype enumer)
{
void Delay(unsigned char DelayCount); /* 延时 */
void Start(void); /* 启动总线 */
void Stop(void); /* 停止IIC总线 */
bit RecAck(void); /* 检查应答位 */
void NoAck(void); /* 不对IIC总线产生应答 */
void Ack(void); /* 对IIC总线产生应答 */
unsigned char Receive(void); /* 从IIC总线上读数据子程序 */
void Send(unsigned char sendbyte); /* 向IIC总线写数据 */
unsigned char data j,i=ERROR;
bit errorflag=1; /* 出错标志 */
while (i--)
{
Start(); /* 启动总线 */
Send(Control & 0xfe); /* 向IIC总线写数据,器件地址 */
if (RecAck()) continue; /* 如写不正确结束本次循环 */
if (enumer > AT2416)
{
Send((unsigned char)(Addr >> 8));//把整型数据转换为字符型数据:弃高取低,只取低8位.如果容量大于32K位,使用16位地址寻址,写入高八位地址
if (RecAck()) continue;
}
Send((unsigned char)Addr); /* 向IIC总线写数据 */
if (RecAck()) continue; /* 如写正确结束本次循环 */
if (!(Control & 0x01)) //判断是读器件还是写器件
{
j=Length;
errorflag=0; /* 清错误特征位 */
while (j--)
{
Send(*DataBuff++); /* 向IIC总线写数据 */
if (!RecAck()) continue; /* 如写正确结束本次循环 */
errorflag=1;
break;
}
if (errorflag==1) continue;
break;
}
else
{
Start(); /* 启动总线 */
Send(Control); /* 向IIC总线写数据 */
if (RecAck()) continue;//器件没应答结束本次本层循环
while (--Length) /* 字节长为0结束 */
{
*DataBuff ++= Receive();
Ack(); /* 对IIC总线产生应答 */
}
*DataBuff=Receive(); /* 读最后一个字节 */
NoAck(); /* 不对IIC总线产生应答 */
errorflag=0;
break;
}
}
Stop(); /* 停止IIC总线 */
if (!(Control & 0x01))
{
Delay(255);
Delay(255);
Delay(255);
Delay(255);
}
return(errorflag);
}
/* * * * * 以下是对IIC总线的操作子程序 * * * * */
/* * * * * * 启动总线 * * * * */
void Start(void)
{
SCL=0; /* SCL处于高电平时,SDA从高电平转向低电平表示 */
SDA=1; /* 一个"开始"状态,该状态必须在其他命令之前执行 */
SCL=1;
_nop_();
_nop_();
_nop_();
SDA=0;
_nop_();
_nop_();
_nop_();
_nop_();
SCL=0;
SDA=1;
}
/* * * * * 停止IIC总线 * * * * */
void Stop(void)
{
SCL=0; /*SCL处于高电平时,SDA从低电平转向高电平 */
SDA=0; /*表示一个"停止"状态,该状态终止所有通讯 */
SCL=1;
_nop_();
_nop_();
_nop_(); /* 空操作 */
SDA=1;
_nop_();
_nop_();
_nop_();
SCL=0;
}
/* * * * * 检查应答位 * * * * */
bit RecAck(void)
{
SCL=0;
SDA=1;
SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
CY=SDA; /* 因为返回值总是放在CY中的 */
SCL=0;
return(CY);
}
/* * * * *对IIC总线产生应答 * * * * */
void Ack(void)
{
SDA=0; /* EEPROM通过在收到每个地址或数据之后, */
SCL=1; /* 置SDA低电平的方式确认表示收到读SDA口状态 */
_nop_();
_nop_();
_nop_();
_nop_();
SCL=0;
_nop_();
SDA=1;
}
/* * * * * * * * * 不对IIC总线产生应答 * * * * */
void NoAck(void)
{
SDA=1;
SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
SCL=0;
}
/* * * * * * * * * 向IIC总线写数据 * * * * */
void Send(unsigned char sendbyte)
{
unsigned char data j=8;
for (; j>0; j--)
{
SCL=0;
sendbyte <<= 1; /* 使CY=sendbyte^7; */
SDA=CY; /* CY 进位标志位 */
SCL=1;
}
SCL=0;
}
/* * * * * * * * * 从IIC总线上读数据子程序 * * * * */
unsigned char Receive(void)
{
register receivebyte,i=8;
SCL=0;
while (i--)
{
SCL=1;
receivebyte = (receivebyte <<1 ) | SDA;
SCL=0;
}
return(receivebyte);
}
/* * * * * * * * 一个简单延时程序 * * * * * * * * * * * * */
void Delay(unsigned char DelayCount)
{
while (DelayCount--);
}
/* ----- AT24C01~AT24C256 的读写程序 ------ */
void main()
{
unsigned char Control,*p1,*p2;
unsigned char Length,i;
unsigned int addr ; /* 24Cxx片内地址 */
p1=buf1;
p2=buf2;
addr=0; /* 片内地址 AT24C256为0~32767 */
Length=8; /* 读写长度 */
// enumer=AT24256; /* 读写AT24C256 */
// Control=0xa0; /* 写操作 */
// RW24xx(p1,Length,addr,Control,enumer); /* 写 */
// Control=0xa1; /* 读操作 */
// RW24xx(p2,Length,addr,Control,enumer); /* 读 */
enumer=AT2402; /* 读写AT24C256 */
Control=0xa0; /* 写操作 */
P2=0XFE;
Delay(255);
for (i=0; i<32; i++)
{
RW24xx(p1,Length,addr,Control,enumer); /* 写 */
Delay(20);
addr+=8;
p1+=8;
}
Delay(255);
P2=0XFD;
// Control=0xa1; /* 读操作 */
// RW24xx(p2,Length,addr,Control,enumer); /* 读 */
while (1)
{
;
}
}
用Keil uVision3编译结果如下:
Program Size: data=43.1 xdata=0 code=785
"1" - 0 Error(s), 0 Warning(s).
如有任何问题可以发E-Mail:[email protected]给我,共同探讨,共同进步!