Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Master Slave Clocks with PIC16F887

Status
Not open for further replies.

koolguy

Active Member
Hello,
I have pic16f887 and i want to connect the RTC module with it, Module from provotech, it has scl and sda.
according to little research it say to connect the SQW to timer interput at 1Hz something like that!!


Thanks
 
Hello,
The data sheet says....

The address map for the DS1307 RTC and RAM registers. The RTC registers are located in address
locations 00h to 07h. The RAM registers are located in address locations 08h to 3Fh. During a multibyte access,
when the address pointer reaches 3Fh, the end of RAM space, it wraps around to location 00h, the beginning of
the clock space.

00 to 007h mean display register!
But what about 08h to 3fH mean here?
 
Hello, i got this code but not understanding working!

Then I don't understand your problem....

When a DS1307 is first initialised, we send the time to it... Once this is done we then can read back the real time whenever we need... There is no need to stop / start the oscillator...

Set up a time array Sec, Min, Hour, Day, Date, Mon,Year..... And just write the whole array to and from the chip..
You will also need a binary ~ BCD routine and the BCD ~ binary routine as the DS1307 stores the information in BCD format!
C:
void bcdBin(char* array)
    {
    char x;
    unsigned char tmp;
    for(x=0;x<8;x++)
        {
        tmp = *array  >> 4;
        tmp *= 10;
        tmp = tmp + (*array & 0xf);
        *array++ = tmp;
        }
    }

void binBcd(char* array)
    {
    char x;
    unsigned char tmp;
    for(x=0;x<8;x++)
        {
        tmp = *array  / 10;
        tmp = tmp << 4;
        tmp = tmp + (*array % 10);
        *array++ = tmp;
        }
    }

void WriteClock(char *array)
    {
    char x;
    for(x=0;x<8;x++)
        WriteRTC(x,array[x]); 
    } 

void ReadClock(char *array)
    {
    char x;
    for(x=0;x<8;x++)
        array[x] = ReadRTC(x); 
    }

From this you should get the idea!!!
 
The DS1307 ids the RTC I use... There is 8 registers at the beginning of the device that stores this..

upload_2015-4-4_12-30-36.png


You read the BCD values and display them however you want!!!
 
Why manufacture give this option is there any specific reason?
and do i have to read time from i every minutes or every sec?
 
Think!.... 56 bytes + 8 registers..... That's an even 64 bytes... It makes perfect sense to me!!
8 x 8 memory.
making no sense to me!
I read every program cycle ( 3 times a second )
why?

After that connecting the Ds1307 with PIC16f877 with pull up's what to do?
I mean we have to write days times in chip?
 
8 x 8 memory.
making no sense to me!
I read every program cycle ( 3 times a second )
why?

After that connecting the Ds1307 with PIC16f877 with pull up's what to do?
I mean we have to write days times in chip?
This is going to be hard work..... Just copy the code in tutorial 6... Everything is in there..
Use the code as you will...
C:
#include <pic.h>         // pic specific identifiers
#include <stdio.h>         // New include file..
#define _XTAL_FREQ  4000000     // Xtal speed
__CONFIG(0x3D18);         // Config bits

#define LCD_PORT   PORTA       // LCD configuration
#define LCD_TRIS   TRISA
#define LCD_RS     RA4
#define LCD_RW     RA6
#define LCD_E     RA7

#define I2C_PORT   PORTB       // I2C port configuration
#define I2C_TRIS   TRISB
#define SDAI     RB7       
#define SCLI     RB6
#define SDA       TRISB7     // in C  we can control the input / output
#define SCL       TRISB6     // by one simple command.

#define ErrFlag     0x0         // errors for
#define StartFlag   0x1         // those who wish to use them
#define One       0x2
#define Zero     0x3

#define EEPROM     0xA0     // standard eeprom address fro writing
#define ADC       0x90
#define CHIP_Read   0x01     // and reading


     // Required prototypes

void LCD_init(void), LCD_cmd(unsigned char ch),  initTimer(void);
void LCD_printC(const char *str), LCD_printR(char *str);
void LCD_goto(char line, char column), LCD_clr(void), DelayMs(int dly);
void LCD_cur(unsigned char ch), pulse_E(void), LCD_hex(int value);
void LCD_char(unsigned char ch), LCD_charD(unsigned char ch);
void I2C_Sendnack(void), I2C_ack(void), I2C_Stop(void), clock(void);
void I2C_Start(void), I2C_Write(unsigned char ch);
void interrupt isr(void);
void read_Mem(void), write_Mem(void), clear_Mem(void), setTime(void);
char I2C_nack(), E_Write(int addr, unsigned char* ch, unsigned char len);
unsigned char I2C_Read(void), E_Read(int addr, char* ch, char len);
int getkey(void), getADC(void);

unsigned char HEX_Table[] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
               0x37, 0x38, 0x39, 0x41, 0x42, 0x43,
               0x44, 0x45, 0x46};

unsigned char WRITE , run = 1, stop = 1;;   // could be ADC or Eeprom
char time_var, time_cnt, timer;
unsigned int e_addr = 0;
unsigned int timer0;
char LcdBuffer[17];                   // a screen buffer
unsigned char time[8] = {1,2,5,10,20,50,100,200};
char I2CBuffer[64] ;

// The SDA and SCL pins are ALWAYS set at 0 we use tristated pins to
// control the control.. while SDA and SCL are inputs the external pullup
// resistors give a high conditon whilst when SDA or SCL are outputs
// the control lines are pulled low.

void main(void)               // program entry
   {
   unsigned char key, ch;           // key pressed
   unsigned char select = 0;
   OPTION = 0x88;             // timer pre-scaler
   CMCON = 0x7;             // Comparitors off
   LCD_TRIS = 0b00000000;         // Led port as outputs
   I2C_TRIS = 0b11111111;         // I2C  port
   OPTION = 0b10000101;
   __delay_ms(150);
   RA6 = 0;               // RW low
   RB6 = 0;
   RB7 = 0;
   I2C_PORT = 0;
   initTimer();
   LCD_init();                     // Initalise screen
   LCD_printC(" Pic Tutorial.\n Data logger.");     // "\n" = newline
   while(!getkey());
   LCD_clr();
   LCD_goto(2,0);
   LCD_printC("Menu  +  -  Set");
   getADC();
   while(1)                     // endless Loop
     {
     key = getkey();
     LCD_goto(1,0);
     switch (select)
       {
       case 0:
         LCD_printC("Write Memory?  ");
         break;
       case 1:
         LCD_printC("Read Memory?  ");
         break;
       case 2:
         LCD_printC("Set sample time?");
         break;
       case 3:
         LCD_printC("Clear Memory?  ");         
       }
     if(key == 2) select++;
     if(key == 3) select--;
     if(key == 1 ||  key==4)
       {
       if(select == 0) write_Mem();
       if(select == 1) read_Mem();
       if(select == 2) setTime();
       if(select == 3) clear_Mem();
       }
     select &= 3;
     }
   }

void initTimer()
   {
   TMR0 = -126;
   INTCON = 0b10100000;
   timer = 13;               //
   time_var = time[eeprom_read(0)];
   time_cnt = time_var;
   run = 0;
   stop = 1;
   }

void clear_Mem()
   {
   unsigned int index;
   unsigned char ch = 0;
   int key;
   LCD_goto(1,0);
   LCD_printC("Are you sure  ");
   LCD_goto(2,0);
   LCD_printC("No!  Yes  ");
   key = 0;
   for(index = 0;index<16; index++)
     I2CBuffer[index] = 0;
   while(!key)
     key = getkey();
   if(key==4)
     {
     WRITE = EEPROM;
     LCD_goto(1,0);
     LCD_printC("Clearing....  ");
     for(index = 0; index < 0x4000; index += 64)
       {
       E_Write(index,I2CBuffer,64);
       DelayMs(5);
       }
     LCD_goto(1,0);
     LCD_printC("Memory cleared  ");
     DelayMs(1000);
     e_addr = 0;
     LCD_goto(2,0);
     LCD_printC("Menu  +  -  Set");
     }
   
   }

void write_Mem()   
   {
   unsigned int index=0;
   int key;
   LCD_goto(1,0);
   LCD_printC("Writing.  ");
   WRITE = EEPROM;
   run = 0;
   while(1)
     {
     getADC();
     if(run && !stop)
       {
       WRITE = EEPROM;
       E_Write(index,I2CBuffer,4);
       index+=4;
       run = 0;
       }
     LCD_goto(1,11);
     sprintf(LcdBuffer,"%d", index);   
     LCD_printR(LcdBuffer);
     LCD_goto(2,0);
     sprintf(LcdBuffer,"%3d %3d %3d %3d ", I2CBuffer[1],I2CBuffer[2],I2CBuffer[3],I2CBuffer[0]);
     LCD_printR(LcdBuffer);
     key = getkey();
     if(key == 4)
       {
       GIE = 0;
       stop = 0;
       LCD_goto(2,0);
       LCD_printC("Menu  +  -  Set");
       e_addr = index;
       return;
       }
     if(key==2)    
       {
       stop = 0;
       }
     if(key==3)
       {
       stop = 1;
       }
     }
   }

void setTime()
   {
   unsigned int index;
   int key;
   LCD_goto(1,0);
   LCD_printC("Sample.  ");
   while(1)
     {
     LCD_goto(1,9);
     sprintf(LcdBuffer,"%d",index);
     LCD_printR(LcdBuffer);
     key = getkey();
     if(key==1 || key == 4)
       {
       eeprom_write(0,index);
       initTimer();
       return;
       }
     if(key == 2) index++;
     if(key == 3) index--;
     index &= 7;   
     }
   
   }

void read_Mem()
   {
   unsigned int index = 0;
   int key;
   LCD_goto(1,0);
   LCD_printC("Reading.  ");
   WRITE = EEPROM;
   while(1)
     {
     E_Read(index,I2CBuffer,4);
     LCD_goto(1,11);
     sprintf(LcdBuffer,"%5d", index);   
     LCD_printR(LcdBuffer);
     LCD_goto(2,0);
     sprintf(LcdBuffer,"%3d %3d %3d %3d ", I2CBuffer[0],I2CBuffer[1],I2CBuffer[2],I2CBuffer[3]);
     LCD_printR(LcdBuffer);
     key = getkey();
     if(key == 4 || key == 1)
       {
       LCD_goto(2,0);
       LCD_printC("Menu  +  -  Set");
       return;
       }
     if(key==2 && index < (e_addr -4) ) index += 4;
     if(key==3 && index > 4) index -= 4;
     }
   }   

int getADC()
   {
   unsigned char ch;
   WRITE = ADC;
   ch = 4;
   E_Write(0,&ch,1);
   E_Read(0,I2CBuffer,4);
   }

void interrupt isr()
   {
   TMR0 = -113;
   timer--;
   if(timer-- == 0)
     {
     timer = 13;
     if(time_cnt-- == 0)   
       {
       time_cnt = time_var;
       run = 1;
       }
     }
   T0IF = 0;
   }

// Write to eeprom this returns a 0 if it fails or a 1 if all gooes well
// For byte eeproms and RTC devices.. comment out the Hi address byte
// and the I2C_nack() that follows it in both these functions.

// As you're aware by now there are three kinds of eeprom reads / writes
// we need to combine the three.. Here is how I manage it
// Using the variable "Len" we can adjust, inside the function, which write / read
// we require..
// If len = 0.. We can assume no length so a '0' terminated string is assumed..
// If Len = 1.. We can assume a single (random) read..
// if Len > 1.. we can assume a squential write / read..


char E_Write(int addr, unsigned char* ch, char len)
   {
   I2C_Start();                   // Send a start condition
   I2C_Write(WRITE);                 // chip write address
   if(!I2C_nack()) return 0;             // wait for ack
   if(WRITE == 0xA0)
     {
     I2C_Write((unsigned char)( addr >> 8 & 0xff));// Not used if out if single byte address
     if(!I2C_nack()) return 0;           // wait for ack
     }
   if(!(WRITE==0x90))   
     {
     I2C_Write((unsigned char) addr & 0xff);     // low address (ADC not used)
     if(!I2C_nack()) return 0;           // wait for ack
     }
   if(len == 1)
     {
     I2C_Write(*ch);
     if(!I2C_nack()) return 0;
     }
   else if(len > 1)
     {           
     while(len--)
       {
       I2C_Write(*ch++);             // Write values to Eeprom
       if(!I2C_nack()) return 0;     
       }
     }
   else
     {
     while(*ch != 0)
       {
       I2C_Write(*ch++);             // Write values to Eeprom
       if(!I2C_nack()) return 0;
       }
     I2C_Write(0);                 // Write values to Eeprom
     if(!I2C_nack()) return 0;
     }
   I2C_Stop();                     // Send a stop.
   return 1;                     // All went well
   }

// Returns a 1 for error and 0 for OK.
// The function takes an address and a pointer to a character

unsigned char E_Read(int addr, unsigned char *ch, char len)
   {
   unsigned char byte;
   I2C_Start();
   I2C_Write(WRITE);
   if(!I2C_nack()) return  1;             // Whoops!! problems
   if(WRITE == 0xA0)
     {
     I2C_Write((unsigned char)( addr >> 8 & 0xff));// Not used if out if single byte address
     if(!I2C_nack()) return  1;
     }
   if(!(WRITE == 0x90))
     {
     I2C_Write((unsigned char) addr & 0xff);     // not use with ADC
     if(!I2C_nack()) return 1;
     }
   I2C_Start();
   I2C_Write(WRITE + CHIP_Read);               //
   if(!I2C_nack()) return  1;
   if(len == 1)                   // Read a single char.
     {
     *ch = I2C_Read();
     }
   else if(len > 1)                 // Read a sequential data steam
     {
     while(len-- > 1)
       {
       *ch++ = I2C_Read();             // read character
       I2C_ack();                 // Send ack
       }
     *ch = I2C_Read();
     }
   else                       // Read s NULL string
     {
     do{
       *ch = I2C_Read();
       I2C_ack();
       }while(*ch++ != 0);
     *ch = I2C_Read();
     }
   I2C_Sendnack();                   // send nack
   I2C_Stop();                     // send stop
   return 0;
   }

void I2C_Start()     //  start combo
   {       
   SDA = 1;
   SCL = 1;
   SDA = 0;       // bring SDA low while SCL is high
   SCL = 0;
   }

void I2C_Stop()       // stop combo
   {
   SCL = 0;
   SDA = 0;
   SCL = 1;
   SDA = 1;       // bring SDA high while SCL is high
   }

unsigned char I2C_Read()
   {
   char index;
   unsigned char byte = 0;             // initialize in byte
   for(index = 0x80; index > 0 ;index>>=1)     // using index as a mask
     {                     // cycles through bit 7 to bit 0
     if(SDAI) byte += index;           // read in the SDA line
     clock();
     }
   return byte;                 // 8 bits in...
   }

void I2C_Write(unsigned char ch)
   {
   char index;

   for(index = 0x80; index > 0 ;index>>=1)     // using index as mask
     {
     if(ch & index)                // bit high or low
       SDA = 1;
     else
       SDA = 0;
     clock();
     }
   }

void I2C_ack()               // generate an ack
   {
   SDA = 0;
   clock();
   SDA = 1;
   }

void I2C_Sendnack()             // generate a not ack
   {
   SDA = 1;
   clock();
   }

char I2C_nack()               // recive a not ack
   {
   unsigned char timeout = 255;
   SDA = 1;
   SCL = 1;
   while(SDAI)               // wait till SDA goes low
     {
     if(timeout-- == 0) return 0;   // whoops!! no ack recieved
     }
   SCL = 0;
   return 1;
   }

void clock()               // Might work without the nop
   {
   SCL=1;
   asm("nop");
   SCL=0;
   }

int getkey()               // read keypad
   {
   int key = 0;
   if(!RB0) key = 1;
   if(!RB1) key = 2;
   if(!RB2) key = 3;
   if(!RB3) key = 4;
   if(key)
     DelayMs(400);   
   return key;   
   }

void DelayMs(int dly)
   {
   while(dly--)
     __delay_ms(1);   
   }

// In C we can use Pointers, Pointers are advanced programming
// and can tie you in knots. The simplest pointer to use is the
// array pointer using "rom char" allows the pointer to
// point to constant character in code section.

void LCD_printC(const char * str)       // This passes the start a ROM character array
   {                     // by default the pointer points to data section
   while(*str != 0)             // while the character pointed to isn't 0
     {
     if(*str == 0x0A)
       LCD_goto(2,0);           // if a new line goto a newline
     else
       LCD_char(*str);
     str++;                 // print out the character, then increment
     }
   }                     // the pointer down the array

void LCD_printR(char * str)             // This passes the start of a RAM character array
   {                     // by default the pointer points to data section
   while(*str != 0)             // while the character pointed to isn't 0
     LCD_char(*str++);           // print out the character, then increment
   }                     // the pointer down the array

void LCD_init()
   {
   LCD_PORT = 2;           // I decided to write the first command
   LCD_RS = 0;             // manually, as the busy flag can't be read
   pulse_E();             // on the first instruction
   __delay_ms(50);
   LCD_PORT = 2;
   LCD_RS = 0;
   pulse_E();
   __delay_ms(50);           // busy should be available now..
   //LCD_cmd(0x20);         // 4 bit
   LCD_cmd(0x28);           // display shift
   LCD_cmd(0x6);           // character mode
   LCD_cmd(0xc);           // display on / off and cursor
   LCD_clr();             // clear display
   }

void LCD_hex(int value)
   {
   char data;
   data = value >> 4 & 0xf;
   data = HEX_Table[data];          // send upper nibble
   LCD_char(data);
   data = value & 0xf;             // send lower nibble
   data = HEX_Table[data];
   LCD_char(data);
   }

void LCD_goto(char line, char column)     // combines line and lineW
   {
   unsigned char data = 0x80;         // default to 1
   if(line == 2)data = 0xc0;         // change to 2
   data += column;               // add in  column
   LCD_cmd(data);
   }

void LCD_clr()
   {
   LCD_cmd(1);                 // Clr screen
   }

void LCD_cur(char on)
   {
   unsigned char cur = 0xc;         // cursor off
   if(on) cur = 0xd;             // cursor on
   LCD_cmd(cur);
   }

void LCD_cmd(unsigned char ch)
   {
   LCD_PORT = ch >> 4 & 0xf;
   LCD_RS = 0;
   pulse_E();
   LCD_PORT = ch & 0xf;
   LCD_RS = 0;
   pulse_E();
   __delay_ms(5);
   }

void LCD_charD(unsigned char ch)
   {
   ch+=0x30;
   LCD_char(ch);
   }

void LCD_char(unsigned char ch)
   {
   LCD_PORT = ch >> 4 & 0xf;
   LCD_RS = 1;
   pulse_E();
   LCD_PORT = ch & 0xf;
   LCD_RS = 1;
   pulse_E();
   __delay_ms(5);
   }

void pulse_E()
   {
   LCD_E = 1;
   __delay_us(1);
   LCD_E = 0;
   }
 
Hehe, the answer I usually find at the bottom of a bottle of Jack is "never again", I move onto the Bowmore and all is fine again :D
 
Hehe, the answer I usually find at the bottom of a bottle of Jack is "never again", I move onto the Bowmore and all is fine again :D
Bottle of Jack with some truth serum (sodium pentothol) -- in it? I invite everyone on this forum to come and drink with me! Nothing to worry about unless you are an paedophile.
 
Hello,
I will use 7 segment LED display..
only min and hours.
so, how to start in Hi tech c i have done i2C based project in BLDC ESC motor.

thanks
 
Hello,
I will use 7 segment LED display..
only min and hours.
so, how to start in Hi tech c i have done i2C based project in BLDC ESC motor.
Hi Tech C? What did you shell out USD 3K for it did you? I thought the FREE version did not handle the 16F series PICs. MikroC is a good buy for USD 249. I was tempted to purchase Hi Tech many years back on eBay... Too rich for me. Although I did pay AUD 1,500 for circuit maker 2000, and a couple of grand for QuarkXPress... But back in those days I had money. Now I am as poor as an ****-house rat.

No point me posting MikroC code since you are running Hi Tech. Otherwise I would help you out brother...
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top