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] DS1307 +lcd using PIC

Status
Not open for further replies.

zakir_cool

Junior Member level 3
Joined
Sep 27, 2012
Messages
31
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Activity points
1,558
Hi...i am trying a C code for RTC using PIC...I am not getting the exact thing,which i want to, So can any body suggest me..that what mistake i have done..the main thing is in 8051 my program is running fine. bt here i dont know when the ack and Nack should send...i gone throgh the data sheet of DS1307.i did't got it..

This is the main file..


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <htc.h>
#include "i2c.c"
#include "rtc.c"
#include "lcd.c"
#include "header.h"
 
//clock[]={seconds,minutes,hours,day_of_week,date,month,year};
    unsigned char I2CData[] = {0x00, 0x15, 0x11, 0x01, 0x25, 0x01, 0x09, 0x12};
    unsigned char *s[]={"SUN","MON","TUE","WED","THU","FRI","SAT"};
    unsigned char add = 0, d;
 
void main()
{
    
    TRISB =0x00; // Configure PORTB as output
    TRISD=0x00;
    TRISC=0x00;
    init_lcd();
    I2CInit(); //DS1307 I2C is running at 100KHz
  
      
            while(add<=6)   //update real time clock
                        {
   
                       write_ds1307(add,I2CData[add]); 
                       add++;   
                       }
                    
        while(1)
        {
            d=read_ds1307(0x02);//read hour 
            write_lcd((d/16)+48);
            write_lcd((d%16)+48);
            delay_ms(10);
            write_lcd(':');
            d=read_ds1307(0x01); // read minute;
            write_lcd((d/16)+48);
            write_lcd((d%16)+48);
            delay_ms(10);
            write_lcd(':');
            d=read_ds1307(0x00); // read second
            write_lcd((d/16)+48);
            write_lcd((d%16)+48);
            delay_ms(10);
            write_lcd(' ');
           display_lcd(s[read_ds1307(0x03)]); // read day
            delay_ms(10);
            cmd_lcd(0xc0);
            d=read_ds1307(0x04); // read date
            write_lcd((d/16)+48);
            write_lcd((d%16)+48);
            delay_ms(10);
             write_lcd('/');
            d=read_ds1307(0x05); // read month
            write_lcd((d/16)+48);
            write_lcd((d%16)+48);
            delay_ms(10);
            write_lcd('/');
            write_lcd('2');
            write_lcd('0');
            d=read_ds1307(0x06); // read year
            write_lcd((d/16)+48);
            write_lcd((d%16)+48);
            delay_ms(75);
            cmd_lcd(0x01);
        }
}




This is RTC file...


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include "header.h"
 
 
unsigned char read_ds1307(unsigned char address)
{  
    unsigned char data;
    I2CStart();
      
    I2CSend(0xd0); //address 0x68 followed by direction bit (0 for write, 1 for read) 0x68 followed by 0 --> 0xD0
    I2CAck();
    I2CSend(address);
    I2CAck();
    I2CRestart();
    I2CSend(0xd1); //0x68 followed by 1 --> 0xD1
   I2CAck();
      data=I2CRead();
    I2CNak();
    I2CStop();
    delay_ms(10);
    return(data);
}
 
void write_ds1307(unsigned char address,unsigned char w_data)
{
 
I2CStart(); // issue I2C start signal
 
//address 0x68 followed by direction bit (0 for write, 1 for read) 0x68 followed by 0 --> 0xD0
I2CSend(0xD0); // send byte via I2C (device address + W)
I2CAck();
I2CSend(address); // send byte (address of DS1307 location)
I2CAck();
I2CSend(w_data); // send data (data to be written)
I2CAck();
I2CStop(); // issue I2C stop signal
delay_ms(10);
}



And this I2C file...


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include "header.h"
 
void I2CInit()
{
        TRISC3 = 1;      /* SDA and SCL as input pin */
        TRISC4 = 1;      /* these pins can be configured either i/p or o/p */
        SSPSTAT = 0x80; /* Slew rate disabled */
        SSPCON = 0x28;   /* SSPEN = 1, I2C Master mode, clock = FOSC/(4 * (SSPADD + 1)) */
        SSPADD = 0x28;    /* 100Khz @ 4Mhz Fosc */
}
 
/*
Function: I2CStart
Return:
Arguments:
Description: Send a start condition on I2C Bus
*/
void I2CStart()
{        
        I2CWait();
         SEN = 1;         /* Start condition enabled */
        while(SEN);      /* automatically cleared by hardware */
                     /* wait for start condition to finish */
}
 
/*
Function: I2CStop
Return:
Arguments:
Description: Send a stop condition on I2C Bus
*/
void I2CStop()
{
        I2CWait();
        PEN = 1;         /* Stop condition enabled */
        while(PEN); /* PEN automatically cleared by hardware */     
                      /* Wait for stop condition to finish */
}
 
/*
Function: I2CRestart
Return:
Arguments:
Description: Sends a repeated start condition on I2C Bus
*/
void I2CRestart()
{ 
         I2CWait();
        RSEN = 1;        /* Repeated start enabled */
        while(RSEN);     /* wait for condition to finish */
}
 
/*
Function: I2CAck
Return:
Arguments:
Description: Generates acknowledge for a transfer
*/
void I2CAck(){
        ACKDT = 0;       /* Acknowledge data bit, 0 = ACK */
        ACKEN = 1;       /* Ack data enabled */
        while(ACKEN);    /* wait for ack data to send on bus */
}
 
/*
Function: I2CNck
Return:
Arguments:
Description: Generates Not-acknowledge for a transfer
*/
void I2CNak(){
        ACKDT = 1;       /* Acknowledge data bit, 1 = NAK */
        ACKEN = 1;       /* Ack data enabled */
        while(ACKEN);    /* wait for ack data to send on bus */
}
 
/*
Function: I2CWait
Return:
Arguments:
Description: wait for transfer to finish
*/
void I2CWait(){
        while ( ( SSPCON2 & 0x1F ) || ( SSPSTAT & 0x04 ) );
    /* wait for any pending transfer */
}
 
/*
Function: I2CSend
Return:
Arguments: dat - 8-bit data to be sent on bus
           data can be either address/data byte
Description: Send 8-bit data on I2C bus
*/
void I2CSend(unsigned char dat)
{
      //display_lcd("It's done here");  
        SSPBUF = dat;    /* Move data to SSPBUF */
        while(BF);      /* wait till complete data is sent from buffer */
       I2CWait();       /* wait for any pending transfer */
 
}
 
 
/*
Function: I2CRead
Return:    8-bit data read from I2C bus
Arguments:
Description: read 8-bit data from I2C bus
*/
unsigned char I2CRead(void){
        unsigned char temp;
/* Reception works if transfer is initiated in read mode */
        RCEN = 1;        /* Enable data reception */
        while(!BF);      /* wait for buffer full */
        //BF = 1;
        temp = SSPBUF;   /* Read serial buffer and store in temp register */
        I2CWait();       /* wait to check any pending transfer */
        return temp;     /* Return the read data from bus */
}

 
Last edited by a moderator:

Hello!

Some remarks:

* I don't know what PIC you use, but anyway instead of re-inventing I2C yourself, you
may consider using a device with an I2C engine.

* You are including C files:
Code:
#include "i2c.c"
#include "rtc.c"
#include "lcd.c"
As a rule: NEVER include C files. Include only headers.
If you include C files, you will compile everything everytime. Not a problem for short programs, but
it's a very bad way to write code.

* If you have a problem, then you should explain what the problem is. Here we don't know what happens
except that it doesn't work. You may consider splitting a big problem into smaller problems.
- Does your I2C code work?
In particular
1. Does the RTC acknowledge to its own address?
2. Are you able to read data from the RTC?
3. Are you able to retrieve the whole time buffer?
4. Are you able to write a character to the LCD?
5. Are you able to write a number to the LCD.

Review these items and never go to item n+1 if item n is not solved.
And in the future, try to focus on one bug at a time, try to find exactly where
things go wrong. You publish 50 ~ 100 lines of code, I don't feel like reading it all,
and I guess many people are like me.

Dora
 
  • Like
Reactions: PA3040

    PA3040

    Points: 2
    Helpful Answer Positive Rating
ya...i like ur suggestion...let me try...and thnks for ur kind reply...
 

Dear zakir,

Hopes this will help you. This is working find for me with PIC 16f877a LCD 8bit mode + DS1307
Code:
#include <htc.h>
#define _XTAL_FREQ 4000000 // 4 MHz clock 

__CONFIG(0X3F39);
#define LCD_EN RB3
#define	LCD_RS RB5
#define	LCD_RW RB4
#define LCD_DATA	PORTD
#define	LCD_STROBE()	((LCD_EN = 1),(LCD_EN=0))
unsigned char date [5] = {"Date:"};
unsigned char time [5] = {"Time:"};

unsigned char I2CData[]= {0x00,0x01,0x40,0x03,0x04,0x05,0x06,0x07};
unsigned I2CInitval  []= {0x55,0x59,0x23,0x29,0x29,0x20,0x12,0x20};
unsigned char tmp;
unsigned char i;

void I2CWait(){
        while ( ( SSPCON2 & 0x1F ) || ( SSPSTAT & 0x04 ) );		/* wait for any pending transfer */

}

void I2CInit(void){
        TRISC3 = 1;      	/* SDA and SCL as input pin */
        TRISC4 = 1;      	/* these pins can be configured either i/p or o/p */
        SSPSTAT |= 0x80; 	/* Slew rate disabled */
        SSPCON = 0x28;   	/* SSPEN = 1, I2C Master mode, clock = FOSC/(4 * (SSPADD + 1)) */
        SSPADD = 0x28;    	/* 100Khz @ 4Mhz Fosc */
}

void I2CStart(){
		I2CWait(); 
        SEN = 1;         	
        while(SEN);      	
                    	
}

void I2CStop(){
        PEN = 1;         	/* Stop condition enabled */
        while(PEN);      	/* Wait for stop condition to finish */
                     		/* PEN automatically cleared by hardware */
}

void I2CRestart(){
        RSEN = 1;        	/* Repeated start enabled */
        while(RSEN);     	/* wait for condition to finish */
}

void I2CAck(){
        ACKDT = 0;       	/* Acknowledge data bit, 0 = ACK */
        ACKEN = 1;       	/* Ack data enabled */
        while(ACKEN);    	/* wait for ack data to send on bus */
}

void I2CNak(){
        ACKDT = 1;       	/* Acknowledge data bit, 1 = NAK */
        ACKEN = 1;       	/* Ack data enabled */
        while(ACKEN);    	/* wait for ack data to send on bus */
}

void I2CSend(unsigned char dat){
	
        SSPBUF = dat;    		/* Move data to SSPBUF */
        while(BF);       		/* wait till complete data is sent from buffer */
        I2CWait();       		/* wait for any pending transfer */
}

unsigned char I2CRead(void){
		I2CWait(); 						/* Reception works if transfer is initiated in read mode */
        RCEN = 1;        		/* Enable data reception */
        while(!BF);      		/* wait for buffer full */
        return SSPBUF;   		/* Read serial buffer and store in temp register */
        	     				/* wait to check any pending transfer */	     
}

void lcddata(unsigned char value)
	{

LCD_DATA = value;
LCD_RS = 1; 
LCD_RW = 0;
LCD_EN = 1;
__delay_ms (1);
LCD_EN = 0;

	}

void lcdcmd(unsigned char value)
	{
LCD_DATA = value;
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 1;
__delay_ms (1);
LCD_EN = 0;

	}

void bcdToascii(unsigned char value){

	tmp = value;
	tmp = tmp & 0xf0;
	tmp = tmp >> 4;
	tmp = tmp | 0x30;
	lcddata(tmp);
	tmp = value;
	tmp = tmp & 0x0f;
	tmp = tmp | 0x30;
	lcddata(tmp);

}

void display (){
lcdcmd(0x80);
for (char i=0;i<5;i++)
			{
		lcddata(time[i]);
			}
	bcdToascii(I2CData[2]);
	lcddata('-');
	bcdToascii(I2CData[1]);
	lcddata('-');
	bcdToascii(I2CData[0]);
	
	lcdcmd(0xc0);
for (char j=0;j<5;j++)
			{
		lcddata(date[j]);
			}
	bcdToascii(I2CData[3]);
	lcddata('-');
	bcdToascii(I2CData[4]);
	lcddata('-');	
	bcdToascii(I2CData[5]);
	bcdToascii(I2CData[6]);
}
void lcd_init(){

TRISD	= 0;
TRISB	= 0;
TRISC7  = 0;
TRISC6  = 0;
LCD_EN =0;
__delay_ms(175);
lcdcmd(0x38);
__delay_ms(175);
lcdcmd(0x0a);
__delay_ms(15);
lcdcmd(0x01);
__delay_ms(10);
lcdcmd(0x06);
__delay_ms(10);
lcdcmd(0x80);
__delay_ms(10);
lcdcmd(0x0c);
__delay_ms(10);
				}


void I2Cwrite(){
											/* Initialize I2C Port */
 		I2CStart();						/* Send Start condition */
        I2CSend(0xD0);					/* Send DS1307 slave address with write operation */
        I2CSend(0x00);						/* Send subaddress 0x00, we are writing to this location */
			for(i=0;i<8;i++) {			/* Loop to write 8 bytes */
            	I2CSend(I2CInitval[i]);							/* send I2C data one by one */			
        }
			I2CStop();							/* Send a stop condition - as transfer finishes */
}

void I2Cread(){
        I2CStart();
		I2CSend(0xD0);							/* Send slave address with write */ /* Send address for dummy write operation *//* this address is actually where we are going to read from */					       						       
        I2CSend(0x00);							/* Send a repeated start, after a dummy write to start reading */
        I2CRestart();
        I2CSend(0xD1);										/* send slave address with read bit set */
  
			for(i=0;i<7;i++) {
      			I2CData[i] = I2CRead();			/* read a byte */								/* ACK if its not the last byte to read */             	 
				I2CAck();	
        }
			I2CData[i] = I2CRead();	
			I2CNak();
	 		I2CStop(); /* Send stop */								
}

void main(){        
        I2CInit();
        lcd_init();       
		I2Cwrite();
		
while(1){
		
        I2Cread();			
		display();
		
}
}
 
@PA3040
Thanks for your support sir...but Your code is also not working fine in Proteus.i tried to modify your code also.bt i did't got.tell whether there will be any probs in proteus or in code???

regard
Zakir
 

Hi Zakir;
In Proteus try to change the 'Model Type' of both I2C pullup resistors to DIGITAL.
 

Thanks for info....ya..i tried that too...i am getting some junk value...actually...its not writing to Ds1307...What will be prob with the code...
 

how to update RTC ???i have done as per I2C...bt still not working.Can any body tell,what mistake i have done...??
 

Hi Zakir;
Here is a well working and debuggable Proteus project (NOT mine !). Written in Boost C, no LCD but RS232 Virtual Terminal, however I hope it helps you.
 

Attachments

  • DS1307_project.rar
    27.1 KB · Views: 75

@zuisti:
Thnks fr ur kind reply....bt i want to know wht mistake i have done, in-order not to repeat in future...the thing is, i have used i2c debugger in proteus..all data is writing...while reading it only reading first 3 data..though i have used a for loop for <6.After each and every data its giving Ack. After 3rd data i.e(0x02) its giving NAck,instead it should give after 0x12 right???

Code:
unsigned char I2CData[] = {0x00, 0x25, 0x15, 0x02, 0x25, 0x10, 0x12};
void I2Cread()
{
I2CStart();
I2CSend(0xD0);
I2CSend(0x00);
I2CRestart();
I2CSend(0xD1);

for(i=0;i<6;++i)
{
d = I2CRead();
I2CAck();
}

d = I2CRead();
I2CNak();
I2CStop();
}
 

Your above code snippet contains recursive calls, ie the function void I2Cread() calls itself: d = I2CRead(); ???
Or the two names (I2Cread and I2CRead) are different in your compiler? Which compiler are you using?

Attach here the whole, source level debuggable Proteus project!
 

Dear zuisti,

It is wonder if my code is non working, try again. it is working for me
 

@Zuisti
I didn't told that ur code is not working,sir. I told that,i want to know what mistake i have done in my code,thn only i will come to know where i am standing. .actually that function is not recursive...i have used in different method...i have mentioned that function is for reading purpose for ur understanding. here is my complete source code,u will come to know..Thanks..

Regard
Zakir

- - - Updated - - -

here the complete source code...

regard
zakir
 

Attachments

  • RTC_PIC.rar
    119.6 KB · Views: 63
  • RTC_PIC.rar
    119.6 KB · Views: 51

Hi zakir_cool;
I was talking about the routine in your above post #10, that's recursive unless your compiler is case sensitive (as I wrote).

The attached simulation project is working if the usual two I2C pullups are applied, but the time displaying is bad, because of inadequate addressing of the data. For example, 'minute' is not D[2] but D[1], the 'year' is not D[5] but D[6] and so on.
If you change the HEX to COF in the Proteus, you can debug it at source level.

I'm not using (and don't like) the HI-Tech C, so I cannot modify and recompile your source, sorry.
 

@Zuisti:
No prob's...and thanks for supporting me..why i have changed that address of data means,i didn't got,the exact data...for that i have changed that..even though i have applied, two I2C pullups,i am just getting seconds,minutes and hour...(that too interchange value) .
If you don't mind can changed that much part and send to me in notepad itself..i will be thank full you.

regard
Zakir
 

@all
Finally i got the output..thanks 2 all for supporting me...

regards
Zakir
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top