help required to get RTC and pic16f877a going

Discussion in 'Embedded Systems and Microcontrollers' started by n_1_needs_help, Jun 8, 2014.

  1. n_1_needs_help

    Thread Starter New Member

    Jun 8, 2014
    5
    0
    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

    Code ( (Unknown Language)):
    1.  
    2. #include<pic.h>       //Define PIC Registers
    3. #include<stdio.h>            
    4.  
    5.          
    6. __CONFIG(0x3f72); //Select HS oscillator, Enable (PWRTE,BOREN),                  
    7. //Disable (CPD,CP,WDTEN,In-circuit Debugger)
    8.  
    9. //-----------defines section
    10. #define LC01CTRLIN    0xd0
    11. #define LC01CTRLOUT 0xd1
    12. #define I2C_FREG   100
    13. #define FOSC       20000
    14. #define BAUD_RATE   9.6       // 9600 Baud rate
    15. #define BAUD_VAL   (char)(FOSC/ (16 * BAUD_RATE )) - 1;          //Calculation For 9600 Baudrate @20Mhz  
    16. //note this is over-ridden below by setting SPBRG to 129
    17. unsigned char sec,min,hour,day,date,month,year;
    18. unsigned char data[7]={0x45,0x59,0x71,0x04,0x05,0x10,0x06};
    19. int i;
    20. void DS1307Write(unsigned char,unsigned char);            
    21. void WaitMSSP();                                
    22. unsigned char DS1307Read(unsigned char);
    23. void i2c_init(void);
    24. void ds1307_init(void);
    25. void serial_init(void);
    26. void putch(unsigned char byte);
    27. void DelayMs(unsigned int);
    28.  
    29. //--------main section
    30. void main()
    31.  {    
    32.  int count=0;  
    33.  DelayMs(20);    
    34.  ds1307_init();  
    35.  serial_init();  
    36.  for(i=0;i<7;i++)  
    37. {
    38.  DS1307Write(i,data[i]);
    39. }                            
    40.  printf("\033[2J");    
    41.  DelayMs(20);    
    42. while(1)    
    43.   {      
    44.   sec=DS1307Read(0);        // Read second      
    45.   min=DS1307Read(1);        // Read minute    
    46.   hour=DS1307Read(2);       // Read hour    
    47.   day=DS1307Read(3);        // Read day    
    48.   date=DS1307Read(4);       // Read date      
    49.   month=DS1307Read(5);      // Read month    
    50.   year=DS1307Read(6);       // Read year      
    51.   printf("Time: %x : %x : %x  ",(hour&0x1f),min,sec);   //Display the Hours, Minutes, Seconds(hours is taken from 5 LSB bits      
    52.   printf("Date: %x / %x / %x    \r",date,month,year);   //Display the Date, Month, Year    
    53.   DelayMs(150);    
    54.   }
    55. }        
    56.  
    57.  
    58. //-----------------code to write to RTC using i2c
    59. void DS1307Write(unsigned char addr, unsigned char data)
    60. {    
    61.   SEN=1;      //Initiate Start condition on SDA & SCL pins    
    62.   WaitMSSP();                              
    63.   SSPBUF=LC01CTRLIN;   // Slave address + Write command  
    64.   WaitMSSP();                            
    65.   SSPBUF=addr;         // Write the location  
    66.   WaitMSSP();                                
    67.   SSPBUF=data;         // Write the Data  
    68.   WaitMSSP();                                
    69.   PEN=1;               // Enable the Stop bit  
    70.   WaitMSSP();                                
    71. }  
    72.  
    73. //--------------------code to read RTC using I2C
    74. unsigned char DS1307Read(unsigned char addr)
    75. {
    76.    unsigned char x;
    77.    RSEN=1;   // Enable the repeated Start Condition
    78.    WaitMSSP ();                          
    79.    SSPBUF=LC01CTRLIN; // Slave address + Write command  
    80.    WaitMSSP ();                            
    81.    SSPBUF=addr;      //Write the location (memory address of Hour, minute, etc...  
    82.    WaitMSSP ();                            
    83.    RSEN=1;    // Enable the repeated Start Condition  
    84.    WaitMSSP ();                          
    85.    SSPBUF=LC01CTRLOUT; // Slave address + Read command  
    86.    WaitMSSP ();                          
    87.    RCEN=1;            // Enable to receive data  
    88.    WaitMSSP ();                            
    89.    ACKDT=1;    // Acknowledge the operation (Send NACK)  
    90.    ACKEN=1;    // Acknowledge sequence on SDA & SCL pins  
    91.    PEN=1;      // Enable the Stop bit  
    92.    WaitMSSP ();                          
    93.    x=SSPBUF;   // Store the Receive value in a variable
    94.    return (x);          
    95. }  
    96.  
    97. //---------------------wait I2C routine
    98. void WaitMSSP()
    99. {
    100.    while(!SSPIF); // SSPIF is zero while TXion is progress  
    101.    SSPIF=0;          
    102. }  
    103.  
    104. //-------------------------------------initialisation of I2C
    105.  
    106. void ds1307_init()
    107. {
    108.    TRISC3=1;      // RC3,RC4 set to I2C Mode(Input)  
    109.    TRISC4=1;  
    110.    SSPCON=0x28;   // Enable the SDA,SCL & I2C Master Mode  
    111.    SSPADD=(FOSC / (4 * I2C_FREG)) - 1;// SSP baud rate 100Khz  
    112.    SSPSTAT=0x80;  // Disable slew Rate control  
    113.    PORTC=0x18;  
    114.    DS1307Write(0,0x00);  
    115.  
    116. //---------------------initialise serial communications for USART
    117. }   void serial_init()
    118. {
    119.   TRISC6=1;     // RC7, RC6 set to USART Mode
    120.   TRISC7=1;  
    121.   TXSTA=0x24; // Enable Transmission, Asynchronous mode, High Speed mode
    122. //  SPBRG=BAUD_VAL;    // 9600 Baud rate selection
    123.   SPBRG=129;  
    124.   RCSTA=0x90;   // Enable Serial Port & Continuous Reception  
    125.   BRGH=1;
    126.   TXIF=1;       // Enable Transmission
    127. }  
    128.  
    129. //------------usart putch
    130. void putch(unsigned char byte)//Required for printf statement
    131. {                  
    132.    while(!TXIF); // Wait for the Transmit Buffer to be empty
    133.    TXREG = byte; // Transmit the Data
    134. }
    135. //--------------delay routine
    136. void DelayMs(unsigned int Ms)
    137. {  
    138.   int delay_cnst;    
    139.   while(Ms>0)    
    140.   {      
    141.    Ms--;    
    142.    for(delay_cnst = 0;delay_cnst <420;delay_cnst++);  
    143.    }
    144. }
    145. [/i]


    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: Jun 9, 2014
  2. shteii01

    AAC Fanatic!

    Feb 19, 2010
    3,383
    495
  3. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    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!
     
  4. n_1_needs_help

    Thread Starter New Member

    Jun 8, 2014
    5
    0
    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
     
  5. THE_RB

    AAC Fanatic!

    Feb 11, 2008
    5,435
    1,305
    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.
     
  6. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    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.
     
  7. n_1_needs_help

    Thread Starter New Member

    Jun 8, 2014
    5
    0
    it was something I wasn't expecting. I feel like a complete munter
     
Loading...