Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

My RTC is ds1307 not work

Status
Not open for further replies.
I guess it depends on the library functions you use, in AVR I have a library that uses tw_write(1); for write with acknowledge and tw_write(0); for write with Nak so there is no need for separate ack/nak

Maybe your functions already use acknowledge , I don't know.

If it is incrementing to 25,26,27 then you are not reading the correct value,I don't see how the hour becomes higher than 23.

The strange part is that it works fine in proteus and I can't explain that, this seems to imply that there is a hardware problem.
Is your i2c operating in a proper frequency , maybe you can try with a lower clock to see if it helps.
You said the but resistors are in place and the battery pin is grounded (?)

How exactly do you read these 25..26 values?
what setting do you apply to hour so that you can get that?
Do you set it to 23:59 and wait to increment and you see 24:00?
 

Maybe your functions already use acknowledge , I don't know.
I think "I2CSend()" function does not include acknowledge as well as others

Code:
void I2CSend(unsigned char dat){
        SSPBUF = dat;    		
        while(BF);       		
        I2CWait();       		
}


Do you set it to 23:59 and wait to increment and you see 24:00?
Yes I did it then 23:59 change to 24:00 and if I set 24:59 change to 25:00
 

I'm not sure that you read the data correctly , after reading the memory in address 2 you have to mask the two bits on the front and then use b5:4 for the first digit and b3:0 for the second (24H mode)

can you post your code?
 
  • Like
Reactions: PA3040

    PA3040

    Points: 2
    Helpful Answer Positive Rating
Dear Alex

Now hours is working correctly
now I am working with day month and year

Code:
#include <htc.h>
#define _XTAL_FREQ 4000000 // 4 MHz clock 

__CONFIG(0X3F39);
#define LCD_EN RB3
#define	LCD_RS RB5
#define	LCD_RW RB4
#define LCD_DATA	PORTD
#define	LCD_STROBE()	((LCD_EN = 1),(LCD_EN=0))
unsigned char date [5] = {'D','a','t','e',':'};
unsigned char time [5] = {'T','i','m','e',':'};
//unsigned char time [5] = {'T','i','m','e',':'};


unsigned char I2CData[8]= {0x00,0x01,0x40,0x03,0x04,0x05,0x06,0x07};
unsigned I2CInitval  [8]= {0x55,0x59,0x23,0x29,0x29,0x12,0x12,0x12};
unsigned char tmp;
unsigned char i;


void I2CInit(void){
        TRISC3 = 1;      	/* SDA and SCL as input pin */
        TRISC4 = 1;      	/* these pins can be configured either i/p or o/p */
        SSPSTAT |= 0x80; 	/* Slew rate disabled */
        SSPCON = 0x28;   	/* SSPEN = 1, I2C Master mode, clock = FOSC/(4 * (SSPADD + 1)) */
        SSPADD = 0x28;    	/* 100Khz @ 4Mhz Fosc */
}

void I2CStart(){
        SEN = 1;         	/* Start condition enabled */
        while(SEN);      	/* automatically cleared by hardware */
                     		/* wait for start condition to finish */
}

void I2CStop(){
        PEN = 1;         	/* Stop condition enabled */
        while(PEN);      	/* Wait for stop condition to finish */
                     		/* PEN automatically cleared by hardware */
}

void I2CRestart(){
        RSEN = 1;        	/* Repeated start enabled */
        while(RSEN);     	/* wait for condition to finish */
}

void I2CAck(){
        ACKDT = 0;       	/* Acknowledge data bit, 0 = ACK */
        ACKEN = 1;       	/* Ack data enabled */
        while(ACKEN);    	/* wait for ack data to send on bus */
}

void I2CNak(){
        ACKDT = 1;       	/* Acknowledge data bit, 1 = NAK */
        ACKEN = 1;       	/* Ack data enabled */
        while(ACKEN);    	/* wait for ack data to send on bus */
}

void I2CWait(){
        while ( ( SSPCON2 & 0x1F ) || ( SSPSTAT & 0x04 ) );		/* wait for any pending transfer */

}

void I2CSend(unsigned char dat){
        SSPBUF = dat;    		/* Move data to SSPBUF */
        while(BF);       		/* wait till complete data is sent from buffer */
        I2CWait();       		/* wait for any pending transfer */
}

unsigned char I2CRead(void){
        unsigned char temp;
								/* Reception works if transfer is initiated in read mode */
        RCEN = 1;        		/* Enable data reception */
        while(!BF);      		/* wait for buffer full */
        temp = SSPBUF;   		/* Read serial buffer and store in temp register */
        I2CWait();       		/* wait to check any pending transfer */
        return temp;     		/* Return the read data from bus */	
}

void lcddata(unsigned char value)
	{
LCD_DATA = value;
LCD_RS = 1; 
LCD_RW = 0;
LCD_EN = 1;
__delay_ms (1);
LCD_EN = 0;

	}

void lcdcmd(unsigned char value)
	{
LCD_DATA = value;
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 1;
__delay_ms (1);
LCD_EN = 0;
	}
void bcdToascii(unsigned char value){

	tmp = value;
	tmp = tmp & 0xf0;
	tmp = tmp >> 4;
	tmp = tmp | 0x30;
	lcddata(tmp);
	tmp = value;
	tmp = tmp & 0x0f;
	tmp = tmp | 0x30;
	lcddata(tmp);

}

void display (){
lcdcmd(0x80);
for (char i=0;i<5;i++)
			{
		lcddata(time[i]);
			}
	bcdToascii(I2CData[2]);
	lcddata('-');
	bcdToascii(I2CData[1]);
	lcddata('-');
	bcdToascii(I2CData[0]);
	
	lcdcmd(0xc0);
for (char j=0;j<5;j++)
			{
		lcddata(date[j]);
			}
	bcdToascii(I2CData[3]);
	lcddata('-');
	bcdToascii(I2CData[4]);
	lcddata('-');	
	bcdToascii(I2CData[5]);
	bcdToascii(I2CData[6]);
}
void lcd_init(){
//TRISC	=1;
TRISD	= 0;
TRISB	= 0;
LCD_EN =0;
__delay_ms(175);
lcdcmd(0x38);
__delay_ms(175);
lcdcmd(0x0e);
__delay_ms(15);
lcdcmd(0x01);
__delay_ms(10);
lcdcmd(0x06);
__delay_ms(10);
lcdcmd(0x80);
__delay_ms(10);
lcdcmd(0x0c);
__delay_ms(10);
				}


void I2Cwrite(){
											/* Initialize I2C Port */
 		I2CStart();						/* Send Start condition */
        I2CSend(0xD0);					/* Send DS1307 slave address with write operation */
        I2CSend(0x00);						/* Send subaddress 0x00, we are writing to this location */
			for(i=0;i<8;i++) {			/* Loop to write 8 bytes */
            	I2CSend(I2CInitval[i]);							/* send I2C data one by one */			
        }
			I2CStop();						/* Send a stop condition - as transfer finishes */
}

void I2Cread(){
		for(i=0;i<8;i++){
        I2CStart();
		I2CSend(0xD0);						/* Send slave address with write */ /* Send address for dummy write operation *//* this address is actually where we are going to read from */					       						       
        I2CSend(0x00);							/* Send a repeated start, after a dummy write to start reading */
        I2CRestart();
        I2CSend(0xD1);
		//I2CAck();							/* send slave address with read bit set */
  				
				//I2CAck();
      			I2CData[i] = I2CRead();			/* read a byte */								/* ACK if its not the last byte to read */             
        }
			//I2CNak();
		 	I2CStop();								/* Send stop */
}


void main(){        
        I2CInit();
        lcd_init();       
		I2Cwrite();
		
while(1){
		
        I2Cread();
        
        				
		display();
       


}
}

This is something additinally to this
Can you have experiencing with HMC5883L (Three-Axis Digital Compass)
This IC does not existing in the Protues
Please help
 

I haven't used any accelerometer device (or compass).

So from what I see in your code you don't use any ACK or NAK at all but this is part of the sequence to read/write so I'm not sure what you are doing wrong and it only works without these.

I found this example that is very similar to your code and they use ACK and NAK (at least for reading) https://www.8051projects.net/i2c-twi-tutorial/pic-i2c-code-example.php
 
  • Like
Reactions: PA3040

    PA3040

    Points: 2
    Helpful Answer Positive Rating
Dear alex,
Thanks for reply
My codes similar to this codes because before I write codes, I followed this site
I don't know why if I insert ack and Nack result become mess and strange part is it is working fine without Ack and Nack

and you can see I2Cwrite() function is working while incrementing address pointer automatically
Code:
void I2Cwrite(){
											
 		I2CStart();						
        I2CSend(0xD0);					
        I2CSend(0x00);						
			for(i=0;i<8;i++) {			
            	I2CSend(I2CInitval[i]);										
        }
			I2CStop();						
}

But correct I2CRead() function should be as follows but it does not work well
Code:
void I2Cread(){
		
        I2CStart();
		I2CSend(0xD0);										       						       
        I2CSend(0x00);							
        I2CRestart();
        I2CSend(0xD1);
						
  				
				for(i=0;i<8;i++){
      			I2CData[i] = I2CRead();									           
        }
		
		 	I2CStop();								
}

Therefore I modified I2CRead() function as follows then it is working fine

Code:
void I2Cread(){
		[COLOR="#FF0000"]for(i=0;i<8;i++){[/COLOR]
        I2CStart();
		I2CSend(0xD0);										       						       
        I2CSend(0x00);							
        I2CRestart();
        I2CSend(0xD1);
						
  				
			
      			I2CData[i] = I2CRead();										            
        }
		
		 	I2CStop();								
}

As I know in the I2Cread() function the address pointer does not increment am I correct
 
Last edited:

Normally the ACK is used in both write and read, if something goes wrong in the data transmition then you will get no ACK

1. Slave Receiver Mode (Write Mode): Serial data and clock are received through SDA and SCL. After
each byte is received an acknowledge bit is transmitted. START and STOP conditions are recognized
as the beginning and end of a serial transfer. Hardware performs address recognition after reception of
the slave address and direction bit (see Figure 4). The slave address byte is the first byte received
after the master generates the START condition. The slave address byte contains the 7-bit DS1307
address, which is 1101000, followed by the direction bit (R/W), which for a write is 0. After receiving and
decoding the slave address byte, the DS1307 outputs an acknowledge on SDA
. After the DS1307
acknowledges the slave address + write bit, the master transmits a word address to the DS1307. This
sets the register pointer on the DS1307, with the DS1307 acknowledging the transfer. The master can
then transmit zero or more bytes of data with the DS1307 acknowledging each byte received. The
register pointer automatically increments after each data byte are written. The master will generate a
STOP condition to terminate the data write.

2. Slave Transmitter Mode (Read Mode): The first byte is received and handled as in the slave receiver
mode. However, in this mode, the direction bit will indicate that the transfer direction is reversed. The
DS1307 transmits serial data on SDA while the serial clock is input on SCL. START and STOP
conditions are recognized as the beginning and end of a serial transfer (see Figure 5). The slave
address byte is the first byte received after the START condition is generated by the master. The slave
address byte contains the 7-bit DS1307 address, which is 1101000, followed by the direction bit (R/W),
which is 1 for a read. After receiving and decoding the slave address the DS1307 outputs an
acknowledge on SDA
. The DS1307 then begins to transmit data starting with the register address
pointed to by the register pointer. If the register pointer is not written to before the initiation of a read
mode the first address that is read is the last one stored in the register pointer. The register pointer
automatically increments after each byte are read. The DS1307 must receive a Not Acknowledge to
end a read
.

It is also shown in the protocol
DS1307_ACK-NAK.gif

I'm not sure about the address , the datasheet says "The register pointer automatically increments after each byte are read" and I'm not sure is this happens without ACK too.
Did you get the correct result without ACK?
Is so then it increments , or your master (pic hardware) sends ACK without you knowing it.
 
  • Like
Reactions: PA3040

    PA3040

    Points: 2
    Helpful Answer Positive Rating
Dear Alex
Thank you so much for continuous help
However my RTC is working without Ack and NAck but little confusing with Year digits, normally it should be four digits but I could find out only two digits
Please advice
 
Last edited:

04h has the date
05h the month
06h the year

what exactly is the problem, if you read the three address you will get 6 digits

Code:
I2CStart();
I2CSend(0xD0);
I2CSend(0x4);
I2CRestart();
I2CSend(0xD1);
I2CData[4] = I2CRead();
I2CData[5] = I2CRead();
I2CData[6] = I2CRead();

Each byte has two digits ,the first one are the four MSB (0b00000000)and the second the four LSB (0b00000000)

- - - Updated - - -

I think you mean the date format, the year is with two digits

01/01/00 00:00:00 (MM/DD/YY HH:MM:SS)
 
  • Like
Reactions: PA3040

    PA3040

    Points: 2
    Helpful Answer Positive Rating
Dear Alex
Thanks for reply
I thought that year has four digits, now I can continue it
Thanks again and again
 

Dear Alex
I am very worry about that my I2C codes because, when I insert the "I2CAck();" function to I2C read routing it becomes mess. still I can not find out the reason but everything is working fine
Any Help if you free
Thanks in advance
 

Unfortunately this is a part I can't help in because I have never used a PIC .
In AVR the code with ACK/Nack works fine but I don't know what you should do with PIC to make it work with ACK/Nack
 

I have been watching this thread with keen interest since it started.

Because every time I tried to interface using DS1307 with 16F877 using MicroC Pro I2C library in the past, I have faced some unusual problems.
But interfacing the same micro with same RTC chip using MicroC Pro Software I2C library worked smoothly every time.
 

Dear All,
My next step is set the time and date while it is running
Any one can please help the algorithm that I need to follow-up
Please advice

- - - Updated - - -

Dear papunblg,
Thanks for reply
Dear papunblg I can not clear what you are going to printed out
Thanks
 

There is no special algorithm , just make sure that you don't set to 1 the CH bit in address 0 because it stops the counter.
Also don't change (or change) the 12/24H format

Code:
I2CStart();
I2CSend(0xD0);
I2CSend(0x0);
I2CSend(sec);
I2CSend(min);
I2CSend(hour);
I2CStop();

Code:
I2CStart();
I2CSend(0xD0);
I2CSend(0x4);
I2CSend(date);
I2CSend(month);
I2CSend(year);
I2CStop();
 

Dear Alex
Thanks for reply
Sorry I could not say clearly what I need is?
actually I need adjust the time and date using externally used micro switch
Please advice
 

A part from the interface initialization and any existing "bugs" particular to a device, much of the mechanics of the I2C interface are essentially consistent from one device to another.

If you need inspiration for composing an I2C library of routines, you may want to reference the Hi-Tech routines for the PIC18. The library is quite extensive, with routines particular to devices which feature two I2C interfaces and handling various EEPROM devices, however the basic routines, read and write, are quite easy to understand and include acknowledgment signalling.

i2c_read.c
Code:
#include <pic18.h>
#include <peripheral/i2c.h>

/********************************************************************
*     Function Name:    ReadI2C                                     *
*     Return Value:     contents of SSPBUF register                 *
*     Parameters:       void                                        *
*     Description:      Read single byte from I2C bus.              *
********************************************************************/
#if defined (_I2C_V1)
unsigned char ReadI2C( void )
{
  RCEN_x = 1;           // enable master for 1 byte reception
  while ( !BF_x );      // wait until byte received  
  return ( SSPBUF );              // return with read byte 
}
#endif

#if defined (_I2C_V4)
unsigned char ReadI2C( void )
{
  while ( !BF_x );      // wait until byte received  
  return ( SSPBUF );              // return with read byte 
}
#endif


i2c_writ.c
Code:
#include <pic18.h>
#include <peripheral/i2c.h>

/********************************************************************
*     Function Name:    WriteI2C                                    *
*     Return Value:     Status byte for WCOL detection.             *
*     Parameters:       Single data byte for I2C bus.               *
*     Description:      This routine writes a single byte to the    * 
*                       I2C bus.                                    *
********************************************************************/
#if defined (_I2C_V1)
unsigned char WriteI2C( unsigned char data_out )
{
  SSPBUF = data_out;           // write single byte to SSPBUF
  if ( WCOL_x )      // test if write collision occurred
   return ( -1 );              // if WCOL bit is set return negative #
  else
  {
    while( BF_x );   // wait until write cycle is complete         
    IdleI2C();                 // ensure module is idle
    if ( ACKSTAT_x) // test for ACK condition received
    	 return ( -2 );
	else return ( 0 );              // if WCOL bit is not set return non-negative #
  }
}

#endif

i2c_gets.c
Code:
#include <pic18.h>
#include <peripheral/i2c.h>


/********************************************************************
*     Function Name:    getsI2C                                     *
*     Return Value:     error condition status                      *
*     Parameters:       address of read string storage location     *
*                       length of string bytes to read              *
*     Description:      This routine reads a predetemined string    *
*                       length in from the I2C bus. The routine is  *                       
*                       developed for the Master mode. The bus ACK  *
*                       condition is generated within this routine. *
********************************************************************/
#if defined (_I2C_V1) 

unsigned char getsI2C( unsigned char *rdptr, unsigned char length )
{
    while ( length -- )           // perform getcI2C() for 'length' number of bytes
    {
      *rdptr++ = getcI2C();       // save byte received
      while ( RCEN_x ); // check that receive sequence is over    

      if ( BCLIF )       // test for bus collision
        return ( -1 );            // return with Bus Collision error

      if ( length )               // test if 'length' bytes have been read
      {
        ACKDT_x = 0;    // set acknowledge bit state for ACK        
        ACKEN_x = 1;    // initiate bus acknowledge sequence
        while ( ACKEN_x ); // wait until ACK sequence is over 
      } 
    }
    return ( 0 );                 // last byte received so don't send ACK      
}

#endif


i2c_puts.c
Code:
#include <pic18.h>
#include <peripheral/i2c.h>


/********************************************************************
*     Function Name:    putsI2C                                     *
*     Return Value:     error condition status                      *
*     Parameters:       address of write string storage location    *
*     Description:      This routine writes a string to the I2C bus,*
*                       until a null character is reached. If Master*
*                       function putcI2C is called. When trans-     *
*                       mission is complete then test for ack-      *
*                       nowledge bit. If Slave transmitter wait for *
*                       null character or not ACK received from bus *
*                       device.                                     *
********************************************************************/
#if defined (_I2C_V1)

signed char putsI2C( unsigned char *wrptr )
{
	  unsigned char temp;
  while ( *wrptr )                // transmit data until null character 
  {
    if ( SSPM3_x )      // if Master transmitter then execute the following
    {
	  temp = putcI2C ( *wrptr );
	  if (temp ) return ( temp );            // return with write collision error
    
//      if ( putcI2C ( *wrptr ) )   // write 1 byte
//      {
//        return ( -3 );            // return with write collision error
//      }
//      IdleI2C();                  // test for idle condition
//      if ( SSPCON2bits.ACKSTAT )  // test received ack bit state
//      {
//        return ( -2 );            // bus device responded with  NOT ACK
//      }                           // terminate putsI2C() function
    }

    else                          // else Slave transmitter
    {
      SSPIF = 0;         // reset SSPIF bit
      SSPBUF = *wrptr;            // load SSPBUF with new data
      CKP_x = 1;        // release clock line 
      while ( !SSPIF );  // wait until ninth clock pulse received

      if ( ( !R_W_x ) && ( !BF_x ) )// if R/W=0 and BF=0, NOT ACK was received
        return ( -2 );            // terminate PutsI2C() function
    }

  wrptr ++;                       // increment pointer

  }                               // continue data writes until null character

  return ( 0 );
}

#endif

#if defined (_I2C_V4)

signed char putsI2C( unsigned char *wrptr )
{
	  unsigned char temp;
  while ( *wrptr )                // transmit data until null character 
  {
    if ( SSPM3_x )      // if Master transmitter then execute the following
    {
	  temp = putcI2C ( *wrptr );
	  if (temp ) return ( temp );            // return with write collision error
    
//      if ( putcI2C ( *wrptr ) )   // write 1 byte
//      {
//        return ( -3 );            // return with write collision error
//      }
//      IdleI2C();                  // test for idle condition
//      if ( SSPCON2bits.ACKSTAT )  // test received ack bit state
//      {
//        return ( -2 );            // bus device responded with  NOT ACK
//      }                           // terminate putsI2C() function
    }

    else                          // else Slave transmitter
    {
      SSPIF = 0;         // reset SSPIF bit
      SSPBUF = *wrptr;            // load SSPBUF with new data
      CKP_x = 1;        // release clock line 
      while ( !SSPIF );  // wait until ninth clock pulse received

      if ( ( !R_W_x ) && ( !BF_x ) )// if R/W=0 and BF=0, NOT ACK was received
        return ( -2 );            // terminate PutsI2C() function
    }

  wrptr ++;                       // increment pointer

  }                               // continue data writes until null character

  return ( 0 );
}

#endif


i2c.h
Code:
#include <htc.h>
#ifndef __I2C_H
#define __I2C_H

/* PIC18 I2C peripheral library header */

/* SSPCON1 REGISTER */
#ifndef SSPENB
#define   SSPENB        0b00100000           // Enable serial port and configures SCK, SDO, SDI
#endif
#define   SLAVE_7   			0b00000110     /* I2C Slave mode, 7-bit address      */
#define   SLAVE_10  			0b00000111     /* I2C Slave mode, 10-bit address     */
#define   MASTER    			0b00001000     /* I2C Master mode                    */
#define   MASTER_FIRMW			0b00001011
#define   SLAVE_7_STSP_INT 		0b00001110
#define   SLAVE_10_STSP_INT 	0b00001111
/* SSPSTAT REGISTER */
#define   SLEW_OFF  			0b10000000  /* Slew rate disabled for 100kHz mode */
#define   SLEW_ON   			0b00000000  /* Slew rate enabled for 400kHz mode  */


#if defined (_I2C_V2) || defined (_I2C_V3) || defined (_I2C_V5) || defined (_I2C_V6) /* These versions have MSSP1 */

/* ***** I2C1 ***** */

/* StopI2C1
 * Generate bus stop condition
 */
#define StopI2C1()  PEN_x=1
#define StopI2C StopI2C1

/* StartI2C1
 * Generate bus start condition
 */
#define StartI2C1()  SEN_x=1
#define StartI2C StartI2C1 

/* RestartI2C1
 * Generate bus restart condition
 */
#define RestartI2C1()  RSEN_x=1
#define RestartI2C RestartI2C1

/* NotAckI2C1
 * Generate bus Not ACK condition
 */
#define NotAckI2C1()     do { ACKDT_x=1;\
   							  ACKEN_x=1; } while(0)
#define NotAckI2C NotAckI2C1

/* AckI2C1
 * Generate bus ACK condition
 */
#define AckI2C1() do { ACKDT_x=0;\
					   ACKEN_x=1; } while(0)
#define AckI2C AckI2C1

/* Idle I2C1
 * Test if I2C1 module is idle
 */
#define IdleI2C1()    while ((SSP1CON2 & 0x1F) | (R_W_x))
#define IdleI2C IdleI2C11
/* CloseI2C1
 * Disable SPI module
 */
#define CloseI2C1()  SSP1CON1 &=0xDF
#define CloseI2C CloseI2C1
/* OpenI2C1
 * Configure SSP module for use with I2C1 EEPROM or I2C1 bus device.
 */
#define OpenI2C1_BEGIN(sync_mode, slew) SSP1STAT &= 0x3F;\
									    SSP1CON1 = 0x00;\
									    SSP1CON2 = 0x00;\
									    SSP1CON1 |= sync_mode;\
									    SSP1STAT |= slew
#define OpenI2C1_END SSP1CON1 |= SSPENB
#if defined (_I2C_V2) || defined (_I2C_V3)
#define OpenI2C1(sync_mode, slew) do {OpenI2C1_BEGIN(sync_mode, slew);\
									  I2C1_SCL = 1;\
									  I2C1_SDA = 1;\
									  OpenI2C1_END; } while(0)
#endif
#if defined (_I2C_V5) || defined (_I2C_V6)
#define OpenI2C1(sync_mode, slew) do {OpenI2C1_BEGIN(sync_mode, slew);\
	                                  OpenI2C1_END; } while(0)
#endif
#define OpenI2C OpenI2C1

/* DataRdyI2C1
 * Test if SSPBUF register is full
 */
#define DataRdyI2C1()    (BF_x)
#define DataRdyI2C DataRdyI2C1

/* ReadI2C1
 * Read byte from SSP1BUF register
 */
unsigned char ReadI2C1( void );
#define ReadI2C ReadI2C1

/* GetcI2C1
 * Read byte from SSP1BUF register
 */
#define  getcI2C1  ReadI2C1
#define  getcI2C getcI2C1

/* WriteI2C1
 * Write byte to SSP1BUF register
 */
unsigned char WriteI2C1(  unsigned char data_out );
#define WriteI2C WriteI2C1

/* putcI2C1
 * Write byte to SSP1BUF register
 */
#define  putcI2C1  WriteI2C1
#define  putcI2C putcI2C1

/* getsI2C1
 * Read in a string from I2C1 module
 */
unsigned char getsI2C1(  unsigned char *rdptr,  unsigned char length );
#define getsI2C getsI2C1

/* putsI2C1
 * Write a string to I2C1 module
 */
unsigned char putsI2C1(  unsigned char *wrptr );
#define putsI2C putsI2C1

/* EEAckPolling1
 */
unsigned char EEAckPolling1(  unsigned char control );
#define EEAckPolling EEAckPolling1

/* EEByteWrite1
 */
unsigned char EEByteWrite1(  unsigned char control,
                            unsigned char address,
                            unsigned char data );
#define EEByteWrite EEByteWrite1

/* EECurrentAddRead1
 */
unsigned int  EECurrentAddRead1(  unsigned char control );
#define EECurrentAddRead EECurrentAddRead1

/* EEPageWrite1
 */
unsigned char EEPageWrite1(  unsigned char control,
                            unsigned char address,
                            unsigned char *wrptr );
#define EEPageWrite EEPageWrite1

/* EERandomRead1
 */
unsigned int  EERandomRead1(  unsigned char control,  unsigned char address );
#define EERandomRead EERandomRead1

/* EESequentialRead1
 */
unsigned char EESequentialRead1(  unsigned char control,
                                 unsigned char address,
                                 unsigned char *rdptr,
                                 unsigned char length );
#define EESequentialRead EESequentialRead1
#endif

#if defined (_I2C_V3) || defined (_I2C_V6) /*This version has MSSP2*/
/* ***** I2C2 ***** */

/* StopI2C2
 * Generate bus stop condition
 */
#define StopI2C2()  PEN_x=1

/* StartI2C2
 * Generate bus start condition
 */
#define StartI2C2()  SEN_x=1

/* RestartI2C2
 * Generate bus restart condition
 */
#define RestartI2C2() RSEN_x=1

/* NotAckI2C2
 * Generate bus Not ACK condition
 */
#define NotAckI2C2() do {ACKDT_x=1;\
   						 ACKEN_x=1; } while(0)

/* AckI2C2
 * Generate bus ACK condition
 */
#define AckI2C2() do { ACKDT_x=0;\
   					   ACKEN_x=1; } while(0)

/* Idle I2C2
 * Test if I2C2 module is idle
 */
#define IdleI2C2()    while ((SSP2CON2 & 0x1F) | (R_W_x))

/* CloseI2C2
 * Disable SPI module
 */
#define CloseI2C2()  SSP2CON1 &=0xDF

/* OpenI2C2
 * Configure SSP module for use with I2C2 EEPROM or I2C2 bus device.
 */
#define OpenI2C2_BEGIN(sync_mode, slew) SSP2STAT &= 0x3F;\
										SSP2CON1 = 0x00;\
                                        SSP2CON2 = 0x00;\
                                        SSP2CON1 |= sync_mode;\
                                        SSP2STAT |= slew
#define OpenI2C2_END SSP2CON1 |= SSPENB
#if defined (_I2C_V3)
#define OpenI2C2(sync_mode, slew) do {OpenI2C2_BEGIN(sync_mode, slew);\
	                                  I2C2_SCL = 1;\
	                                  I2C2_SDA = 1;\
	                                  OpenI2C2_END; } while(0)
#endif
#if defined (_I2C_V6)
#define OpenI2C2(sync_mode, slew) do {OpenI2C2_BEGIN(sync_mode, slew);\
	                                  OpenI2C2_END; } while(0)
#endif




/* DataRdyI2C2
 * Test if SSPBUF register is full
 */
#define DataRdyI2C2()    (BF_x)

/* ReadI2C2
 * Read byte from SSP2BUF register
 */
unsigned char ReadI2C2( void );

/* GetcI2C2
 * Read byte from SSP2BUF register
 */
#define  getcI2C2  ReadI2C2

/* WriteI2C2
 * Write byte to SSP2BUF register
 */
unsigned char WriteI2C2(  unsigned char data_out );

/* putcI2C2
 * Write byte to SSP2BUF register
 */
#define  putcI2C2  WriteI2C2

/* getsI2C2
 * Read in a string from I2C2 module
 */
unsigned char getsI2C2(  unsigned char *rdptr,  unsigned char length );

/* putsI2C2
 * Write a string to I2C2 module
 */
signed char putsI2C2(  unsigned char *wrptr );

/* EEAckPolling2
 */
unsigned char EEAckPolling2(  unsigned char control );

/* EEByteWrite2
 */
unsigned char EEByteWrite2(  unsigned char control,
                            unsigned char address,
                            unsigned char data );

/* EECurrentAddRead2
 */
unsigned int  EECurrentAddRead2(  unsigned char control );

/* EEPageWrite2
 */
unsigned char EEPageWrite2(  unsigned char control,
                            unsigned char address,
                            unsigned char *wrptr );

/* EERandomRead2
 */
unsigned int  EERandomRead2(  unsigned char control,  unsigned char address );

/* EESequentialRead2
 */
unsigned char EESequentialRead2(  unsigned char control,
                                 unsigned char address,
                                 unsigned char *rdptr,
                                 unsigned char length );
#endif

#if defined (_I2C_V1) || defined (_I2C_V4)    /* Parts with only one I2C, MSSP */

/* GetcI2C
 * Read byte from SSPBUF register
 */
#define  getcI2C  ReadI2C

/* putsI2C
 * Write a string to I2C module
 */
signed char putsI2C(  unsigned char *wrptr );

/* ReadI2C
 * Read byte from SSPBUF register
 */
unsigned char ReadI2C( void );

#endif

#if defined (_I2C_V1) 

/* CloseI2C
 * Disable SPI module
 */
#define CloseI2C()  SSPCON1 &=0xDF

/* OpenI2C
 * Open SPI module
 */

#define OpenI2C_BEGIN(sync_mode, slew) SSPSTAT &= 0x3F;\
									   SSPCON1 = 0x00;\
                                       SSPCON2 = 0x00;\
                                       SSPCON1 |= sync_mode;\
                                       SSPSTAT |= slew
#define OpenI2C_END SSPCON1 |= SSPENB
#define OpenI2C(sync_mode, slew) do {OpenI2C_BEGIN(sync_mode, slew);\
	                                 I2C_SCL = 1;\
	                                 I2C_SDA = 1;\
	                                 OpenI2C_END; } while(0)
#if defined (_I2C_V2) || defined (_I2C_V3)
#define OpenI2C(sync_mode, slew) do {OpenI2C_BEGIN(sync_mode, slew);\
	                                 I2C_SCL = 1;\
	                                 I2C_SDA = 1;\
	                                 OpenI2C_END; } while(0)
#endif
#if defined (_I2C_V5) || defined (_I2C_V6)
#define OpenI2C(sync_mode, slew) do {OpenI2C_BEGIN(sync_mode, slew);\
	                                 OpenI2C_END; } while(0)
#endif


/* Idle I2C
 * Test if I2C module is idle
 */
#define IdleI2C()    while ((SSPCON2 & 0x1F) | (R_W_x))

/* StopI2C
 * Generate bus stop condition
 */
#define StopI2C()  PEN=1

/* StartI2C
 * Generate bus start condition
 */
#define StartI2C() SEN_x=1

/* RestartI2C
 * Generate bus restart condition
 */
#define RestartI2C() RSEN_x=1

/* NotAckI2C
 * Generate bus Not ACK condition
 */
#define NotAckI2C() do { ACKDT_x=1;\
   						 ACKEN_x=1; } while(0)

/* AckI2C
 * Generate bus ACK condition
 */
#define AckI2C() do { ACKDT_x=0;\
   					  ACKEN_x=1; } while(0)

/* DataRdyI2C
 * Test if SSPBUF register is full
 */
#define DataRdyI2C()    (BF_x)

/* putcI2C
 * Write byte to SSPBUF register
 */
#define  putcI2C  WriteI2C

/* WriteI2C
 * Write byte to SSPBUF register
 */
unsigned char WriteI2C(  unsigned char data_out );

/* getsI2C
 * Read in a string from I2C module
 */
unsigned char getsI2C(  unsigned char *rdptr,  unsigned char length );

/* EEAckPolling
 */
unsigned char EEAckPolling(  unsigned char control );

/* EEByteWrite
 */
unsigned char EEByteWrite(  unsigned char control,
                            unsigned char address,
                            unsigned char data );

/* EECurrentAddRead
 */
unsigned int  EECurrentAddRead(  unsigned char control );

/* EEPageWrite
 */
unsigned char EEPageWrite(  unsigned char control,
                            unsigned char address,
                            unsigned char *wrptr );

/* EERandomRead
 */
unsigned int  EERandomRead(  unsigned char control,  unsigned char address );

/* EESequentialRead
 */
unsigned char EESequentialRead(  unsigned char control,
                                 unsigned char address,
                                 unsigned char *rdptr,
                                 unsigned char length );
#endif

#if defined (_I2C_V4)
#define CloseI2C()  SSPCON &=0xDF
#define IdleI2C()    while ((SSPCON & 0x1F) | (R_W_x)) 

/* OpenI2C
 *  * Open SPI module
 *   */

#define OpenI2C_BEGIN(sync_mode, slew) SSPSTAT &= 0x3F;\
									   SSPCON = 0x00;\
                                       SSPCON = 0x00;\
                                       SSPCON |= sync_mode;\
                                       SSPSTAT |= slew
#define OpenI2C_END SSPCON |= SSPENB
#if defined (_I2C_V2) || defined (_I2C_V3)
#define OpenI2C(sync_mode, slew) do {OpenI2C_BEGIN(sync_mode, slew);\
	                                 I2C_SCL = 1;\
	                                 I2C_SDA = 1;\
	                                 OpenI2C_END; } while(0)
#endif
#if defined (_I2C_V5) || defined (_I2C_V6)
#define OpenI2C(sync_mode, slew) do {OpenI2C_BEGIN(sync_mode, slew);\
	                                 OpenI2C_END; } while(0)
#endif
#endif

#if defined (_18C242) ||defined (_18C252) ||defined (_18C442) ||\
defined (_18C452) ||defined (_18F242) ||defined (_18F252) ||\
defined (_18F442) ||defined (_18F452) ||defined (_18F248) ||\
defined (_18F258) ||defined (_18F448) ||defined (_18F458) ||\
defined (_18F2439) ||defined (_18F2539) ||defined (_18F4439) ||\
defined (_18F4539) ||defined (_18C601) ||defined (_18C801) ||\
defined (_18C658) ||defined (_18C858) ||defined (_18F6620) ||\
defined (_18F6720) ||defined (_18F8620) ||defined (_18F8720) ||\
defined (_18F6520) ||defined (_18F8520) ||defined (_18F2220) ||\
defined (_18F2320) ||defined (_18F4220) ||defined (_18F4320) ||\
defined (_18F2420) ||defined (_18F2520) ||defined (_18F4420) ||\
defined (_18F4520) ||defined (_18F2423) ||defined (_18F2523) ||\
defined (_18F4423) ||defined (_18F4523) ||defined (_18F2480) ||\
defined (_18F2580) ||defined (_18F4480) ||defined (_18F4580) ||\
defined (_18F2410) ||defined (_18F2510) ||defined (_18F2515) ||\
defined (_18F2610) ||defined (_18F4410) ||defined (_18F4510) ||\
defined (_18F4515) ||defined (_18F4610) ||defined (_18F2525) ||\
defined (_18F2620) ||defined (_18F4525) ||defined (_18F4620) ||\
defined (_18F2585) ||defined (_18F2680) ||defined (_18F4585) ||\
defined (_18F4680) ||defined (_18F2682) ||defined (_18F2685) ||\
defined (_18F4682) ||defined (_18F4685) ||defined (_18F2221) ||\
defined (_18F2321) ||defined (_18F4221) ||defined (_18F4321) ||\
defined (_18F6310) ||defined (_18F6410) ||defined (_18F8310) ||\
defined (_18F8410) ||defined (_18F6390) ||defined (_18F6490) ||\
defined (_18F8390) ||defined (_18F8490) ||defined (_18F6585) ||\
defined (_18F6680) ||defined (_18F8585) ||defined (_18F8680) ||\
defined (_18F6525) ||defined (_18F6621) ||defined (_18F8525) ||\
defined (_18F8621) ||defined (_18F63J11) ||defined (_18F64J11) ||\
defined (_18F65J11) ||defined (_18F83J11) ||defined (_18F84J11) ||\
defined (_18F85J11) ||defined (_18F63J90) ||defined (_18F64J90) ||\
defined (_18F65J90) ||defined (_18F83J90) ||defined (_18F84J90) ||\
defined (_18F85J90) ||defined (_18F23K20) ||defined (_18F24K20) ||\
defined (_18F25K20) ||defined (_18F26K20) ||defined (_18F43K20) ||\
defined (_18F44K20) ||defined (_18F45K20) ||defined (_18F46K20 )||\
defined (_18F6493) || defined (_18F8493) ||\
defined (_18F6393) || defined (_18F8393) 
#define I2C_SCL	TRISC3
#define I2C_SDA	TRISC4
#endif

#if defined (_18F2331) ||defined (_18F2431) ||defined (_18F4331) || defined (_18F4431)
#define I2C_SCL	TRISC5
#define I2C_SDA	TRISC4
#endif

#if defined (_18F2455) ||defined (_18F2550) ||defined (_18F4455) ||\
	defined (_18F4550) ||defined (_18F2458) ||defined (_18F2553) ||\
	defined (_18F4458) ||defined (_18F4553)
#define I2C_SCL	TRISB1
#define I2C_SDA	TRISB0
#endif

#if defined (_18F13K50) || defined (_18F14K50) ||\
    defined (_18LF13K50) || defined (_18LF14K50) ||\
    defined (_18F13K20) || defined (_18F14K20) ||\
    defined (_18F13K22) || defined (_18F14K22) ||\
    defined (_18LF13K22) || defined (_18LF14K22)
#define I2C_SCL	TRISB6
#define I2C_SDA	TRISB4

#endif

#if defined (_18F6527) ||defined (_18F6622) ||defined (_18F6627) ||\
defined (_18F6722) ||defined (_18F8527) ||defined (_18F8622) ||\
defined (_18F8627) ||defined (_18F8722) ||defined (_18F24J10) ||\
defined (_18F25J10) ||defined (_18F44J10) ||defined (_18F45J10) ||\
defined (_18F65J10) ||defined (_18F65J15) ||defined (_18F66J10) ||\
defined (_18F66J15) ||defined (_18F67J10) ||defined (_18F85J10) ||\
defined (_18F85J15) ||defined (_18F86J10) ||defined (_18F86J15) ||\
defined (_18F87J10) ||defined (_18F66J60) ||defined (_18F66J65) ||\
defined (_18F67J60) ||defined (_18F86J60) ||defined (_18F86J65) ||\
defined (_18F87J60) ||defined (_18F96J60) ||defined (_18F96J65) ||\
defined (_18F97J60) ||defined (_18F66J11) ||defined (_18F66J16) ||\
defined (_18F67J11) ||defined (_18F86J11) ||defined (_18F86J16) ||\
defined (_18F87J11) ||defined (_18F65J50) ||defined (_18F66J50) ||\
defined (_18F66J55) ||defined (_18F67J50) ||defined (_18F85J50) ||\
defined (_18F86J50) ||defined (_18F86J55) ||defined (_18F87J50) ||\
defined (_18F6628)  || defined (_18F6723) || defined (_18F8628) ||\
defined (_18F8723)
#define I2C1_SCL	RC3
#define I2C1_SDA	RC4
#endif

#if defined (_18F44J10) || defined (_18F45J10)
#define I2C2_SCL	RD0
#define I2C2_SDA	RD1
#endif

#if defined (_18F6527) ||defined (_18F6622) ||defined (_18F6627) ||\
defined (_18F6722) ||defined (_18F8527) ||defined (_18F8622) ||\
defined (_18F8627) ||defined (_18F8722) ||defined (_18F65J10) ||\
defined (_18F65J15) ||defined (_18F66J10) ||defined (_18F66J15) ||\
defined (_18F67J10) ||defined (_18F85J10) ||defined (_18F85J15) ||\
defined (_18F86J10) ||defined (_18F86J15) ||defined (_18F87J10) ||\
defined (_18F96J60) ||defined (_18F96J65) ||defined (_18F97J60) ||\
defined (_18F66J11) ||defined (_18F66J16) ||defined (_18F67J11) ||\
defined (_18F86J11) ||defined (_18F86J16) ||defined (_18F87J11) ||\
defined (_18F65J50) ||defined (_18F66J50) ||defined (_18F66J55) ||\
defined (_18F67J50) ||defined (_18F85J50) ||defined (_18F86J50) ||\
defined (_18F86J55) ||defined (_18F87J50) ||defined (_18F6628)  ||\
defined (_18F6723)  || defined (_18F8628) ||defined (_18F8723)
#define I2C2_SCL	RD6
#define I2C2_SDA	.RD5
#endif

#endif


Attached is the I2C Library Source Code and Header File.

BigDog
 

Attachments

  • i2c.zip
    26.4 KB · Views: 98
  • Like
Reactions: zuisti

    zuisti

    Points: 2
    Helpful Answer Positive Rating
@PA3040,
Since you are step by step building routines to control DS1307 RTC, the following might help you:-


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/********************************************************
  *      Real Time Clock DS1307 Library for 18F4620     *
  *                  (for PIC IC.)                      *
  *                 by Deniz ELMASLI                    *
  * Version 2.0                                         *
  * Creation Date: 28.12.2008   -   10:12 Friday        *
  * Revision Date: 08.06.2008   -   03:42 Saturday      *
  * Ide(s) : Code::Blocks v1.0 (C++ developement)       *
  *          MikroC V7.0                                *
  * Target Platform: PIC                                *
  * MCU : 18F4620                                       *
  * Contact: elmasli@gmail.com                          *
  * Web    : [url]www.dronology.com[/url]                          *
  *                                                     *
  *   This code in intended to work with PIC IC. This   *
  * source code contains functions to drive DS1307 real *
  * time clock  . I2C Functions used in ver2.0          *
  *******************************************************
 
*/
 
 
    void start1307s();
    void ds1307_init();
    void ds1307_set_date_time(char day,char mth,char year,char dow,char hr,char min, int sec);
    void ds1307_get_time_date(char *day, char *mth, char *year, char *dow, char *hr, char *min, char *sec);
 
 
void ds1307_init(){
    int seconds=0;
 
    I2C_Start();
    I2C_Wr(0xD0);      // WR to RTC
    I2C_Wr(0x00);      // REG 0
    I2C_Start();
    I2C_Wr(0xD1);      // RD from RTC
    seconds = Bcd2Dec(I2C_Rd(0)); // Read current "seconds" in DS1307
    I2C_Stop();
    seconds = (seconds & 0x7F);
 
    Delay_ms(50);
 
    I2C_Start();
    I2C_Wr(0xD0);      // WR to RTC
    I2C_Wr(0x00);      // REG 0
    I2C_Wr(Dec2Bcd(seconds));     // Start oscillator with current "seconds value
    I2C_Start();
    I2C_Wr(0xD0);      // WR to RTC
    I2C_Wr(0x07);      // Control Register
    I2C_Wr(0x80);      // Disable squarewave output pin
    I2C_Stop();
}//~
 
 
 
 
void ds1307_set_date_time(char day,char mth,char year,char dow,char hr,char min, int sec){
    sec =(sec & 0x7F);
    hr =(hr & 0x3F);
 
    I2C_Start();
    I2C_Wr(0xD0);               // I2C write address
    I2C_Wr(0x00);               // Start at REG 0 - Seconds
    I2C_Wr(Dec2Bcd(sec));       // REG 0
    I2C_Wr(Dec2Bcd(min));       // REG 1
    I2C_Wr(Dec2Bcd(hr));        // REG 2
    I2C_Wr(Dec2Bcd(dow));       // REG 3
    I2C_Wr(Dec2Bcd(day));       // REG 4
    I2C_Wr(Dec2Bcd(mth));       // REG 5
    I2C_Wr(Dec2Bcd(year));      // REG 6
    I2C_Wr(0x80);               // REG 7 - Disable squarewave output pin
    I2C_Stop();
}//~
 
 
 
 
 
void ds1307_get_time_date(char *day, char *mth, char *year, char *dow, char *hr, char *min, char *sec){
    I2C_Start();
    I2C_Wr(0xD0);
    I2C_Wr(0x00);                     // Start at REG 3 - Day of week
    I2C_Start();
    I2C_Wr(0xD1);
    *sec=Bcd2Dec(I2C_Rd(1) & 0x7F);
    *min=Bcd2Dec(I2C_Rd(1) & 0x7F);
    *hr=Bcd2Dec(I2C_Rd(1) & 0x3F);
    *dow=Bcd2Dec(I2C_Rd(1) & 0x7F);   // REG 3
    *day=Bcd2Dec(I2C_Rd(1) & 0x3F);   // REG 4
    *mth=Bcd2Dec(I2C_Rd(1) & 0x1F);   // REG 5
    *year=Bcd2Dec(I2C_Rd(0));         // REG 6
    I2C_Stop();
}//~

 
  • Like
Reactions: PA3040

    PA3040

    Points: 2
    Helpful Answer Positive Rating
Dear Alex
Thanks for reply
Sorry I could not say clearly what I need is?
actually I need adjust the time and date using externally used micro switch
Please advice

What exactly do you mean by that?
You mean the routines to scan the button press?
Or do you mean the button configuration?
You can use two buttons , one to select date/month/year/hour/min/sec and the other to increment the number, or three buttons , one to select and two for up/down.
You can store the value after a long press of the button or when the user goes through all the settings or show a store mode after the seconds, there are several ways.
 
  • Like
Reactions: PA3040

    PA3040

    Points: 2
    Helpful Answer Positive Rating
Dear Alex,
Yes you are correct
As a First step, I need to use three buttons one select and two for up/down
My hardware reserved PORTD for LCD data (8bit) and three pins of PORTB for (E,RS,W) bit7 and bit6 reserved for ICSP
Hopefully to use PORTA for buttons ( any Advice)
Can I have simple pseudocode please
Thanks in advance

- - - Updated - - -

Dear papunblg,
Thank you so much for help
I am following your codes, any helps, I will let you know
Thanks again and again
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top