|
下面是24LC256 的程序,我自己的项目里的,绝对可用。
/*-----------------------
*函数名称:vid Init(void)
*函数说明:IIC器件的初始化
*----------------------*/
void Init(void)
{
SCL_1;
delay(5);
SDA_1;
delay(5);
}
/*-------------------------------------
*函数名称:void Start(void)
*函数说明:提供I2C总线工作时序中的起始位
*------------------------------------*/
void Start(void)
{
SDA_1;
delay(5);
SCL_1;
delay(5);
SDA_0;
delay(5);
SCL_0;
delay(5);
}
/*--------------------------------------
*函数名称:void Stop(void)
*函数说明:提供I2C总线工作时序中的停止位
*-------------------------------------*/
void Stop(void)
{
SDA_0;
delay(5);
SCL_1;
delay(5);
SDA_1;
delay(5);
}
/*------------------------------------------------------------
*函数名称:IICAck(void)
*函数说明:对IIC总线产生应答,在连续读取时,每读取1字节后执行
*------------------------------------------------------------*/
void IICAck(void)
{
SDA_0;
SCL_1;
_NOP();
_NOP();
_NOP();
SCL_0;
_NOP();
SDA_1;
}
/*------------------------------------------------------
*函数名称:IICNoAck(void)
*函数说明: 不对IIC总线产生应答,在读取完最后1字节数据后执行
*-----------------------------------------------------*/
void IICNoAck(void)
{
SDA_1;
SCL_1;
_NOP();
_NOP();
_NOP();
SCL_0;
}
/*-----------------------------------------------------
*函数名称: ReceiveAck(void)
*函数说明: 检查返回应答位,在每写入1字节数据后都要执行
*----------------------------------------------------*/
unsigned char ReceiveAck(void)
{
unsigned char Ack=0; //存储应答位的字节
SDA_1 ;
delay(2);
SCL_1 ;
delay(2);
DIR_IN; // SDA 方向为输入
Ack = SDA_IN ; //SDA状态送Ack
SCL_0 ;
DIR_OUT; //SDA 方向重新还原为输出
delay(2);
return (Ack);
}
/*-----------------------------------------------------
*函数名称:Write_byte(unsigned char input)
*函数说明:向I2C总线发送8位数据, 高位在先
*----------------------------------------------------*/
void Write_byte(unsigned char input)
{
unsigned char i;
for(i=0;i<8;i++)
{
if((input&0x80)==0x80)
SDA_1;
else
SDA_0;
SCL_1;
SCL_0;
input=input<<1;
delay(3);
}
}
/*--------------------------------------
*函数名称:Read_byte(unsigned char input)
*函数说明:从I2C总线读取8位数据, 高位在先
*-------------------------------------*/
unsigned char Read_byte(void)
{
unsigned char i, output=0;
DIR_IN; //SDA方向设置为 输入
for(i=0;i<8;i++)
{
SCL_1;
output=output<<1;
if(SDA_IN==0x01)output=output|0x01;
SCL_0;
delay(3);
}
DIR_OUT; //SDA方向设置为 输出
return(output);
}
/*------------------------------------------------------------------------------
*函数名称:WR_24LC256(unsigned int RomAddress,unsigned char data)
*函数说明:写1字节数据到LC256(字节写模式),(先写器件地址,片内地址,再送数据)
*-----------------------------------------------------------------------------*/
void WR_24LC256(unsigned int RomAddress,unsigned char data)
{
unsigned char i;
unsigned char Ack;
Init(); //I2C总线初始化
for (i=0;i<10;i++) //每个要写入的数据最多允许写10次(在失败情况下)
{
Start();
Write_byte(0xa0); //24C的外部地址,0xa0
Ack= ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
Write_byte((unsigned char)(RomAddress>>8)); //片内rom地址 高8位
Ack= ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
Write_byte((unsigned char)RomAddress); //片内rom地址 低8位
Ack= ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
Write_byte(data);
Ack= ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
Stop();
if (Ack==0) break;//写入正确,1次即可,跳出for
}
delay(1000);
}
/*-----------------------------------------------------------------------------------------
*函数名称:void PWR_24LC256(unsigned int RomAddress,unsigned char number)
*函数说明:连续写模式,一次写入最多64字节数据,RomAddress为起始地址,number为要写入的数据字节数
*-----------------------------------------------------------------------------------------*/
void PWR_24LC256(unsigned int RomAddress,unsigned char number )
{
unsigned char i,k;
unsigned char Ack;
unsigned char errorflag;
Init(); //I2C总线初始化
for (i=0;i<10;i++) //每个要写入的数据最多允许写10次(在失败情况下)
{
Start();
Write_byte(0xa0); //24C的外部地址,0xa0
Ack= ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
Write_byte((unsigned char)(RomAddress>>8)); //片内rom地址 高8位
Ack= ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
Write_byte((unsigned char)RomAddress); //片内rom地址 低8位
Ack= ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
errorflag=0;
for(k=0;k<number;k++) //循环送数据
{
Write_byte(WR_RDtab[k]);
Ack= ReceiveAck();//
if(Ack==0x00) //写入正确
{ continue;}
errorflag=1;
break;
}
if(errorflag==1)
{continue;} //写入错误,重新写入控制字节,首地址,重新写所有数据
break;
}
Stop();
delay(1000);
}
/*----------------------------------------------------------------------------------
*函数名称:RD_24LC256(unsigned cahr addr1,unsigned int addr2)
*函数说明:读24LC256函数(字节模式),带二个参数,第一个参数为24C的外部地址和读写命令码
* 第二个参数为24C的内部存储地址,返回值为欲读出的值
*---------------------------------------------------------------------------------*/
unsigned char RD_24LC256(unsigned int RomAddress)
{
unsigned char Temp;
unsigned char i;
unsigned char Ack;
Init(); //I2C总线初始化
for(i=0;i<10;i++)
{
Start();
Write_byte(0xa0); //devices address(control byte) 写
Ack=ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
Write_byte((unsigned char)(RomAddress>>8)); //片内rom地址 高8位
Ack=ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
Write_byte((unsigned char)RomAddress); //片内rom地址 低8位
Ack=ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
Start();
Write_byte(0xa1); //devices address(control byte) 读
Ack=ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
Temp=Read_byte();
IICNoAck();
Stop();
if (Ack==0 ) break;//写入正确,1次即可,跳出for
}
return (Temp) ;
}
/*----------------------------------------------------------------------------
*函数名称:SRD_24LC256(unsigned int RomAddress,unsigned char number)
*函数说明:连续读模式,RomAddress为要读取数据的起始地址,number为要读取的字节数
*---------------------------------------------------------------------------*/
void SRD_24LC256(unsigned int RomAddress,unsigned char number)
{
unsigned char i,k;
unsigned char Ack;
Init(); //I2C总线初始化
for(i=0;i<10;i++)
{
Start();
Write_byte(0xa0); //devices address 写
Ack=ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
Write_byte((unsigned char)(RomAddress>>8)); //片内rom地址 高8位
Ack= ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
Write_byte((unsigned char)RomAddress); //片内rom地址 低8位
Ack= ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
Start();
Write_byte(0xa1); //devices address 读
Ack=ReceiveAck();
if(Ack==0x01)
{
Stop();
continue;
}
for(k=0;k<number-1;k++) //循环读取数据
{
WR_RDtab[k]=Read_byte();
IICAck();
}
WR_RDtab[k]=Read_byte();//读取最后一个字节数据
IICNoAck();
break;
}
Stop();
} |
|