×
单片机 > 单片机程序设计 > 详情

关于51单片机模拟IIC总线的程序

发布时间:2020-05-25 发布时间:
|
下面是一个关于IIC总线的程序,用的是51单片机做控制器,对24c16的EEPROM进行数据的读写,由于51没有IIC总线接口,所以需要根据IIC的协议模拟它进行数据传输。IIC是一中同步串口总线,scl为时钟线,sda为数据线;scl为低时sda的数据允许变化,scl为高时sda的数据必须保持稳定。同一个IIC总线根据器件地址的不同可以同时对多个器件进行读写,例如可以同时接8个24c16系列的EEPROM。

 

下面的程序是一个时钟程序,当断电时将数据将保存在24c16中。重新上电后先读出24c16中存的数据,之后一直对24c16进行写操作,这样断电就可以保持最后次数据在14c16里面了。

 

对24c16系列的EEPROM写的过程:起始信号 写器件地址 应答 写地址 应答 写数据.....无应答 停止

对24c16系列的EEPROM写的过程:起始信号 写器件地址 应答 写地址 应答 重新开始 写器件+1 应答 读出数据 停止

#include
#define uchar unsigned char
sbit sda=P2^1;
sbit scl=P2^0;
sbit p1_0=P1^0;
sbit p1_1=P1^1;
sbit p1_2=P1^2;
uchar a,tt;
uchar tem=0;
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
void delay()
{ ;; }
void start()  //开始信号,scl在高电平时sda由高变低产生开始信号

 sda=1;
 delay();
 scl=1;
 delay();
 sda=0;
 delay();
}

void stop()   //停止信号,scl在高电平时sda由低变高产生停止信号

{
 sda=0;
 delay();
 scl=1;
 delay();
 sda=1;
 delay();
}

void respons()  //应答,sda为高时表示从机有应答,没有就默认应答
{
 uchar i;
 scl=1;
 delay();
 while((sda==1)&&(i<250))i++;
 scl=0;
 delay();
}

void init()//初始化定时器
{
 sda=1;
 delay();
 scl=1;
 delay();
 TMOD=0x01;
 TH0=(65536-50000)/256;
 TH0=(65536-50000)%6;
 EA=1;
 ET0=1;
 TR0=1;
 p1_1=1;
 p1_0=1;
}

void write_byte(uchar date)//写一个字节
{
 uchar i,temp;
 temp=date;


 for(i=0;i<8;i++)
 {
  temp=temp<<1;
  scl=0;
  delay();
  sda=CY;//利用了CY这个移除来写
  delay();
  scl=1;
  delay();
  scl=0;
  delay();
 }
 scl=0;
 delay();
 sda=1;
 delay();
}

uchar read_byte()//读一个字节
{
 uchar i,k;
 scl=0;
 delay();
 sda=1;  //释放sda
 delay();
 for(i=0;i<8;i++)
 {
  scl=1;
  delay(); 
  k=(k<<1)|sda;//读出来的字节存在k中
  scl=0;
  delay(); 
 }
 return k;
}

void delay1(uchar x)
{
 uchar a,b;
 for(a=x;a>0;a--) 
  for(b=110;b>0;b--);
}

void write_add(uchar address,uchar date)//写数据的整个过程

{
 start();
 write_byte(0xa0);//a0为从机器件地址,最后位为0表示写
 respons();
 write_byte(address);//要写的地址
 respons();
 write_byte(date);//要写的数据
 respons();
 stop();
}

uchar read_add(uchar address))//读数据的整个过程
{
 uchar date;
 start();
 write_byte(0xa0);
 respons();
 write_byte(address);//待读数据的地址
 respons();
 start();//由写变为读的过程需要重新执行start的过程
 write_byte(0xa1);//最后位为一表示读
 respons();
 date=read_byte();//读出数据
 stop();
 return date;
 

void main()

 
 uchar shi,ge;
 init();
 
 if(read_add(20))
 {
  tem=read_add(20);
 }
 else
 {
  tem=0;
 }
 while(1)
 {
  
  if(tem>99)
  {
    tem=0;
  }
  
  shi=tem/10;
  ge=tem; 
  p1_1=0;
  P3=table[shi];
  delay1(14);
  p1_1=1;
  p1_0=0;
  P3=table[ge];
  delay1(14);
  p1_0=1;
  }

}
void zhongd() interrupt 1 

{
 TH0=(65536-50000)/256;
    TL0=(65536-50000)%6;
    tt++;
 if(tt==20)
  {
    tt=0;
   tem++;
   write_add(20,tem);
  }
 }

关键字:51单片机  模拟IIC总线 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
如何为单片机选择合适的负载电容