这是以前做的一个项目中的一部分,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;
}
用户1599209 2014-2-7 02:24
用户1361860 2008-4-14 14:08
用户1328398 2008-4-14 11:54