Arduino版简单的DS1307程序

    DS1307是一款低功耗,具有56字节非失性RAM的全BCD码时钟日历实时时钟芯片,地址和数据通过两线双向的串行总线的传输,芯片可以提供秒,分,小时等信息,每一个月的天数能自动调整。并且有闰年补偿功能。

    Arduino上可以使用别人写好的库,但是我们也可以自己写一个简单的,正好拿来练练手。

    观察DS1307芯片,不难发现有SDA和SCL两个引脚,那么通信总线应该是I2C。

第一部分 I2C通信

    Arduino进行I2C总线通信时,通常需要写出以下关键程序。

//初始化

void ds1307_init()
{
  pinMode(sda,OUTPUT);
  digitalWrite(scl,HIGH);
  delayMicroseconds(5);
  digitalWrite(sda,HIGH);
  delayMicroseconds(5);
}
//启动信号

void ds1307_start()
{
  pinMode(sda,OUTPUT);
  digitalWrite(sda,HIGH);
  digitalWrite(scl,HIGH); 
  delayMicroseconds(5);
  digitalWrite(sda,LOW);
  delayMicroseconds(5);
}
//等待应答

void ds1307_waitack()
{ 
  unsigned char i=255;
  pinMode(sda,INPUT);
  digitalWrite(scl,HIGH);
  while(digitalRead(sda) && i)i--;
  delayMicroseconds(5);
  digitalWrite(scl,LOW); 
}
//停止信号

void ds1307_stop()
{
  pinMode(sda,OUTPUT);
  delayMicroseconds(2);
  digitalWrite(sda,LOW);
  delayMicroseconds(5);
  digitalWrite(scl,HIGH);
  delayMicroseconds(5);
  digitalWrite(sda,HIGH);
}
//写1字节

void ds1307_writeByte(unsigned char oneByte)
{
  pinMode(sda,OUTPUT);
  for(int i=0;i<8;i++){
    digitalWrite(scl,LOW); 
    delayMicroseconds(1);
    if(oneByte & 0x80){digitalWrite(sda,HIGH);}
    else{digitalWrite(sda,LOW);}
    delayMicroseconds(1);
    oneByte=oneByte<<1;
    digitalWrite(scl,HIGH); 
    delayMicroseconds(1);
  }
  digitalWrite(scl,LOW);
  delayMicroseconds(1);
  digitalWrite(sda,HIGH);
  delayMicroseconds(1);
}
//读1字节

unsigned char ds1307_readByte()
{  
  pinMode(sda,INPUT);
  unsigned char dat=0;
  unsigned char tmp;
  for(int i=0;i<8;i++){
    digitalWrite(scl,LOW);
    delayMicroseconds(5);
    digitalWrite(scl,HIGH);
    tmp=digitalRead(sda);
    tmp=tmp<<7-i;
    dat=dat|tmp;
    delayMicroseconds(1);
    digitalWrite(scl,LOW);
  }
  return dat;
}

第二部分 DS1307时序

一.DS1307的内部地址如下:

    00H-06H是我们需要的数据。

    二.写入的时序如下:

    启动信号-写入0xD0-等待ack-写入地址-等待ack-写入数据-等待ack-结束信号

    地址是每写一个自动加1,写到0x06以后跳回0x00

    因此程序如下:

void write_time()
{
  ds1307_init();
  ds1307_start();
  ds1307_writeByte(0xd0);
  ds1307_waitack();
  ds1307_writeByte(0x00);
  ds1307_waitack();  
  for(int i=0;i<7;i++){
    ds1307_writeByte(TIME[i]);
    ds1307_waitack();
  }
  ds1307_stop();
}

三.读取时序

  和写入差不多,但要注意2点:

1.读取的地址是跟着写入地址的,也就是说如果上面的写入地址是0x01,读取的时候也是从0x01开始读,因此可以在读取之前先进行定位。

2.应答和非应答信号是单片机发送给DS1307的。

void read_time()
{
  ds1307_start();
  ds1307_writeByte(0xd1);
  ds1307_waitack();

  TIME[0]=ds1307_readByte();
  ds1307_sendack();
  TIME[1]=ds1307_readByte();
  ds1307_sendack();
  TIME[2]=ds1307_readByte();
  ds1307_sendack();
  TIME[3]=ds1307_readByte();
  ds1307_sendack();
  TIME[4]=ds1307_readByte();
  ds1307_sendack();
  TIME[5]=ds1307_readByte();
  ds1307_sendack();  
  TIME[6]=ds1307_readByte();
  ds1307_noack();
  ds1307_stop();  
}

void ds1307_noack()
{
  pinMode(sda,OUTPUT);
  digitalWrite(scl,LOW);
  delayMicroseconds(5);
  digitalWrite(sda,HIGH);
  delayMicroseconds(2);
  digitalWrite(scl,HIGH);
  delayMicroseconds(5);
  digitalWrite(scl,LOW);
  pinMode(sda,INPUT);
}

void ds1307_sendack()
{
  pinMode(sda,OUTPUT);
  digitalWrite(scl,LOW); 
  delayMicroseconds(5);
  digitalWrite(sda,LOW);
  delayMicroseconds(2);
  digitalWrite(scl,HIGH);
  delayMicroseconds(5);
  digitalWrite(scl,LOW);
  pinMode(sda,INPUT);
}

    这样基本上就差不多了。

结尾

    其实后面还有个坑,没注意到的话程序是读不出来的,卖个关子,呵呵

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

claria029

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值