hello,
Please help me on my problem, i made a code for DS1307 with using MPLAB v8.50,
it should display/save time and date on the EEPROM, but its not working very well,
Please help me to debug my code..
the output is like this.
Here are the codes:
main.c
i2c.c
i2c.h
Please help me guys.
Thanks in advance...
Please help me on my problem, i made a code for DS1307 with using MPLAB v8.50,
it should display/save time and date on the EEPROM, but its not working very well,
Please help me to debug my code..
the output is like this.
Here are the codes:
main.c
Code:
//Sample code for
//DS1307 RTC Interfacing with PIC16F877A
//Coded by punkky@gmail.com
//Compiler: mikroC 8.0.0
//http://picnote.blogspot.com
//05/01/2009
//Use with your own risk
#include<pic.h>
#include"i2c.h"
unsigned short read_ds1307(unsigned short address );
void write_ds1307(unsigned short address,unsigned short w_data);
unsigned short sec;
unsigned short minute;
unsigned short hour;
unsigned short day;
unsigned short date;
unsigned short month;
unsigned short year;
unsigned short data;
char time[9];
char ddate[11];
unsigned char BCD2UpperCh(unsigned char bcd);
unsigned char BCD2LowerCh(unsigned char bcd);
void write_eeprom(unsigned char adr, unsigned char d);
unsigned char read_eeprom(unsigned char adr);
void write_eeprom_string(unsigned char adr, unsigned char eeprom[]);
void main(){
//I2C_Init(100000); //DS1307 I2C is running at 100KHz
PORTB = 0;
TRISB = 0; // Configure PORTB as output
TRISC = 0xFF;
//Lcd_Init(&PORTB); // Initialize LCD connected to PORTB
//Lcd_Cmd(//Lcd_CLEAR); // Clear display
//Lcd_Cmd(//Lcd_CURSOR_OFF); // Turn cursor off
//Lcd_Out(1, 1, "TIME:");
//Lcd_Out(2, 1, "DATE:");
//Set Time
write_ds1307(0,0x80); //Reset second to 0 sec. and stop Oscillator
write_ds1307(1,0x10); //write min 27
write_ds1307(2,0x01); //write hour 14
write_ds1307(3,0x02); //write day of week 2:Monday
write_ds1307(4,0x05); // write date 17
write_ds1307(5,0x01); // write month 6 June
write_ds1307(6,0x09); // write year 8 --> 2008
write_ds1307(7,0x10); //SQWE output at 1 Hz
write_ds1307(0,0x00); //Reset second to 0 sec. and start Oscillator
for(int y=0;y<0x0F;y++){;}
while(1)
{
sec=read_ds1307(0); // read second
minute=read_ds1307(1); // read minute
hour=read_ds1307(2); // read hour
day=read_ds1307(3); // read day
date=read_ds1307(4); // read date
month=read_ds1307(5); // read month
year=read_ds1307(6); // read year
time[0] = BCD2UpperCh(hour);
time[1] = BCD2LowerCh(hour);
time[2] = ':';
time[3] = BCD2UpperCh(minute);
time[4] = BCD2LowerCh(minute);
time[5] = ':';
time[6] = BCD2UpperCh(sec);
time[7] = BCD2LowerCh(sec);
time[8] = '\0';
ddate[0] = BCD2UpperCh(date);
ddate[1] = BCD2LowerCh(date);
ddate[2] ='/';
ddate[3] = BCD2UpperCh(month);
ddate[4] = BCD2LowerCh(month);
ddate[5] ='/';
ddate[6] = '2';
ddate[7] = '0';
ddate[8] = BCD2UpperCh(year);
ddate[9] = BCD2LowerCh(year);
ddate[10] = '\0';
write_eeprom_string(0x00,time);
write_eeprom_string(0x40,ddate);
//Lcd_Out(1,6,time);
//Lcd_Out(2,6,ddate);
//Delay_ms(50);
for(int x=0;x<=0xFF;x++) {;}
}
}
unsigned short read_ds1307(unsigned short address)
{
i2c_Start();
i2c_WriteTo(0xd0); //address 0x68 followed by direction bit (0 for write, 1 for read) 0x68 followed by 0 --> 0xD0
i2c_WriteTo(address);
i2c_Restart();
i2c_WriteTo(0xd1); //0x68 followed by 1 --> 0xD1
data=i2c_read(0);
i2c_Stop();
return(data);
}
unsigned char BCD2UpperCh(unsigned char bcd)
{
return ((bcd >> 4) + '0');
}
unsigned char BCD2LowerCh(unsigned char bcd)
{
return ((bcd & 0x0F) + '0');
}
void write_ds1307(unsigned short address,unsigned short w_data)
{
i2c_Start(); // issue I2C start signal
//address 0x68 followed by direction bit (0 for write, 1 for read) 0x68 followed by 0 --> 0xD0
i2c_WriteTo(0xD0); // send byte via I2C (device address + W)
i2c_WriteTo(address); // send byte (address of DS1307 location)
i2c_WriteTo(w_data); // send data (data to be written)
i2c_Stop(); // issue I2C stop signal
}
unsigned char read_eeprom(unsigned char adr)
{ EEADR=adr;
RD=1; // set the read bit
return(EEDATA);
}
void write_eeprom(unsigned char adr, unsigned char d)
{ EEADR = adr;
EEDATA = d;
WREN = 1; // write enable
EECON2 = 0x55; // protection sequence
EECON2 = 0xaa;
WR = 1; // begin programming sequnce
for(int x=0;x<0xFF;x++){;} // delay
WREN = 0; // disable write enable
}
void write_eeprom_string(unsigned char adr, unsigned char eeprom[])
{ for(int x=0;x<13;x++)
{ if(eeprom[x]!=0)
{ write_eeprom(adr,eeprom[x]);
adr=adr+1;
}
else
x=15;
}
}
i2c.c
Code:
#include <htc.h>
#include "i2c.h"
/*
* I2C functions for HI-TECH PIC C - master mode only
*/
/*
* TIMING - see Philips document: THE I2C-BUS SPECIFICATION
*/
/*
* Send stop condition
* - data low-high while clock high
*/
void
i2c_Stop(void)
{
/* don't assume SCL is high on entry */
SDA_LOW(); /* ensure data is low first */
SCL_HIGH();
__delay_us(I2C_TM_DATA_SU);
SCL_DIR = I2C_INPUT; /* float clock high */
__delay_us(I2C_TM_STOP_SU);
SDA_HIGH(); /* the low->high data transistion */
__delay_us(I2C_TM_BUS_FREE); /* bus free time before next start */
SDA_DIR = I2C_INPUT; /* float data high */
return;
}
/*
* Send (re)start condition
* - ensure data is high then issue a start condition
* - see also i2c_Start() macro
*/
void
i2c_Restart(void)
{
SCL_LOW(); /* ensure clock is low */
SDA_HIGH(); /* ensure data is high */
__delay_us(I2C_TM_DATA_SU);
SCL_DIR = I2C_INPUT; /* clock pulse high */
__delay_us(I2C_TM_SCL_HIGH);
SDA_LOW(); /* the high->low transition */
__delay_us(I2C_TM_START_HD);
return;
}
/*
* Send a byte to the slave
* - returns true on error
*/
unsigned char
i2c_SendByte(unsigned char byte)
{
signed char i;
for(i=7; i>=0; i--)
{
SCL_LOW(); /* drive clock low */
/* data hold time = 0, send data now */
SDA_DIR = ((byte>>i)&0x01);
if ((byte>>i)&0x01) { /* bit to send */
SDA_HIGH();
}else {
SDA_LOW();
}
__delay_us(I2C_TM_DATA_SU);
SCL_DIR = I2C_INPUT; /* float clock high */
if(i2c_WaitForSCL()) /* wait for clock release */
return TRUE; /* bus error */
__delay_us(I2C_TM_SCL_HIGH); /* clock high time */
}
return FALSE;
}
/*
* send an address and data direction to the slave
* - 7-bit address (lsb ignored)
* - direction (FALSE = write )
*/
unsigned char
i2c_SendAddress(unsigned char address, unsigned char rw)
{
return i2c_SendByte(address | (rw?1:0));
}
/*
* Check for an acknowledge
* - returns ack or ~ack, or ERROR if a bus error
*/
signed char
i2c_ReadAcknowledge(void)
{
unsigned char ack;
SCL_LOW(); /* make clock is low */
SDA_DIR = I2C_INPUT; /* disable data line - listen for ack */
__delay_us(I2C_TM_SCL_TO_DATA); /* SCL low to data out valid */
SCL_DIR = I2C_INPUT; /* float clock high */
__delay_us(I2C_TM_DATA_SU);
ack = SDA; /* read the acknowledge */
/* wait for slave to release clock line after processing byte */
if(i2c_WaitForSCL())
return I2C_ERROR;
return ack;
}
/*
* Read a byte from the slave
* - returns the byte, or I2C_ERROR if a bus error
*/
int
i2c_ReadByte(void)
{
unsigned char i;
unsigned char byte = 0;
for(i=0; i<8; i++)
{
SCL_LOW(); /* drive clock low */
__delay_us(I2C_TM_SCL_LOW); /* min clock low period */
SDA_DIR = I2C_INPUT; /* release data line */
SCL_DIR = I2C_INPUT; /* float clock high */
if(i2c_WaitForSCL())
return I2C_ERROR;
__delay_us(I2C_TM_SCL_HIGH);
byte = byte << 1; /* read the next bit */
byte |= SDA;
}
return (int)byte;
}
/*
* Send an (~)acknowledge to the slave
* - status of I2C_LAST implies this is the last byte to be sent
*/
void
i2c_SendAcknowledge(unsigned char status)
{
SCL_LOW();
if ( status & 0x01) {
SDA_LOW(); /* drive line low -> more to come */
}else {
SDA_HIGH();
}
__delay_us(I2C_TM_DATA_SU);
SCL_DIR = I2C_INPUT; /* float clock high */
__delay_us(I2C_TM_SCL_HIGH);
return;
}
/*
* Send a byte to the slave and acknowledges the transfer
* - returns I2C_ERROR, ack or ~ack
*/
signed char
i2c_PutByte(unsigned char data)
{
if(i2c_SendByte(data))
return I2C_ERROR;
return i2c_ReadAcknowledge(); /* returns ack, ~ack */
}
/*
* Get a byte from the slave and acknowledges the transfer
* - returns true on I2C_ERROR or byte
*/
int
i2c_GetByte(unsigned char more)
{
int byte;
if((byte = i2c_ReadByte()) == I2C_ERROR)
return I2C_ERROR;
i2c_SendAcknowledge(more);
return byte;
}
/*
* Send an array of bytes to the slave and acknowledges the transfer
* - returns number of bytes not successfully transmitted
*/
int
i2c_PutString(const unsigned char *str, unsigned char length)
{
signed char error;
while(length)
{
if((error = i2c_PutByte(*str)) == I2C_ERROR)
return -(int)length; /* bus error */
else
if(error)
return (int)length; /* non acknowledge */
str++;
length--;
}
return FALSE; /* everything OK */
}
/*
* Reads number bytes from the slave, stores them at str and acknowledges the transfer
* - returns number of bytes not successfully read in
*/
unsigned char
i2c_GetString(unsigned char *str, unsigned char number)
{
int byte;
while(number)
{
if((byte = i2c_GetByte(number-1)) == I2C_ERROR)
return number; /* bus error */
else
*str = (unsigned char)byte;
str++;
number--;
}
return FALSE; /* everything OK */
}
/*
* Opens communication with a device at address. mode
* indicates I2C_READ or I2C_WRITE.
* - returns TRUE if address is not acknowledged
*/
unsigned char
i2c_Open(unsigned char address, unsigned char mode)
{
i2c_Start();
i2c_SendAddress(address, mode);
if(i2c_ReadAcknowledge())
return TRUE;
return FALSE;
}
/*
* wait for the clock line to be released by slow slaves
* - returns TRUE if SCL was not released after the
* time out period.
* - returns FALSE if and when SCL released
*/
unsigned char
i2c_WaitForSCL(void)
{
/* SCL_DIR should be input here */
if(!SCL)
{
__delay_us(I2C_TM_SCL_TMO);
/* if the clock is still low -> bus error */
if(!SCL)
return TRUE;
}
return FALSE;
}
void
i2c_Free()
{
unsigned char ucI;
SDA_DIR=I2C_INPUT;
for(ucI=0;ucI!=9;ucI++)
{
SCL_HIGH();
__delay_us(5);
SCL_LOW();
__delay_us(5);
}
}
unsigned char i2c_read(unsigned char ucAdr)
{
unsigned char ucDat;
if (i2c_ReadFrom(ucAdr)==0)
{
ucDat=i2c_GetByte(I2C_MORE);
i2c_Stop();
}
return(ucDat);
}
i2c.h
Code:
#ifndef _I2C_H_
#define _I2C_H_
/*
* SDA (data) and SCL (clock) bits
*
* Special note!!!
*
* If the clock and data lines are in the same port, you will need
* to beware of the Read/Modify/Write issue in the PIC - since
* a bit set or clear on any one bit in a port will read and write
* back all other bits.
*/
#ifndef _XTAL_FREQ
// Unless specified elsewhere, 4MHz system frequency is assumed
#define _XTAL_FREQ 4000000
#endif
/* Uncomment the next line to use the PIC's SSP Module*/
#define I2C_MODULE 1
#ifdef I2C_MODULE
/* I2C module uses PORT C */
#define SCL RC3 /* clock on port C bit 2 */
#define SCL_DIR TRISC3
#define SDA RC4 /* data on port C bit 1 */
#define SDA_DIR TRISC4
#define I2CTRIS TRISC
#define MASTER_MODE 0B1011 /* I2C firmware controlled Master Mode (slave idle) */
#define SSPMode(val) SSPCON &=0xF0; SSPCON|=(val & 0xf)
#else
/* Change port as required - defaults to port b */
#define SCL RB2 /* clock on port B bit 2 */
#define SCL_DIR TRISB2
#define SDA RB1 /* data on port B bit 1 */
#define SDA_DIR TRISB1
#define I2CTRIS TRISB
#endif
#define M_SDA_INP 0x02
#define M_SDA_OUT 0xFD
#define M_SCL_INP 0x04
#define M_SCL_OUT 0xFB
#define I2C_INPUT 1 /* data direction input */
#define I2C_OUTPUT 0 /* data direction output */
#define I2C_READ 0x01 /* read bit used with address */
#define I2C_WRITE 0x00 /* write bit used with address */
#define FALSE 0
#define TRUE !FALSE
#define I2C_ERROR (-1)
#define I2C_LAST FALSE /* SendAck: no more bytes to send */
#define I2C_MORE TRUE /* SendAck: more bytes to send */
#define i2c_Start() i2c_Restart()
#define i2c_WriteTo(address) i2c_Open((address), I2C_WRITE)
#define i2c_ReadFrom(address) i2c_Open((address), I2C_READ)
#ifdef I2C_MODULE
#define SCL_HIGH() SCL_DIR = I2C_INPUT
#define SCL_LOW() SCL_DIR = I2C_OUTPUT
#define SDA_HIGH() SDA_DIR = I2C_INPUT
#define SDA_LOW() SDA_DIR = I2C_OUTPUT
#else
#define SCL_HIGH() SCL = 1; SCL_DIR = I2C_OUTPUT
#define SCL_LOW() SCL = 0; SCL_DIR = I2C_OUTPUT
#define SDA_HIGH() SDA = 1; SDA_DIR = I2C_OUTPUT
#define SDA_LOW() SDA = 0; SDA_DIR = I2C_OUTPUT
#endif
/*
* Timings for the i2c bus. Times are rounded up to the nearest
* micro second.
*/
#define I2C_TM_BUS_FREE 5
#define I2C_TM_START_SU 5
#define I2C_TM_START_HD 4
#define I2C_TM_SCL_LOW 5
#define I2C_TM_SCL_HIGH 4
#define I2C_TM_DATA_SU 1
#define I2C_TM_DATA_HD 0
#define I2C_TM_SCL_TO_DATA 4 /* SCL low to data valid */
#define I2C_TM_STOP_SU 4
#define I2C_TM_SCL_TMO 10 /* clock time out */
extern signed char i2c_ReadAcknowledge(void);
extern unsigned char i2c_SendAddress(unsigned char, unsigned char);
extern unsigned char i2c_SendByte(unsigned char);
extern int i2c_ReadByte(void);
extern void i2c_Restart(void);
extern void i2c_Stop(void);
extern void i2c_SendAcknowledge(unsigned char);
extern signed char i2c_PutByte(unsigned char);
extern int i2c_GetByte(unsigned char);
extern unsigned char i2c_Open(unsigned char, unsigned char);
extern unsigned char i2c_GetString(unsigned char *, unsigned char);
extern int i2c_PutString(const unsigned char *, unsigned char);
extern unsigned char i2c_WaitForSCL(void);
extern void i2c_Free(void);
extern unsigned char i2c_read(unsigned char);
#endif /* _I2C_H_ */
Please help me guys.
Thanks in advance...