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....


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

 
The DS1307 ids the RTC I use... There is 8 registers at the beginning of the device that stores this..



You read the BCD values and display them however you want!!!
 
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...
 
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!.... 56bytes + 8 registers..... That's an even 64bytes... It makes perfect sense to me!!

I read every program cycle ( 3 times a second )
 
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
 
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
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.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…