📄 24cxxx.c
字号:
/***********************************************************************************
此程序包括对24XX系列EEPROM的字节、页读写操作
DataBuff为读写数据输入/输出缓冲区的首址
ByteQuantity 为要读写数据的字节数量
Address 为EEPROM的片内地址
ControlByte 为EEPROM的控制字节,具体形式为(1)(0)(1)(0)(A2)(A1)(A0)(R/W),其中R/W=1,
表示读操作,R/W=0为写操作,A2,A1,A0为EEPROM的页选或片选地址;
EepromType为枚举变量,需为M2401至M24256中的一种,分别对应24C01至24C256;
函数返回值为一个位变量,若返回1表示此次操作失效,0表示操作成功;
ERRORCOUNT为允许最大次数,若出现ERRORCOUNT次操作失效后,则函数中止操作,并返回1
SDA和SCL由用户自定义,这里暂定义为P0^1和P0^0;
***********************************************************************************/
#pragma ot(5,SIZE)
#include <reg51.h>
#include <intrins.h>
#define ERRORCOUNT 10
sbit SDA=0xB3;
sbit SCL=0xB5;
enum eepromtype {M2401,M2402,M2404,M2408,M2416,M2432,M2464,M24128,M24256};
enum eepromtype EepromType; /* 器件类型枚举变量取值为0-8 */
/***********************************************************************************/
bit RW24XX(unsigned char *DataBuff,unsigned char ByteQuantity,unsigned int Address,
unsigned char ControlByte,enum eepromtype EepromType)
{
void Delay(unsigned char DelayCount);
void IICStart(void);
void IICStop(void);
bit IICRecAck(void);
void IICNoAck(void);
void IICAck(void);
unsigned char IICReceiveByte(void);
void IICSendByte(unsigned char sendbyte);
unsigned char data j,i=ERRORCOUNT;
bit errorflag=1; /* clr errorflag */
while(i--) /* 启动IIC总线并发送EEPROM从器件地址 */
{
IICStart(); /* 启动IIC总线 */
IICSendByte(ControlByte&0xfe); /* 发送EEPROM地址 */
if(IICRecAck()) /* 接收EEPROM应答信号 */
continue; /* 接收EEPROM应答信号,为1重新启动 */
if(EepromType>M2416) /* EEPROM为24C32以上器件内地址为2字节 */
{
IICSendByte((unsigned char)(Address>>8));/* 先发送高字节,参考硬件相关说明 */
if(IICRecAck())
continue;
}
IICSendByte((unsigned char)Address);/* 再发送低字节或单字节地址 */
if(IICRecAck())
continue;
if(!(ControlByte&0x01)) /* 以下为写操作 */
{
j=ByteQuantity; /* ByteQuantity为写入字节数 */
errorflag=0;
while(j--)
{
IICSendByte(*DataBuff++); /* DataBuff写操作缓冲区 */
if(!IICRecAck())
continue;
errorflag=1;
break;
}
if(errorflag==1)
continue;
break;
}
else /* 以下为读操作 */
{
IICStart(); /* 重新启动IIC总线并发送EEPROM从器件地址 */
IICSendByte(ControlByte);
if(IICRecAck())
continue;
while(--ByteQuantity) /* 每次读一字节,共ByteQuantity字节 */
{
*DataBuff++=IICReceiveByte(); /*读1字节并存入DataBuff为指针的存储单元 */
IICAck(); /* 发送应答信号 */
}
*DataBuff=IICReceiveByte(); /*read last byte data*/
IICNoAck(); /* 读入最后一字节无须发送应答信号 */
errorflag=0;
break;
}
}
IICStop(); /* 停止IIC总线信号 */
if(!(ControlByte&0x01)) /* 写入操作需延时,确保足够长写入时间 */
{
Delay(255);
Delay(255);
Delay(255);
Delay(255);
}
return(errorflag);
}
/*******************
以下是对IIC操作子程序
*******************/
/*******************
启动IIC
*******************/
void IICStart(void)
{
SCL=0;
SDA=1;
SCL=1;
_nop_();
_nop_();
_nop_();
SDA=0;
_nop_();
_nop_();
_nop_();
_nop_();
SCL=0;
SDA=1;
}
/*****************
停止IIC总线
*****************/
void IICStop(void)
{
SCL=0;
SDA=0;
SCL=1;
_nop_();
_nop_();
_nop_();
SDA=1;
_nop_();
_nop_();
_nop_();
SCL=0;
}
/**************
检查应答位
**************/
bit IICRecAck(void)
{
SCL=0;
SDA=1;
SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
CY=SDA; /* 应答位返回值在CY中,0有效 */
SCL=0;
return(CY);
}
/***************
对IIC总线产生应答
***************/
void IICAck(void)
{
SDA=0;
SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
SCL=0;
_nop_();
SDA=1;
}
/*****************
不对IIC总线产生应答
*****************/
void IICNoAck(void)
{
SDA=1;
SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
SCL=0;
}
/*******************
向IIC总线写数据
*******************/
void IICSendByte(unsigned char sendbyte)
{
unsigned char data j=8;
for(;j>0;j--)
{
SCL=0;
sendbyte<<=1; /* 发送字节变量sendbyte左移1位,CY=sendbyte^7,并回存 */
SDA=CY;
SCL=1;
}
SCL=0;
}
/********************
从IIC总线读数据子程序
********************/
unsigned char IICReceiveByte(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--);
}
/****************
应用举例
****************/
main()
{
unsigned char *pix=0x30;
unsigned char i;
for(i=0;i<10;i++)
*pix++=i+2; /* 设置待写入数据 */
RW24XX(0x30,10,0x0010,0xa0,6); /* 待写入数据存储指针,写入字节数 */
/* 写入器件内首地址,写入控制字,器件类型 */
RW24XX(0x40,10,0x0010,0xa1,6);
Delay(50); /* 检查内部数据区0x30-0x39与0x40-0x49应完全相同 */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -