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] [Help Needed] RTC with I2C codes in MikroC Pro

Status
Not open for further replies.

jinang

Junior Member level 1
Joined
May 14, 2011
Messages
15
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,532
Hi,

We're working on a project right now that needs the utilization of a Real Time Clock (RTC). However, in order for us to be able to use the RTC in our system that has a power window as motor (position dependent on the RTC), we were advised to use I2C. How do we utilize I2C in our code in MikroC Pro?

Please see our code and see what else is needed. Thank you.

unsigned char sec, min1, hr, week_day, day, mn, year;
char *txt, tnum[4];

void main() {
I2C1_Init(100000); // initialize full master mode

//--------------------- Reads time and date information from RTC (DS1307)
void Read_Time(char *sec, char *min, char *hr, char *week_day, char *day, char *mn, char *year) {
I2C1_Start(); // issue start signal
I2C1_Wr(0xD0);
I2C1_Wr(0);
I2C1_Repeated_Start();
I2C1_Wr(0xD1);
*sec =I2C1_Rd(1);
*min =I2C1_Rd(1);
*hr =I2C1_Rd(1);
*week_day =I2C1_Rd(1);
*day =I2C1_Rd(1);
*mn =I2C1_Rd(1);
*year =I2C1_Rd(1);
I2C1_Stop();
}

//-------------------- Formats date and time
void Transform_Time(char *sec, char *min, char *hr, char *week_day, char *day, char *mn, char *year) {
*sec = ((*sec & 0x70) >> 4)*10 + (*sec & 0x0F);
*min = ((*min & 0xF0) >> 4)*10 + (*min & 0x0F);
*hr = ((*hr & 0x30) >> 4)*10 + (*hr & 0x0F);
*week_day =(*week_day & 0x07);
*day = ((*day & 0xF0) >> 4)*10 + (*day & 0x0F);
*mn = ((*mn & 0x10) >> 4)*10 + (*mn & 0x0F);
*year = ((*year & 0xF0)>>4)*10+(*year & 0x0F);
}

//-------------------- Output values to LCD
void Display_Time(char sec, char min, char hr, char week_day, char day, char mn, char year) {
switch(week_day){
case 1: txt="Sun"; break;
case 2: txt="Mon"; break;
case 3: txt="Tue"; break;
case 4: txt="Wed"; break;
case 5: txt="Thu"; break;
case 6: txt="Fri"; break;
case 7: txt="Sat"; break;
}
LCD_Out(1,1,txt);
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, (mn / 10) + 48);
Lcd_Chr(1,10, (mn % 10) + 48);
Lcd_Chr(1,15, year + 48); // Print year vaiable + 8 (start from year 2008)

Lcd_Chr(2, 6, (hr / 10) + 48);
Lcd_Chr(2, 7, (hr % 10) + 48);
Lcd_Chr(2, 9, (min / 10) + 48);
Lcd_Chr(2,10, (min % 10) + 48);
Lcd_Chr(2,12, (sec / 10) + 48);
Lcd_Chr(2,13, (sec % 10) + 48);

}

//------------------ Performs project-wide init
void Init_Main() {
ANSEL=0;
ANSELH=0;

Lcd_Init(); // Initialize LCD
Lcd_Cmd(_LCD_CLEAR); // Clear LCD display
Lcd_Cmd(_LCD_CURSOR_OFF); // Turn cursor off

I2C1_Init(100000); // initialize I2C
LCD_Chr(1,8,'.');
LCD_Chr(1,11,'.');
txt = "Time:";
LCD_Out(2,1,txt);
LCD_Chr(2,8,':');
LCD_Chr(2,11,':');
txt = "201";
LCD_Out(1,12,txt);
LCD_Cmd(_LCD_CURSOR_OFF);
}

//----------------- Main procedure
void main() {
Init_Main(); // perform initialization
while (1) {
Read_Time(&sec,&min1,&hr,&week_day,&day,&mn,&year); // read time from RTC(DS1307)
Transform_Time(&sec,&min1,&hr,&week_day,&day,&mn,&year); // format date and time
Display_Time(sec, min1, hr, week_day, day, mn, year); // prepare and display on LCD
Delay_ms(1000); // wait 1s
}
}
 

we're using PIC 18F4550, and DS1307 RTC. thank you
 

Hi all,

I am currently working on a project using PIC18F4455 and RTC PCF8583. PIC18F4455 is almost the same with PIC16F877A, it's just that 18 has a USB feature and has higher memory. So for confirmation purposes, I tried it first in PIC16. I was able to run it successfully using PIC16F877A, however, when I tried it using the PIC18F4455, it does not count, just display what we have indicated in Lcd_Out. like 'Date: and Time:'. Kindly help me out on debugging the code below. THANK YOU VERY MUCH!

Code:
char seconds, minutes, hours, day, month, year;    // Global date/time variables

// Software I2C connections
sbit Soft_I2C_Scl           at RB1_bit;
sbit Soft_I2C_Sda           at RB0_bit;
sbit Soft_I2C_Scl_Direction at TRISB1_bit;
sbit Soft_I2C_Sda_Direction at TRISB0_bit;
// End Software I2C connections

// LCD module connections
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;

sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
// End LCD module connections

//--------------------- Reads time and date information from RTC (PCF8583)
void Read_Time() {

  Soft_I2C_Start();               // Issue start signal
  Soft_I2C_Write(0xA0);           // Address PCF8583, see PCF8583 datasheet
  Soft_I2C_Write(2);              // Start from address 2
  Soft_I2C_Start();               // Issue repeated start signal
  Soft_I2C_Write(0xA1);           // 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
  day = Soft_I2C_Read(1);         // Read year/day byte
  month = Soft_I2C_Read(0);       // Read weekday/month 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
  year     =   (day & 0xC0) >> 6;                             // Transform year
  day      =  ((day & 0x30) >> 4)*10    + (day & 0x0F);       // Transform day
  month    =  ((month & 0x10)  >> 4)*10 + (month & 0x0F);     // Transform month
}

//-------------------- 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,15,  year        + 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);
}


//------------------ Performs project-wide init
void Init_Main() {

  TRISB = 0;
  PORTB = 0xFF;
  TRISB = 0xff;
  SPPCON = 0x00;
  INTCON = 0x00;
  ADCON1 = 0x0F;

  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

  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,"201");       // start from year 2010
}

//----------------- Main procedure
void main() {
  Delay_ms(500);

  Init_Main();               // Perform initialization

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

Which of the two codes posted is the latest version? I guess the last one is the test with P16F.
I'm also guessing You're using EasyPIC. RB0 & RB1 are shared by RTC and LCD.
Try using P18F with software I2C (like P16F). If it works, than serial port configuration is messing with your LCD data (RB0 & RB1 are inputs).
 

we're using the codes I have posted yesterday. :) sorry for the confusion. yes we've used this code with PIC16, but scl and sda is initially set at RC3 and RC4 respectively. we're using EasyPIC5 for testing if the code works. it does with the PIC16. we also tried soft I2C already with PIC18 but we assume that it really do mess around with the RB1 and RB0 inputs since LCD also uses that port. is there any way that we can configure the PIC18? thank you very much! (or last option is to just set up the hardware in a breadboard can put the LCD inputs in a different port?)
 

There's the same problem in another thread with using LCD and RTC at the same time:
https://www.edaboard.com/threads/214835/

can put the LCD inputs in a different port?
I might be better if you have free port, to avoid he software acrobatics with LCD and I2C.
Just change this part of code to correspond to your new LCD connections.
Code:
// LCD module connections
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;

sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;


When writing to ports in P18F, use LATB instead of RB.
For example:
Code:
sbit LCD_RS at [B]RB4[/B]_bit;
should be
Code:
sbit LCD_RS at [B]LATB4[/B]_bit;
It goes for all ports, so it would be LATC if you switch.
 
  • Like
Reactions: jinang

    jinang

    Points: 2
    Helpful Answer Positive Rating
hi, thank you for the reply :)

we've tried to assemble the connection in a breadboard instead of the EASYPIC5 dev board. the LCD is now placed in PORTD so as to give way for RTC in PORTB since PIC18F4455's SCL and SDA is in RB1 and RB0 respectively. however, doing so still does not display anything, even the "Date:" and "Time" that we just coupled with Lcd_Out. i think we also have done the necessary configurations needed for the PIC to work properly along with the other registers multiplexed in ports B and D. do you have any other possible ideas on how we can work this out? thank you very very much!
 

As I see in datasheet, 18F4455 has only pins 0,5, 6 and 7 on PORTD. You probably have overlooked this (that might be the new LCD problem).
Try setting LCD on PORTC. Or even PORTB on pins 2-7, leaving pins 0,1 for RTC.

It's all might be some settings mistake in PIC18Fs config, since it already works with PIC16F.
I've never used PICs with USB, but I'm guessing that PLL is enabled, is correct frequency set in project settings (crystal*4 if PLL enabled).
Also swith that CCP mux setting to not interfere with Your LCD port.

Do You have a working serial connection? You could try sending the time value over RS232 to terminal (MicroC has inbuild one) just to make sure that I2C and calculations are working OK. Then we can be sure it's only the LCD config problem.
 

sorry but i didn't get it. what do you mean by "18F4455 has only pins 0,5, 6 and 7 on PORTD"? have reviewed the datasheet but port D has complete pins that can be reconfigured. thank you!

i have just tried having the LCD at portB along with the SCL and SDA. however, the wires are somewhat like overlapping since the RTC don't just use RB1 and RB0. it is presented in such a way that all 8 pins of the port it will be attached to is being occupied. all in all, it still doesn't work.

just to clarify, would the SPPCON register be shared by both RTC and LCD even though we use soft for the RTC. because if it does, i think the one should be 0x00 and the other is 0x01 because we have to enable one pin. thanks.
 

port D has complete pins that can be reconfigured.
You're right, sorry. I just glanced at block diagram which, for some weird reason, shows only pins I mentioned.
...... it is presented in such a way that all 8 pins of the port it will be attached to is being occupied....
Didn't cross my mind. I made a habit to always use bredboard for that reason.

When using software I2C, You need to set the pins as general I/O. And MikroC implements the routine to control the transfer, so disable the I2C module (if You didn't already) when You use Software I2C because it takes priority over digital on pins.
"SSPCON1.SSPEN = 0"; //Disables serial port and configures these pins as I/O port pins

Same goes for LCD, make all pins digital, all internal circuitry on the pins should be disabled (detached).
SPPCON = 0x00; //i guess

The "Soft_I2C_Init()" and "Lcd_Init()" routines should take care of port direction and initial pin states.
 
  • Like
Reactions: jinang

    jinang

    Points: 2
    Helpful Answer Positive Rating
thank you for the suggestion. we've tried it already, but it still does not work. i think we've done so many considerations already, so we opt to confirm first if the circuit itself is working. we first tried the working code for PIC16 and place it in the breadboard. upon trying so, it seems that it does not display anything unlike when it is plugged to the dev board, so there might be something wrong on the circuit since the working code applied in dev board does not work properly in breadboard. might be necessary if we check first the scgematic before we proceed with the testing. thank you very much for the assistance. :)
 

will you please give me the circuit connection for this code? can i use the code for pic 18f452?
Thank you.
 
Last edited:

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top