如何使用C语言实现51单片机模拟I2C总线

电子说

1.3w人已加入

描述

  电路原理图

51单片机

  EEPROM为ATMEL公司的AT24C01A。单片机为ATMEL公司的AT89C51。

  软件说明

  C语言为Franklin C V3.2。将源程序另存为testi2c.c,用命令

  C51 testi2c.c

  L51 TESTI2C.OBJ

  OHS51 TESTI2C

  编译,连接,得到TESTI2C.HEX文件,即可由编程器读入并进行写片,实验。

  3.源程序

  #include 《reg51.h》

  #include 《intrins.h》

  #define uchar unsigned char

  #define uint unsigned int

  #define AddWr 0xa0 /*器件地址选择及写标志*/

  #define AddRd 0xa1 /*器件地址选择及读标志*/

  #define Hidden 0x0e /*显示器的消隐码*/

  /*有关全局变量*/

  sbit Sda= P3^7; /*串行数据*/

  sbit Scl= P3^6; /*串行时钟*/

  sbit WP= P3^5; /*硬件写保护*/

  void mDelay(uchar j)

  { uint i;

  for(;j》0;j--)

  { for(i=0;i《125;i--)

  {;}

  }

  }

  /*发送起始条件*/

  void Start(void) /*起始条件*/

  {

  Sda=1;

  Scl=1;

  _nop_ ();

  _nop_ ();

  _nop_ ();

  _nop_ ();

  Sda=0;

  _nop_ ();

  _nop_ ();

  _nop_ ();

  _nop_ ();

  }

  void Stop(void) /*停止条件*/

  {

  Sda=0;

  Scl=1;

  _nop_ ();

  _nop_ ();

  _nop_ ();

  _nop_ ();

  Sda=1;

  _nop_ ();

  _nop_ ();

  _nop_ ();

  _nop_ ();

  }

  void Ack(void) /*应答位*/

  {

  Sda=0;

  _nop_ ();

  _nop_ ();

  _nop_ ();

  _nop_ ();

  Scl=1;

  _nop_ ();

  _nop_ ();

  _nop_ ();

  _nop_ ();

  Scl=0;

  }

  void NoAck(void) /*反向应答位*/

  {

  Sda=1;

  _nop_ ();

  _nop_ ();

  _nop_ ();

  _nop_ ();

  Scl=1;

  _nop_ ();

  _nop_ ();

  _nop_ ();

  _nop_ ();

  Scl=0;

  }

  void Send(uchar Data) /*发送数据子程序,Data为要求发送的数据*/

  {

  uchar BitCounter=8; /*位数控制*/

  uchar temp; /*中间变量控制*/

  do

  {

  temp=Data;

  Scl=0;

  _nop_ ();

  _nop_ ();

  _nop_ ();

  _nop_ ();

  if((temp&0x80)==0x80)/* 如果最高位是1*/

  Sda=1;

  else

  Sda=0;

  Scl=1;

  temp=Data《《1; /*RLC*/

  Data=temp;

  BitCounter--;

  }while(BitCounter);

  Scl=0;

  }

  uchar Read(void) /*读一个字节的数据,并返回该字节值*/

  {

  uchar temp=0;

  uchar temp1=0;

  uchar BitCounter=8;

  Sda=1;

  do{

  Scl=0;

  _nop_ ();

  _nop_ ();

  _nop_ ();

  _nop_ ();

  Scl=1;

  _nop_ ();

  _nop_ ();

  _nop_ ();

  _nop_ ();

  if(Sda) /*如果Sda=1;*/

  temp=temp|0x01; /*temp的最低位置1*/

  else

  temp=temp&0xfe; /*否则temp的最低位清0*/

  if(BitCounter-1)

  { temp1=temp《《1;

  temp=temp1;

  }

  BitCounter--;

  }while(BitCounter);

  return(temp);

  }

  void WrToROM(uchar Data[],uchar Address,uchar Num)

  {

  uchar i;

  uchar *PData;

  PData=Data;

  for(i=0;i《Num;i++)

  {

  Start(); /*发送启动信号*/

  Send(0xa0); /*发送SLA+W*/

  Ack();

  Send(Address+i); /*发送地址*/

  Ack();

  Send(*(PData+i));

  Ack();

  Stop();

  mDelay(20);

  }

  }

  void RdFromROM(uchar Data[],uchar Address,uchar Num)

  {

  uchar i;

  uchar *PData;

  PData=Data;

  for(i=0;i《Num;i++)

  {

  Start();

  Send(0xa0);

  Ack();

  Send(Address+i);

  Ack();

  Start();

  Send(0xa1);

  Ack();

  *(PData+i)=Read();

  Scl=0;

  NoAck();

  Stop();

  }

  }

  void main()

  {

  uchar Number[4]={1,2,3,4};

  WP= 1;

  WrToROM(Number,4,4); /*将初始化后的数值写入EEPROM*/

  mDelay(20);

  Number[0]=0;

  Number[1]=0;

  Number[2]=0;

  Number[3]=0; /*将数组中的值清掉,以验证读出的数是否正确*/

  RdFromROM(Number,4,4);

  }

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分