1. 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.
    Dismiss Notice

Master Slave Clocks with PIC16F887

Discussion in 'Microcontrollers' started by koolguy, Mar 31, 2015.

  1. koolguy

    koolguy Active Member

    Joined:
    Aug 24, 2010
    Messages:
    2,196
    Likes:
    9
    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
     
  2. koolguy

    koolguy Active Member

    Joined:
    Aug 24, 2010
    Messages:
    2,196
    Likes:
    9
    Hello,
    The data sheet says....

    00 to 007h mean display register!
    But what about 08h to 3fH mean here?
     
  3. koolguy

    koolguy Active Member

    Joined:
    Aug 24, 2010
    Messages:
    2,196
    Likes:
    9
    Hello, i got this code but not understanding working!

     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,142
    Likes:
    907
    Location:
    Rochdale UK

    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!!!
     
    • Like Like x 1
  6. koolguy

    koolguy Active Member

    Joined:
    Aug 24, 2010
    Messages:
    2,196
    Likes:
    9
    What the use of Ram after 08H addr?
     
  7. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,142
    Likes:
    907
    Location:
    Rochdale UK
    Whatever you wish.... It's NON volatile so you can save variables in there ( same as eeprom, but full speed writing )
    As the DS1307 ram is SRAM there are no writing limitations...
     
  8. koolguy

    koolguy Active Member

    Joined:
    Aug 24, 2010
    Messages:
    2,196
    Likes:
    9
    Why manufacture give this option is there any specific reason?
    and do i have to read time from i every minutes or every sec?
     
  9. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,142
    Likes:
    907
    Location:
    Rochdale UK
    Think!.... 56bytes + 8 registers..... That's an even 64bytes... It makes perfect sense to me!!

    I read every program cycle ( 3 times a second )
     
  10. koolguy

    koolguy Active Member

    Joined:
    Aug 24, 2010
    Messages:
    2,196
    Likes:
    9
    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?
     
  11. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,142
    Likes:
    907
    Location:
    Rochdale UK
    This is going to be hard work..... Just copy the code in tutorial 6... Everything is in there..
    Use the code as you will...
    Code (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;
       }
     
     
  12. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,142
    Likes:
    907
    Location:
    Rochdale UK
    If you want the hardware I2C routines just ask!!!
     
  13. Brevor

    Brevor Member

    Joined:
    Feb 3, 2007
    Messages:
    528
    Likes:
    14
    Location:
    Chicago USA
    deleted
     
    Last edited: Apr 4, 2015
  14. MCU88

    MCU88 Member

    Joined:
    Apr 1, 2015
    Messages:
    121
    Likes:
    7
    hahaha....
    You think the answer is at the bottom of a bottle of Jack Daniels?
     
  15. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,142
    Likes:
    907
    Location:
    Rochdale UK
    ???? Not sure I follow...
     
  16. tunedwolf

    tunedwolf Well-Known Member

    Joined:
    Aug 9, 2006
    Messages:
    1,080
    Likes:
    62
    Location:
    UK
    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
     
  17. MCU88

    MCU88 Member

    Joined:
    Apr 1, 2015
    Messages:
    121
    Likes:
    7
    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.
     
  18. koolguy

    koolguy Active Member

    Joined:
    Aug 24, 2010
    Messages:
    2,196
    Likes:
    9
    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
     
  19. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,142
    Likes:
    907
    Location:
    Rochdale UK
    • Like Like x 1
  20. koolguy

    koolguy Active Member

    Joined:
    Aug 24, 2010
    Messages:
    2,196
    Likes:
    9
    Hello,
    i am watching but need to understand it more clearly!
     
  21. MCU88

    MCU88 Member

    Joined:
    Apr 1, 2015
    Messages:
    121
    Likes:
    7
    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...
     

Share This Page