help required to get RTC and pic16f877a going

Thread Starter

n_1_needs_help

Joined Jun 8, 2014
5
Hi
I am using DS1307 and pic16f877a, I am trying to get the RTC to print out on usart and am having all sorts of problems, the code I am using is presented below

Rich (BB code):
#include<pic.h>       //Define PIC Registers
#include<stdio.h>            

         
__CONFIG(0x3f72); //Select HS oscillator, Enable (PWRTE,BOREN),                   
//Disable (CPD,CP,WDTEN,In-circuit Debugger) 

//-----------defines section
#define LC01CTRLIN    0xd0 
#define LC01CTRLOUT 0xd1 
#define I2C_FREG   100 
#define FOSC       20000 
#define BAUD_RATE   9.6       // 9600 Baud rate 
#define BAUD_VAL   (char)(FOSC/ (16 * BAUD_RATE )) - 1;          //Calculation For 9600 Baudrate @20Mhz  
//note this is over-ridden below by setting SPBRG to 129 
unsigned char sec,min,hour,day,date,month,year; 
unsigned char data[7]={0x45,0x59,0x71,0x04,0x05,0x10,0x06}; 
int i; 
void DS1307Write(unsigned char,unsigned char);            
void WaitMSSP();                                 
unsigned char DS1307Read(unsigned char); 
void i2c_init(void);
void ds1307_init(void); 
void serial_init(void); 
void putch(unsigned char byte);
void DelayMs(unsigned int);

//--------main section
void main()
 {     
 int count=0;   
 DelayMs(20);    
 ds1307_init();   
 serial_init();   
 for(i=0;i<7;i++)  
{ 
 DS1307Write(i,data);
}                             
 printf("\033[2J");     
 DelayMs(20);     
while(1)    
  {       
  sec=DS1307Read(0);        // Read second       
  min=DS1307Read(1);        // Read minute     
  hour=DS1307Read(2);       // Read hour     
  day=DS1307Read(3);        // Read day     
  date=DS1307Read(4);       // Read date       
  month=DS1307Read(5);      // Read month     
  year=DS1307Read(6);       // Read year      
  printf("Time: %x : %x : %x  ",(hour&0x1f),min,sec);   //Display the Hours, Minutes, Seconds(hours is taken from 5 LSB bits       
  printf("Date: %x / %x / %x    \r",date,month,year);   //Display the Date, Month, Year     
  DelayMs(150);    
  } 
}        


//-----------------code to write to RTC using i2c
void DS1307Write(unsigned char addr, unsigned char data) 
{    
  SEN=1;      //Initiate Start condition on SDA & SCL pins    
  WaitMSSP();                               
  SSPBUF=LC01CTRLIN;   // Slave address + Write command   
  WaitMSSP();                             
  SSPBUF=addr;         // Write the location   
  WaitMSSP();                                 
  SSPBUF=data;         // Write the Data   
  WaitMSSP();                                 
  PEN=1;               // Enable the Stop bit   
  WaitMSSP();                                
}   

//--------------------code to read RTC using I2C
unsigned char DS1307Read(unsigned char addr) 
{ 
   unsigned char x; 
   RSEN=1;   // Enable the repeated Start Condition 
   WaitMSSP ();                          
   SSPBUF=LC01CTRLIN; // Slave address + Write command  
   WaitMSSP ();                            
   SSPBUF=addr;      //Write the location (memory address of Hour, minute, etc...  
   WaitMSSP ();                            
   RSEN=1;    // Enable the repeated Start Condition  
   WaitMSSP ();                           
   SSPBUF=LC01CTRLOUT; // Slave address + Read command  
   WaitMSSP ();                           
   RCEN=1;            // Enable to receive data  
   WaitMSSP ();                            
   ACKDT=1;    // Acknowledge the operation (Send NACK)  
   ACKEN=1;    // Acknowledge sequence on SDA & SCL pins  
   PEN=1;      // Enable the Stop bit  
   WaitMSSP ();                           
   x=SSPBUF;   // Store the Receive value in a variable 
   return (x);           
}   

//---------------------wait I2C routine
void WaitMSSP() 
{ 
   while(!SSPIF); // SSPIF is zero while TXion is progress  
   SSPIF=0;          
}   

//-------------------------------------initialisation of I2C

void ds1307_init() 
{ 
   TRISC3=1;      // RC3,RC4 set to I2C Mode(Input)  
   TRISC4=1;  
   SSPCON=0x28;   // Enable the SDA,SCL & I2C Master Mode  
   SSPADD=(FOSC / (4 * I2C_FREG)) - 1;// SSP baud rate 100Khz  
   SSPSTAT=0x80;  // Disable slew Rate control  
   PORTC=0x18;  
   DS1307Write(0,0x00);  

//---------------------initialise serial communications for USART
}   void serial_init() 
{ 
  TRISC6=1;     // RC7, RC6 set to USART Mode 
  TRISC7=1;  
  TXSTA=0x24; // Enable Transmission, Asynchronous mode, High Speed mode 
//  SPBRG=BAUD_VAL;    // 9600 Baud rate selection
  SPBRG=129;  
  RCSTA=0x90;   // Enable Serial Port & Continuous Reception  
  BRGH=1;
  TXIF=1;       // Enable Transmission 
}   

//------------usart putch
void putch(unsigned char byte)//Required for printf statement 
{                  
   while(!TXIF); // Wait for the Transmit Buffer to be empty
   TXREG = byte; // Transmit the Data 
} 
//--------------delay routine 
void DelayMs(unsigned int Ms) 
{   
  int delay_cnst;    
  while(Ms>0)    
  {       
   Ms--;    
   for(delay_cnst = 0;delay_cnst <420;delay_cnst++);  
   } 
} 


The response using Realterm through the usart is
"Time: 1f : ff : ff Date: ff / ff / ff"
Any help would be appreciated
 
Last edited by a moderator:

ErnieM

Joined Apr 24, 2011
8,377
I am using DS1307 and pic16f877a, I am trying to get the RTC to print out on usart and am having all sorts of problems
Without a description of specific issues I doubt anyone will read your code to determine what is wrong and what is right.

Break the problem up into several smaller problems like links in a chain. Get each link to work in turn then move onto the next:
-Print dummy data on the USART.
-Convert dummy data into strings and send thru USART.
-Read the time/date, convert and send thru the USART.

You may well break this up into many more steps.

And welcome to the forums!
 

Thread Starter

n_1_needs_help

Joined Jun 8, 2014
5
Hi, the problem was solved the code worked it just needed to flush (cycle the power) to the RTC clock. I spent a whole day on it and then cycled the power and it all worked. I think the RTC can seize up or something after this experience.
Thanks
 

THE_RB

Joined Feb 11, 2008
5,438
You should hold the RTC chip in reset while the microcontroller boots up, and leave it in reset for 100-200mS for the PSU voltages to stabilise etc.

After that time you can bring the RTC out of reset and start comms to it.

The first thing in main() should be your port pin setups, for TRIS (direction) and to set the pin states (which puts the RTC into reset). Then you add the safety delay of 100-200mS, then after that you can init() the RTC.
 

ErnieM

Joined Apr 24, 2011
8,377
I'd avoid trying to reset the DS device as it doesn't have any sort of reset input pin; the only way to reset anything on it is to remove the main power, or just bring it below 1.25 times the battery voltage.

What oft happens (to me at least) is when debugging I2C devices the slave device gets left in ACK mode. When a slave ACKs a transaction it brings the data line low awaiting the next clock. If the master gets reset when the master tries to use the I2C it sees this low and (per the I2C spec) assumes another master is online and waits for it to complete.

But as there is no other master the bus just gets stalled. Or some I2C code does not check the ACK value and joyfully returns garbage from devices it never saw.

The workaround is to just wiggle the clock line a few times until the data line comes high, issue a STOP, then go about normal business.

As far as I can tell this condition only occurs in the debug phase, as it is rare the controller gets reset "in the real world" without a power interruption.
 
Top