原创 实时时钟DS1307的PIC程序

2008-4-13 21:47 6542 6 8 分类: MCU/ 嵌入式

这是以前做的一个项目中的一部分,ds1307的驱动程序,用PIC C语言写的,采用的单片机是PIC16F628,因为不支持硬件I2C,所以用软件模拟的i2c协议.


/**************************************************************


** FileName: i2c_protocol.h


** author: bluehacker<KernelPanicCrash at gmail.com>


** data: 2006-1-04


*************************************************************/



#ifndef __LZP_TM_I2C_H_
#define __LZP_TM_I2C_H_


void i2c_start();
void i2c_stop();
bit i2c_check_ack(void);
void i2c_send_byte(unsigned char _data);
unsigned char i2c_receive_byte(unsigned char ack);
#endif


/*********************************************************


** FileName: i2c_protocol.c


** author: bluehacker<KernelPanicCrash at gmail.com>


** Date:2006-1-04


********************************************************/


#include "common.h"
#include "delay.h"
#include "i2c_protocol.h"


/* generate a start condition*/
void i2c_start()
{
 TRISA1=0;//SDA output
 SDA=1;
 asm("nop");
 SCL=1;
  DelayUs(5);
 SDA=0;
 DelayUs(5);
 SCL=0; 
 asm("nop");
  asm("nop");
}


void i2c_stop()
{
 TRISA1=0;//SDA output
 SDA=0;
  asm("nop");
  SCL="1";
  DelayUs(5);
 SDA=1;
  DelayUs(5);
}


/*check ack*/
bit i2c_check_ack(void)
{
 
 TRISA1=0;//SDA output
 asm("nop");
 SDA=1;
 asm("nop");
 asm("nop");
 SCL=1;
  DelayUs(3);
  TRISA1=1;//SDA input
  if(SDA)/*error*/
  return 1;
 SCL=0;
 return 0;
}


void i2c_send_byte(unsigned char _data)
{
 unsigned char i;
 
 TRISA1=0;//SDA output
 for(i=0;i<8;i++)
 {
  asm("nop");
  if((_data<<i)&0x80)
   SDA=1;
  else
   SDA=0;
    asm("nop");
    SCL=1;
    DelayUs(5);
  SCL=0;
 }
}


/*receive a byte from i2c device
* Argument:
* ack---if 1,means after receive a byte, generate a '1' ack to terminate receive operation
* if 0,means after receive a byte ,generate a '0' ack(NOACK),then we can receive more bytes
*return value;
* return the byte we receive from i2c device
*/
unsigned char i2c_receive_byte(unsigned char ack)
{
 unsigned char i;
 unsigned char result="0";
 TRISA1=1;//SDA input
 SDA=1;//release SDA
 for(i=0;i<8;i++)
 {
  
    asm("nop");
    SCL=0;
    DelayUs(5);
  SCL=1;
 
    asm("nop");
    asm("nop");
   result<<=1;
    if(SDA)
     result=result+1;
  asm("nop");
  asm("nop");
 }
 SCL=0;
 TRISA1=0;//SDA output
 asm("nop");
 asm("nop");
 SDA=ack;
 
  DelayUs(5);
 SCL=1;
 
  DelayUs(5);
 SCL=0;
 asm("nop");
 return result;
}


/******************************************************


** FileName:ds1307.h


** ds1307 operation function define
** Author: Li Zheng-ping<KernelPanicCrash at gmail.com>
** date: 2006-1-19
************************************************************/


#ifndef __LZP_TM_DS1307_H__
#define __LZP_TM_DS1307_H__


#define WR1307  0xD0
#define RD1307  0xD1


void  init_ds1307( unsigned char _data);
bit read_ds1307(unsigned char addr,unsigned char *_data);
bit write_ds1307(unsigned char addr, unsigned char _data);
bit get_cmos_time(unsigned char *buf, unsigned char flag);
bit set_cmos_time(unsigned char *buf);
#endif


/******************************************************


** FileName: ds1307.c


**ds1307 related function implementation,(ds1307 driver)
* *Author: Li Zheng-ping<KernelPanicCrash at gmail.com>
* *date: 2006-1-19
*******************************************************/


#include "common.h"
#include "i2c_protocol.h"
#include "ds1307.h"
///////////////////////////////////////////////////////////////////////////
/* read a byte data from ds1307 RAM
* Arguments:
* addr----the address of RAM we need read
* *_data----return the data contained in "addr" RAM
*return value:
* 0----sucess,the *_data contains the data we need
* 1----failed, there are error(s) occurred
*/
bit read_ds1307(unsigned char addr,unsigned char *_data)
{
 
 i2c_start();


 /*send WR1307 to ds1307,select ds1307 work in write mode*/
 i2c_send_byte(WR1307);
 /*check the ds1307's ACK*/
 if(i2c_check_ack())//error
  return 1;
 
 //send address to ds1307, set the point to this address
 i2c_send_byte(addr);
 
 /*check the ds1307's ACK*/
 if(i2c_check_ack())//error
  return 1;
 /*stop*/
// i2c_stop();
/*restart*/
 i2c_start(); 


/*send RD1307 to select ds1307 to read mode*/
 i2c_send_byte(RD1307);
 /*check the ds1307's ACK*/
 if(i2c_check_ack())//error
  return 1;
/*now receive a byte from "addr"*/
 *_data=i2c_receive_byte(1);
 i2c_stop();
 return 0;
}


/* write data(usually time) to ds1307's register or RAM*/
bit write_ds1307(unsigned char addr, unsigned char _data)
{
 i2c_start();
 i2c_send_byte(WR1307);
 /*check the ds1307's ACK*/
 if(i2c_check_ack())//error
  return 1;
 i2c_send_byte(addr);
 /*check the ds1307's ACK*/
 if(i2c_check_ack())//error
  return 1;
 i2c_send_byte(_data);
 /*check the ds1307's ACK*/
 if(i2c_check_ack())//error
  return 1;
 i2c_stop();
 return 0;
}


/* initialize ds1307 real time clock*/


void init_ds1307(unsigned char i)
{
   unsigned char tmp;
  
  i2c_start();
  i2c_send_byte(WR1307);
  i2c_send_byte(0x07);
  i2c_send_byte(i);
  i2c_stop(); 
  read_ds1307(0x02,&tmp);
  tmp&=0xBF;
  write_ds1307(0x02,tmp);//select 24 hours mode
  read_ds1307(0x00,&tmp);
  tmp&=0x7f;
  write_ds1307(0x00,tmp);
}


/* get cmos time
* time format:
* buf[0]--year,
* buf[1]---month
* buf[2]---date;
* buf[3]---if flag="1", day of week, otherwise, hour
* buf[4]--- if flag="1", hour;otherwise, minute
* byf[5]---if flag="1", minute;otherwise second
* buf[6]---if flag="1",second
*return:
* 1---failed
* 0--success
*/
bit get_cmos_time(unsigned char *buf, unsigned char flag)
{
 unsigned char i;
 
 for(i=0;i<3;i++)
   {
    if(read_ds1307(6-i,&buf))
     return 1;//failed
  if(read_ds1307(2-i,&buf[3+i+flag]))
   return 1;//failed
 }
 if(flag)
 {
  if(read_ds1307(3,&buf[3]))
   return 1;
 }
 return 0;
}



bit set_cmos_time(unsigned char *buf)
{
 unsigned char i;
 
 for(i=0;i<7;i++)
 {
  if(write_ds1307(i,buf[6-i]))
   return 1;
 }
 return 0;
}
  

PARTNER CONTENT

文章评论2条评论)

登录后参与讨论

用户1599209 2014-2-7 02:24

挺好。。。。。。

用户1361860 2008-4-14 14:08

谢谢支持

用户1328398 2008-4-14 11:54

投一票,希望博主能拿奖
相关推荐阅读
用户1361860 2012-06-28 23:44
Nicrosystem Freescale Kinetis教程---SDHC
这是研究生翻译的SDHC的中文文档,里面很多句子不通,但我现在没时间去修改了。先放出来,应该还是会有一点作用  ...
用户1361860 2012-06-26 12:39
Nicrosystem Freescale Kinetis教程--低功耗定时器
Freescale Kinetis内部集成了一个独特的低功耗定时器,它可以在系统处于低功耗模式下,仍然以极低功耗运行,可以用于在适当时候唤醒系统进入正常工作模式  ...
用户1361860 2012-06-24 22:11
Nicrosystem Freescale Kinetis教程----RTC实时时钟
Nicrosystem的飞思卡尔kinetis教程之片上RTC  ...
用户1361860 2012-06-22 10:21
TI C2000微控制器指南
这是官方的C2000的介绍,C2000做电机控制那是业界最好的。  ...
用户1361860 2012-06-20 23:52
Nicrosystem Freescale Kinetis教程--PIT定时器教程
这是PIT定时器的教程,PIT是 Kinetis支持的另一种定时器,相对于上一讲的flextimer要简单。 今晚赶到北京,到宾馆发一篇博客  ...
用户1361860 2012-06-19 13:15
Nicrosystem Freescale Kinetis教程--Flextimer教程
Kinetis的Flextimer定时器教程 kinetis集成了众多功能各异的定时器,flextimer是其中最为复杂的一个  ...
EE直播间
更多
我要评论
2
6
关闭 站长推荐上一条 /3 下一条