Master Slave Clocks with PIC16F887

Status
Not open for further replies.
IN ds1307 chip data sheet there was no addr named 0xd0 in it,why?
Because its classified as a 7 bit address... 0x69... BUT!!! to address an I2C bus we need to shift it up to allow for the R/W bit

0110 1000 = ox69
1101 0000/1 = 0xD0 or 0xD1
What is this ? DS1302 Trickle-Charge Timekeeping Chip

When running on power the DS1302 can charge suitable back-up batteries..
I remember few year back there was BLDC ESc controller by i2C in which it was written only , not reading!
If the BLDC has feedback control then you could read motor position, Obviously that chip only moved the motors..
 
Hello,
Please tell how to make 7 segment clocks using DS1307!
By hardware I2C not by software.
 
I will be at home in about an hour... I'll put the basics in a file and let you finish it!!

I'll try and remark it as well as I can..

P.S.

How are you driving the seven seg display... Also how many digits???
 
Okay.... Simple RTC to Display.... I have only used time....

C:
#include<xc.h>

void delayUs(int x)
   {
   x>>= 5;
   while(x--);           // delay Usv ( aprox...)
   }

void delayMs(int x)
   {
   while(x--)
     delayUs(1000);       // delay Ms
   }
  
void InitI2C()
   {
   TRISC3=1;
   TRISC4=1;
   SSPCON=0b00101000;
   SSPCON2=0;
   SSPSTAT=0b10000000;
   SSPADD=50;  //20000/(4*100);  //Fosc/(4*baud)
   SSPIF=0;
   BCLIF=0;
   }

//Wait for the module to finish it's last action.
void WaitSSP()
   {
   while(SSPIF==0);
   SSPIF=0;
   }

//send start bit
void SendStart()
   {
   SEN=1;
   WaitSSP();
   }

//Send stop bit.
void SendStop()
   {
   PEN=1;
   WaitSSP();
   }

//Send restart bit
void SendRestart()
   {
   RSEN=1;
   WaitSSP();
   }

//Send byte and return ack bit - 1=Ack  0=NAck
char SendByte(char Byte)
   {
   SSPBUF=Byte;
   WaitSSP();
   return(!ACKSTAT);
   }

//Get a byte from the slave
char ReceiveByte()
   {
   RCEN=1;         // get byte
   WaitSSP();
   return(SSPBUF);
   }

//Send a Not Acknowledge (NAck) to the slave
void SendNack()
   {
   ACKDT=1;       // Not Acknowledge
   ACKEN=1;
   WaitSSP();
   }

//Send an Acknowledge (Ack) to the slave
void SendAck()
   {
   ACKDT=0;       // Acknowledge
   ACKEN=1;
   WaitSSP();
   }

//Sends the start and device address.
//If the device is busy then it resends until accepted.
void SendID(char DeviceID)
   {
   SendStart();
   if(SendByte(DeviceID)==1)     // Send ID until accepted..
     return;
   do
     {
     SendRestart();
     }while(SendByte(DeviceID)==0);
   }


//Write a byte to The RTC
char WriteRTC(char Address, char Byte)
   {
   SendID(0b11010000);         // Send 0xD0
   if(SendByte(Address&0xff)==0)   // Send address
     return(0);
   if(SendByte(Byte)==0)       // Send byte
     return(0);
   SendStop();             // All done
   return(1);
   }

//Read a byte from the RTC
char ReadRTC(char Address)
   {
   char Byte;
   SendID(0b11010000);         // Send 0xD0
   if(SendByte(Address&0xff)==0)   // Send address
     return(0);
   SendRestart();           // Re-start
   if(SendByte(0b11010001)==0)     // Read 0xD1
     return(0);
   Byte=ReceiveByte();         // Get byte
   SendNack();             // No more
   SendStop();             // Stop bus
   return(Byte);           // All done
   }

void WriteClock(char *array)       // Not used
   {
   char x;
   int tmp;
   for(x=0;x<7;x++)
     {
     tmp = array[x] / 10;
     tmp << = 4;
     tmp += array[x] % 16;
     WriteRTC(x,tmp);
     }  
   }  

void ReadClock(char *array)
   {
   char x;
   for(x=0;x<7;x++)
     array[x] = ReadRTC(x);       // No need to BCD-BIN
   }  

unsigned char Time[7];
unsigned char DISP[6];
unsigned char digits[] = {0x3f,0x6,0x5b,0x4f,0x66,0x6d,0x7d,0x7,0x7f,0x6f};
             
void main(void)
   {
   int idx, SCL;           // loop variables
   unsigned char DIGIT;       // A temporary store for manipulation
   TRISC = 0;             // portc tris bits
   TRISD = 0;             // portd tris bits
   InitI2C();             // prepare the RTC bus
   RC0 = 1;             // MR high
   RC1 = 0;             // OE low
  
   while(1)
     {
     ReadClock(&Time[0]);               // Get time ( BCD format as
     delayMs(250);                   // we are using  7 seg )
     DISP[5] = Time[2]>>4; DISP[4] = Time[2] & 0xf;   // fill display buffer
     DISP[3] = Time[1]>>4; DISP[2] = Time[1] & 0xf;   // backwards so it's
     DISP[1] = Time[0]>>4; DISP[0] = Time[0] & 0xf;   // readable...
     for(idx = 0;idx < 6;idx++)
       {
       DIGIT = digits[DISP[idx]];         // retrive 7 seg code
       for(SCL = 0; SCL < 8; SCL++)         // 8 clocks
         {
         RD2 = 1;                 // No data ( swap for CC )
         if(DIGIT & 0x80)RD2 = 0;         // Data to send?? ( swap for CC )
         DIGIT<<=1;
         RD0 = 1;                 // data clock
         NOP();
         RD0 = 0;        
         }
      
       }
     RD1 = 1;                     // Latch clock..
     NOP();
     RD1 = 0;
     }  
  
   }



I have used 74ls595 to give visual stability.... See if you can follow the code. NO INTERRUPTS so you should be okay!!!
 
I think you'd better crack open that jd mr rogers.

P.S. after staring at datasheets wondering why an i2c device wasnt responding I've run a i2c scanner and found that the address isnt as published in the datasheet, on a couple of devices.
 
How are you driving the seven seg display... Also how many digits???
Hello,
I am using PORTB directly with 120 ohm to 4 seven segment, and common anode to RD0-RD3 via BJT. the circuit is working fine.
I am using array stored and set to PORTB for Driving 7 segments.!
 
Hi again,

This is what i want to understand
Thanks

If you want to write to the device you have to:

setup a start condition ( if bus is ready )
write device address ( wait for ack )
write register address ( wait for ack )
write device data ( wait for ack )
send nack ( to stop device )
send stop ( to free bus )


If you want to read from the device you have to:

setup a start condition ( if bus is ready )
write device address ( wait for ack )
write register address ( wait for ack )
send re-start( wait for ack )
read device ( send ack if more data needed )
send nack ( to stop device )
send stop ( to free bus )
 
Last edited:
Hello,
I have modified the code simple version.
please have a look i have write 0x0f in sec register @ 0x00h addr to watch the change after this i am reading the i2c buffer register to get value!
In MPLAB build successful, hanging at in debugger can we test code in this?
void i2c_Wait(void){
while((SSPCON2 & 0X1F || (SSPSTAT & 0X04)));
}



C:
#include <htc.h>

__CONFIG(LVP_OFF & BOREN_OFF & PWRTE_ON & WDTE_OFF & FOSC_HS);
#define _XTAL_FREQ 20000000
#define SDATA RC4
#define SCLK RC3
void I2C_init(),I2C_start(void),I2C_write(char x), I2cSTOP(void);  
void i2c_Wait(void);
char data[13]={  0b00010000,0b01111101,0b00100011,0b00101000,0b01001101,0b10001000,
0b10000000, 0b00111101,0X00,0b00001000};

void main(void){
ANSELH = 0;
    TRISC3=1; //direction to input have be changed
    TRISC4=1;
unsigned char ch=0;
    unsigned char i;
TRISC0=0;
TRISB=0X00;
TRISD=0X00;
TRISC1=0;
TRISC2=0;
RC0=0;
RC1=0;
RC2=0;
//__delay_ms(500);
    I2C_init();
//__delay_ms(50);

    I2C_start();
    I2C_write(0xd0);

I2C_write(0x00);
I2C_write(0x0f);

  
I2cSTOP();

while(1){
    I2C_start();
    I2C_write(0xd0);
    I2C_write(0x00);
    I2cSTOP();
    I2C_start();
    I2C_write(0xD1);
   i= SSPBUF;

    I2cSTOP();
}


RD0=0;
RD1=0;
RD2=0;
RD3=1;
PORTB=data[i];
__delay_ms(500);
PORTB=0B00000000;


}

void I2C_init(void)
    {
  SSPCON = 0x38;      // set I2C master mode
SSPCON2 = 0x00;
SSPADD = 0x0C;  //400KHZ  20MHz xtal
SSPSTAT|=0X80;
PSPIF=0;      // clear SSPIF interrupt flag
BCLIF=0;      // clear bus collision flag
}
void I2C_start(void)
{
    i2c_Wait();
    SEN=1;
}
void I2C_write(char x){
    i2c_Wait();  
SSPBUF=x;
        }
void i2c_Wait(void){
    while((SSPCON2 & 0X1F || (SSPSTAT & 0X04)));
}
void I2cSTOP(void)
{
    i2c_Wait();
    PEN=1;
}
 
In MPLAB build successful, hanging at in debugger can we test code in this?
You have to make a stimulus file that injects the data into the serial buffer.... Then at the appropriate time file the stimulus
 
OK, do you find any eror in this upper code it is display only 8 in 7 segment.
not changing the digit is there any error?
 
Well yeah!! The LED write is only once AND!! its outside the while loop.... It will never be updated...

One other thing... i will be a BCD figure... so you also need to and it with 0xf so the data array can separate tens and units... to display the tens shift i 4 times.... i >>= 4;
 
Hi again,
It is not working..



C:
#include <htc.h>

__CONFIG(LVP_OFF & BOREN_OFF & PWRTE_ON & WDTE_OFF & FOSC_HS);
#define _XTAL_FREQ 20000000
#define SDATA RC4
#define SCLK RC3
void I2C_init(),I2C_start(void),I2C_write(char x), I2cSTOP(void);   
void i2c_Wait(void);
char data[13]={  0b00010000,0b01111101,0b00100011,0b00101000,0b01001101,0b10001000,
0b10000000, 0b00111101,0X00,0b00001000};

void main(void){
ANSELH = 0;
    TRISC3=1; //direction to input have be changed
    TRISC4=1;
unsigned char ch=0;
unsigned char i=0;

TRISB=0X00;
TRISD=0X00;
PORTB=0B00000000;
__delay_ms(500);
    I2C_init();
__delay_ms(50);

    I2C_start();
    I2C_write(0xd0);

I2C_write(0x00);
I2C_write(0x00);

I2cSTOP();
   RD0=0;
RD1=0;
RD2=1;
RD3=0;
PORTB=data[0];
__delay_ms(800);
PORTB=0B00000000;
   
while(1){

    I2C_start();
    I2C_write(0xd0);
    I2C_write(0x00);
    I2cSTOP();
    I2C_start();
    I2C_write(0xD1);
   i= SSPBUF;

    I2cSTOP();

i=i&0xf;
RD0=1;
RD1=0;
RD2=0;
RD3=0;
PORTB=data[i];
PORTB=0x00;
__delay_ms(500);

i>>=4;
RD0=0;
RD1=1;
RD2=0;
RD3=1;
PORTB=data[i];
PORTB=0x00;
__delay_ms(500);





}
}
void I2C_init(void)
    {
  SSPCON = 0x38;      // set I2C master mode
SSPCON2 = 0x00;
SSPADD = 0x0C;  //400KHZ  20MHz xtal
SSPSTAT|=0X80;
PSPIF=0;      // clear SSPIF interrupt flag
BCLIF=0;      // clear bus collision flag
}
void I2C_start(void)
{
    i2c_Wait();
    SEN=1;
}
void I2C_write(char x){
    i2c_Wait();   
SSPBUF=x;
        }
void i2c_Wait(void){
    while((SSPCON2 & 0X1F || (SSPSTAT & 0X04)));
}
void I2cSTOP(void)
{
    i2c_Wait();
    PEN=1;
}
 
I am tired now with DS1307 it is still 8 on display...
how to work out from it?
i am using 6V adapter.
 
Arrrgghh!!!
Code:
PORTB=data[i]; <------- LOOK   If  i  is seconds it will be.....
say 0x58 BCD  or dec 88  HOW CAN YOU ASK FOR data[i].....
data[88] doesn't exsist!!!!!!

The Ds1307 stores the data in BCD format..... if seconds = 11 it is stored 0x11 ( dec 17 ).....#

You need to modulus i.... and i / 16....

data[ i %16]; units
data[ i >> 4]; tens
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…