Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] Software RTC I2C interfacing

Status
Not open for further replies.

varunme

Advanced Member level 3
Joined
Aug 10, 2011
Messages
741
Helped
17
Reputation
36
Reaction score
17
Trophy points
1,318
Activity points
5,764
My code for interfacing RTC through software i2C not working in real hardware, but it does in proteus simulation

Code:
                               unsigned short skp;

// Software I2C connections// Software I2C connections
sbit Soft_I2C_Scl           at RC3_bit;
sbit Soft_I2C_Sda           at RC4_bit;
sbit Soft_I2C_Scl_Direction at TRISC3_bit;
sbit Soft_I2C_Sda_Direction at TRISC4_bit;
// End Software I2C connections

// LCD module connections
sbit LCD_RS at RD2_bit;  // for writing to output pin always use latch (PIC18 family)
sbit LCD_EN at RD3_bit;  // for writing to output pin always use latch (PIC18 family)
sbit LCD_D4 at RD4_bit;  // for writing to output pin always use latch (PIC18 family)
sbit LCD_D5 at RD5_bit;  // for writing to output pin always use latch (PIC18 family)
sbit LCD_D6 at RD6_bit;  // for writing to output pin always use latch (PIC18 family)
sbit LCD_D7 at RD7_bit;  // for writing to output pin always use latch (PIC18 family)

sbit LCD_RS_Direction at TRISD2_bit;
sbit LCD_EN_Direction at TRISD3_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
// End LCD module connections

char seconds, minutes, hours, wday,day, month, year; // Global date/time variables
char  keypadPort at PORTD;


void Read_Time() {

  Soft_I2C_Start();               // Issue start signal
  Soft_I2C_Write(0xD0);           // Address PCF8583, see PCF8583 datasheet
  Soft_I2C_Write(0);              // Start from address 2
  Soft_I2C_Start();               // Issue repeated start signal
  Soft_I2C_Write(0xD1);           // Address PCF8583 for reading R/W=1

  seconds = Soft_I2C_Read(1);     // Read seconds byte
  minutes = Soft_I2C_Read(1);     // Read minutes byte
  hours = Soft_I2C_Read(1);       // Read hours byte
  wday = Soft_I2C_Read(1);         // Week Day not use
  day = Soft_I2C_Read(1);         // Read year/day byte
  month = Soft_I2C_Read(1);       // Read weekday/month byte
  year = Soft_I2C_Read(0);        // Read Year byte
  Soft_I2C_Stop();                // Issue stop signal
}


//-------------------- Formats date and time
void Transform_Time() {
  seconds  =  ((seconds & 0xF0) >> 4)*10 + (seconds & 0x0F);  // Transform seconds
  minutes  =  ((minutes & 0xF0) >> 4)*10 + (minutes & 0x0F);  // Transform months
  hours    =  ((hours & 0xF0)  >> 4)*10  + (hours & 0x0F);    // Transform hours
  day      =  ((day & 0xf0) >> 4)*10    + (day & 0x0F);       // Transform day
  month    =  ((month & 0xF0)  >> 4)*10 + (month & 0x0F);     // Transform month
  year     =  ((year & 0xf0) >> 4)*10    + (year & 0x0F);       // Transform year
}

//-------------------- Output values to LCD
void Display_Time() {

   Lcd_Chr(1, 6, (day / 10)   + 48);    // Print tens digit of day variable
   Lcd_Chr(1, 7, (day % 10)   + 48);    // Print oness digit of day variable
   Lcd_Chr(1, 9, (month / 10) + 48);
   Lcd_Chr(1,10, (month % 10) + 48);
   Lcd_Chr(1,14,  year / 10   + 48);    // Print year variable  (start from year 2010)
   Lcd_Chr(1,15,  year % 10   + 48);    // Print year variable  (start from year 2010)

   Lcd_Chr(2, 6, (hours / 10)   + 48);
   Lcd_Chr(2, 7, (hours % 10)   + 48);
   Lcd_Chr(2, 9, (minutes / 10) + 48);
   Lcd_Chr(2,10, (minutes % 10) + 48);
   Lcd_Chr(2,12, (seconds / 10) + 48);
   Lcd_Chr(2,13, (seconds % 10) + 48);
}
char Ds1307_HexFormat(char val){
//int xval=0;
    return((val/10)*16)+(val%10);
    //return xval;
}


void Update_DateTime(int val,int loc){
//Location
// 0-SS   4-DD
// 1-mm   5-Mn
// 2-HH   6-YY
// 3-Wd
   switch (loc){
     case 0: val=0x00; break;
     case 1: if (val>59) val=0x00; if (val<0) val=60+val; break;
     case 2: if (val>23) val=0x00; if (val<0) val=24+val; break;
     case 3: val=0x00; break;
     case 4: if (val>31) val=0x01; if (val<1) val=31+val; break;
     case 5: if (val>12) val=0x01; if (val<1) val=12+val; break;
     case 6: if (val>99) val=0x00; if (val<1) val=99+val; break;
   }

   Soft_I2C_Init();       // Initialize full master mode
   Soft_I2C_Start();      // Issue start signal
   Soft_I2C_Write(0xD0);  // Address PCF8583, see PCF8583 datasheet
   Soft_I2C_Write(loc);     // Start from address 0 (configuration memory location)
   Soft_I2C_Write(Ds1307_HexFormat(val));  //Hours Location  (hh)
   Soft_I2C_Stop();       // Issue stop signal
   Soft_I2C_Start();      // Issue start signal
   Soft_I2C_Write(0xD0);  // Address PCF8530
   Soft_I2C_Write(0);     // Start from address 0
   Soft_I2C_Write(0);     // Write 0 to configuration memory location (enable counting)
   Soft_I2C_Stop();       // Issue stop signal

}

void Disp_tmplt(){
  Lcd_Cmd(_LCD_CLEAR);       // Clear LCD display
  Lcd_Out(1,1,"Date:");      // Prepare and output static text on LCD
  Lcd_Chr(1,8,'.');
  Lcd_Chr(1,11,'.');
  Lcd_Chr(1,16,'.');
  Lcd_Out(2,1,"Time:");
  Lcd_Chr(2,8,':');
  Lcd_Chr(2,11,':');
  Lcd_Out(1,12,"20");       // start from year 2010
}

//------------------ Performs project-wide init

void Disp_Mode(int xM){
         switch (xM){
                case 0:lcd_out(2,15,"SS");break;
                case 1:lcd_out(2,15,"MI");break;
                case 2:lcd_out(2,15,"HH");break;
                case 3:lcd_out(2,15,"WD");break;
                case 4:lcd_out(2,15,"DD");break;
                case 5:lcd_out(2,15,"MO");break;
                case 6:lcd_out(2,15,"YY");break;
                default :lcd_out(2,15,"  ");
         }
}



void Init_Main() {
  trisa=0;
  porta=0;
  TRISB = 0;
  PORTB = 0xFF;
  TRISB = 0xff;
  ADCON0=0;
  ADCON1=0;

  Keypad_Init();
  Soft_I2C_Init();           // Initialize Soft I2C communication
  Lcd_Init();                // Initialize LCD
  Lcd_Cmd(_LCD_CLEAR);       // Clear LCD display
  Lcd_Cmd(_LCD_CURSOR_OFF);  // Turn cursor off
  Disp_tmplt();
}


void main() {
  Delay_ms(500);
  Init_Main();               // Perform initialization



    while (1){
          Read_Time();             // Read time from RTC(PCF8583)
          Transform_Time();        // Format date and time
          Display_Time();          // Prepare and display on LCD
          delay_ms(1000);

}
}

it shows invalid characters for date and time
 

varunme,


What is the reason to you insert a value '1' and '0' as argument to the function Soft_I2C_Read() ?
That is not usual, at most I2C libraries.

+++
 

from mikroC documentation
its


unsigned short Soft_I2C_Read(unsigned int ack);

removing 1 and 0 gives compiler error saying "no enough arguments"
 

What does not work in real hardware? Do you not see anything in the LCD? Or is the time-keeping erroneous? Did you use a 32.768kHz crystal as required? Did you connect a battery? If you need battery backup, you must connect a battery, if not, the pin should be shorted.
 

yes, battery is there,
Seing something in LCD , but some unrecognized characters, plus 20 for year
32Khz crystal is there
 

Did you set the contrast of the LCD properly? Did you set the configuration bits of the PIC properly when burning it? Did you use the proper crystal with the required frequency?

The DS1307 needs a 32.768kHz crystal, not just 32kHz. That will give you inaccuracies.

Which PIC are you using? Can you upload the hex file and the DSN file?
 

Here is the DSN and hex file
I am using the same 32.768, actually this is a module which I bought
 

Attachments

  • RTCmod.zip
    34.7 KB · Views: 64

Which module are you talking about?

In the simulation file, you didn't attach a crystal oscillator. Simulation is fine without it. Did you connect a 20MHz crystal in the hardware? Did you burn the PIC with the correct configuration bits settings?
 

yes,
I disabled, WDT, BODEN, .... all

is there any fuse for the RTC to work ?

module
**broken link removed**

and the board is
**broken link removed**

The display is refreshing every second, but not updating or having correct characters.

---------- Post added at 08:22 ---------- Previous post was at 07:22 ----------

Some problems were there at the headers of RTC board,
I dry soldered it,
Now
For the date all are zero and 2000
ie : 00 00 2000
and for time 00 00 80
 
Last edited:

Make sure all connections are solid and that none of them are loose. Solder all connections across boards. This could be your problem.
Since it works properly on simulation with no warnings or errors, most probably, software is completely fine. Problem is either in hardware or burning your PIC.
Check all connections.
 

Double checked all connections and dry soldered, but now too no luck,
is there a need for adding a delay somewhere ?
 

I added a starting date and time to the code and removed a part of it. Try running it now and post the results.

In the mikroC window, goto to the Project Menu. Click Edit Project. Set the configuration settings properly. Make sure you have HS selected for the oscillator.

Code:
                               unsigned short skp;

// Software I2C connections// Software I2C connections
sbit Soft_I2C_Scl           at RC3_bit;
sbit Soft_I2C_Sda           at RC4_bit;
sbit Soft_I2C_Scl_Direction at TRISC3_bit;
sbit Soft_I2C_Sda_Direction at TRISC4_bit;
// End Software I2C connections

// LCD module connections
sbit LCD_RS at RD2_bit;  // for writing to output pin always use latch (PIC18 family)
sbit LCD_EN at RD3_bit;  // for writing to output pin always use latch (PIC18 family)
sbit LCD_D4 at RD4_bit;  // for writing to output pin always use latch (PIC18 family)
sbit LCD_D5 at RD5_bit;  // for writing to output pin always use latch (PIC18 family)
sbit LCD_D6 at RD6_bit;  // for writing to output pin always use latch (PIC18 family)
sbit LCD_D7 at RD7_bit;  // for writing to output pin always use latch (PIC18 family)

sbit LCD_RS_Direction at TRISD2_bit;
sbit LCD_EN_Direction at TRISD3_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
// End LCD module connections

char seconds, minutes, hours, wday,day, month, year; // Global date/time variables
char  keypadPort at PORTD;


void Read_Time() {

  Soft_I2C_Start();               // Issue start signal
  Soft_I2C_Write(0xD0);           // Address PCF8583, see PCF8583 datasheet
  Soft_I2C_Write(0);              // Start from address 2
  Soft_I2C_Start();               // Issue repeated start signal
  Soft_I2C_Write(0xD1);           // Address PCF8583 for reading R/W=1

  seconds = Soft_I2C_Read(1);     // Read seconds byte
  minutes = Soft_I2C_Read(1);     // Read minutes byte
  hours = Soft_I2C_Read(1);       // Read hours byte
  wday = Soft_I2C_Read(1);         // Week Day not use
  day = Soft_I2C_Read(1);         // Read year/day byte
  month = Soft_I2C_Read(1);       // Read weekday/month byte
  year = Soft_I2C_Read(0);        // Read Year byte
  Soft_I2C_Stop();                // Issue stop signal
}


//-------------------- Formats date and time
void Transform_Time() {
  seconds  =  ((seconds & 0xF0) >> 4)*10 + (seconds & 0x0F);  // Transform seconds
  minutes  =  ((minutes & 0xF0) >> 4)*10 + (minutes & 0x0F);  // Transform months
  hours    =  ((hours & 0xF0)  >> 4)*10  + (hours & 0x0F);    // Transform hours
  day      =  ((day & 0xf0) >> 4)*10    + (day & 0x0F);       // Transform day
  month    =  ((month & 0xF0)  >> 4)*10 + (month & 0x0F);     // Transform month
  year     =  ((year & 0xf0) >> 4)*10    + (year & 0x0F);       // Transform year
}

//-------------------- Output values to LCD
void Display_Time() {

   Lcd_Chr(1, 6, (day / 10)   + 48);    // Print tens digit of day variable
   Lcd_Chr(1, 7, (day % 10)   + 48);    // Print oness digit of day variable
   Lcd_Chr(1, 9, (month / 10) + 48);
   Lcd_Chr(1,10, (month % 10) + 48);
   Lcd_Chr(1,14,  year / 10   + 48);    // Print year variable  (start from year 2010)
   Lcd_Chr(1,15,  year % 10   + 48);    // Print year variable  (start from year 2010)

   Lcd_Chr(2, 6, (hours / 10)   + 48);
   Lcd_Chr(2, 7, (hours % 10)   + 48);
   Lcd_Chr(2, 9, (minutes / 10) + 48);
   Lcd_Chr(2,10, (minutes % 10) + 48);
   Lcd_Chr(2,12, (seconds / 10) + 48);
   Lcd_Chr(2,13, (seconds % 10) + 48);
}
char Ds1307_HexFormat(char val){
//int xval=0;
    return((val/10)*16)+(val%10);
    //return xval;
}


void Update_DateTime(int val,int loc){
//Location
// 0-SS   4-DD
// 1-mm   5-Mn
// 2-HH   6-YY
// 3-Wd
   switch (loc){
     case 0: val=0x00; break;
     case 1: if (val>59) val=0x00; if (val<0) val=60+val; break;
     case 2: if (val>23) val=0x00; if (val<0) val=24+val; break;
     case 3: val=0x00; break;
     case 4: if (val>31) val=0x01; if (val<1) val=31+val; break;
     case 5: if (val>12) val=0x01; if (val<1) val=12+val; break;
     case 6: if (val>99) val=0x00; if (val<1) val=99+val; break;
   }

   Soft_I2C_Init();       // Initialize full master mode
   Soft_I2C_Start();      // Issue start signal
   Soft_I2C_Write(0xD0);  // Address PCF8583, see PCF8583 datasheet
   Soft_I2C_Write(loc);     // Start from address 0 (configuration memory location)
   Soft_I2C_Write(Ds1307_HexFormat(val));  //Hours Location  (hh)
   Soft_I2C_Stop();       // Issue stop signal
   //Soft_I2C_Start();      // Issue start signal
   //Soft_I2C_Write(0xD0);  // Address PCF8530
   //Soft_I2C_Write(0);     // Start from address 0
   //Soft_I2C_Write(0);     // Write 0 to configuration memory location (enable counting)
   //Soft_I2C_Stop();       // Issue stop signal

}

void Disp_tmplt(){
  Lcd_Cmd(_LCD_CLEAR);       // Clear LCD display
  Lcd_Out(1,1,"Date:");      // Prepare and output static text on LCD
  Lcd_Chr(1,8,'.');
  Lcd_Chr(1,11,'.');
  //Lcd_Chr(1,16,'.');
  Lcd_Out(2,1,"Time:");
  Lcd_Chr(2,8,':');
  Lcd_Chr(2,11,':');
  Lcd_Out(1,12,"20");       // start from year 2010
}

//------------------ Performs project-wide init

void Disp_Mode(int xM){
         switch (xM){
                case 0:lcd_out(2,15,"SS");break;
                case 1:lcd_out(2,15,"MI");break;
                case 2:lcd_out(2,15,"HH");break;
                case 3:lcd_out(2,15,"WD");break;
                case 4:lcd_out(2,15,"DD");break;
                case 5:lcd_out(2,15,"MO");break;
                case 6:lcd_out(2,15,"YY");break;
                default :lcd_out(2,15,"  ");
         }
}



void Init_Main() {
  trisa=0;
  porta=0;
  TRISB = 0;
  PORTB = 0xFF;
  TRISB = 0xff;
  ADCON0=0;
  ADCON1=0;

  Keypad_Init();
  Soft_I2C_Init();           // Initialize Soft I2C communication
  Lcd_Init();                // Initialize LCD
  Lcd_Cmd(_LCD_CLEAR);       // Clear LCD display
  Lcd_Cmd(_LCD_CURSOR_OFF);  // Turn cursor off
  Disp_tmplt();
  
  Update_DateTime(0,0);
  Update_DateTime(5,1);
  Update_DateTime(14,2);
  Update_DateTime(22,4);
  Update_DateTime(1,5);
  Update_DateTime(12,6);
}


void main() {
  Delay_ms(500);
  Init_Main();               // Perform initialization



    while (1){
          Read_Time();             // Read time from RTC(PCF8583)
          Transform_Time();        // Format date and time
          Display_Time();          // Prepare and display on LCD
          delay_ms(1000);

}
}

Hope this helps.
Tahmid.
 
  • Like
Reactions: varunme

    varunme

    Points: 2
    Helpful Answer Positive Rating
yes,
its working,
but time not correct,
For that, i have to set it using pushbutton isnt it ?

by modifying

Code:
  Update_DateTime(0,0);
  Update_DateTime(5,1);
  Update_DateTime(14,2);
  Update_DateTime(22,4);
  Update_DateTime(1,5);
  Update_DateTime(12,6);
 

Yes.
You can see in the code that location 0 is for seconds, 1 for minutes, 2 for hours, 4 for day, 5 for month, 6 for year:
// 0-SS 4-DD
// 1-mm 5-Mn
// 2-HH 6-YY
// 3-Wd

Hope this helps.
Tahmid.
 
  • Like
Reactions: varunme

    varunme

    Points: 2
    Helpful Answer Positive Rating
can you figure out simple method to do the time and date change with pushbutton ?
i have to change the seconds or minitues or hours isnt it ?, remaining will change by itself isnt it ?
 
Last edited:

Yes, you have to change seconds, minutes or hours. Since you want to show date, you need to change day, month and year as well.

What do you mean by simple method?
You can have one button for setting time. When this button (let's call it X) is pressed, the PIC halts the clock of DS1307 and waits for setting of seconds either from an increase or decrease button. If X is pressed again, the PIC waits for setting of minutes from those two buttons. When X is pressed again, PIC waits for setting of hours, and then day, month and year each time X is pressed. So, you can set it with 3 push-buttons.

Hope this helps.
Tahmid.
 
  • Like
Reactions: varunme

    varunme

    Points: 2
    Helpful Answer Positive Rating
The button for getting into setup mode has to be connected to interrupt isnt it ?
 

It's better if it's in interrupt, but polling will do as well. You can poll and say, set a flag to 1. If that flag is 0, the program works by displaying time, date and working as a clock. When flag is 1, everything stops. Interrupt's better, but polling will do.

Hope this helps.
Tahmid.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top