原创 51 24c02 读写 实验(十三)

2008-5-12 11:03 5279 8 8 分类: MCU/ 嵌入式

点击下载


这个实验,实现对24c02的读写操作,详情见附件.


平台:FDR51开发板


代码:


#include <reg52.h>
#include <intrins.h>
 
#define ERROR 10
 
#define LEDPORT P0   //数码管接线脚


sbit SCL="P3"^5;     //AT24C02-256的接线脚
sbit SDA="P3"^6;
 
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];         /* 接收缓冲区 */


 


/* 一个通用的24C01-24C256共9种EEPROM的字节读写操作程序,
此程序有五个入口条件,分别为读写数据缓冲区指针,
进行读写的字节数,EEPROM首址,EEPROM控制字节,
以及EEPROM类型。此程序结构性良好,具有极好的容错性,程序机器码也不多:
DataBuff为读写数据输入/输出缓冲区的首址
Length 为要读写数据的字节数量
Addr 为EEPROM的片内地址 AT24256为0~32767
Control 为EEPROM的控制字节,具体形式为(1)(0)(1)(0)(A2)(A1)(A0)(R/W),其中R/W=1,
表示读操作,R/W=0为写操作,A2,A1,A0为EEPROM的页选或片选地址;
enumer为枚举变量,需为AT2401至AT24256中的一种,分别对应AT24C01至AT24C256;
函数返回值为一个位变量,若返回1表示此次操作失效,0表示操作成功;
ERROR为允许最大次数,若出现ERRORCOUNT次操作失效后,则函数中止操作,并返回1
SDA和SCL由用户自定义,这里暂定义为P3^0和P3^1; */   
/* ----- AT24C01~AT24C256 的读写程序 ------ */
bit RW24xx(unsigned char *DataBuff,unsigned char Length,unsigned int Addr,
unsigned char Control,enum eepromtype enumer)
{
 void Delay(unsigned int 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));
   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);
}
/* 以上为AT24C01~AT24C256的读写程序,各人可根据自己的需要应用。
在buf1中填入需要写入的内容,buf2的大小可根据需要定义。
addr可根据使用的芯片选择,可从任何位置读写,只要在该芯片的范围内。
enumer=ATxxx,根据使用的芯片赋值。各函数中的形式参数不需改变。
本程序只要在调用的程序中定义实际参数即可,上述各子程序不必改动。*/


/* * * * * * * * 一个简单延时程序 * * * * * * * * * * * * */
void Delay(unsigned int DelayCount)
{
 while(DelayCount--);
}
/*-------------数码管显示函数--------------------
参数:number 要显示的数字
参数:pos    要显示的位置(从左到右为1--4)
返回值:无
------------------------------------------------*/
/* * * * * * * * * *数码管显示函数* * * * * * * * * * * */
void display(unsigned char number,unsigned char pos)//数码管显示函数
{          
 unsigned char temp;      //临时变量
 if(number<10 && pos<5 && pos>0)//确定数据合法
 {  
  temp=(number<<4)&0xf0;  //获得要显示的数据
  temp+=1<<(pos-1);    //送位置位
  LEDPORT=temp;     ////送显示数据,开始显示
 }
 else return;
}


void leddisplay(unsigned int count)
{
 unsigned int i="6000";
 while(i--)
 {
 if(count>=1000)
 {
  display(count/1000,1);
  display(count%1000/100,2);
  display(count%100/10,3);
  display(count%10,4);
 }
 else  if(count>=100)
 {
  display(count/100,2);
  display(count%100/10,3);
  display(count%10,4);
 }
 else  if(count>=10)
 {
  display(count/10,3);
  display(count%10,4);
 }
 else
 {
  display(count,4);
 }
 }
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * */
void main()
{
  unsigned char Control,*p1,*p2;
 unsigned char Length,i=0;
 unsigned int addr ; /* 24Cxx片内地址 */
 p1=buf1;p2=&buf2[0];
 addr=0;    /* 片内地址 AT24C02为0~255 */
 Length=10;    /* 读写长度 */
 enumer=AT2402;   /* 读写AT24C02 */
 Control=0xa0;   /* 写操作 */
 RW24xx(p1,Length,addr,Control,enumer); /* 写 */
 Control=0xa1;   /* 读操作 */
 RW24xx(p2,Length,addr,Control,enumer); /* 读 */
 while(1)
 {
     leddisplay(buf2);//数码管显示读出来的数据
  i++;
  if(i==10){i=0;}
 }
}

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
8
关闭 站长推荐上一条 /3 下一条