pic18+ds1307+lcd: I am facing a problem in my program.

Status
Not open for further replies.

ARAVINDHANK

Newbie level 6
Joined
Jan 23, 2013
Messages
12
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Visit site
Activity points
1,353
The LCD is displaying time and date along with some symbols in between in a fluctuating manner. Please some one help me to solve the problem.
Code:
#include <p18f4520.h>
#include <delays.h>
#include <i2c.h> 
#include <stdio.h> 
//#define _XTAL_FREQ 4000000 // 4 MHz clock 

//__CONFIG(0X3F39);
#define LCD_EN PORTCbits.RC2
#define	LCD_RS PORTCbits.RC0
#define	LCD_RW PORTCbits.RC1
#define LCD_DATA LATD
#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};
unsigned char I2CInitval[]= {0x00,0x00,0x12,0x01,0x23,0x01,0x13};
unsigned char tmp;
unsigned char i;
unsigned int j;
void MSDelay(unsigned int itime)
{
unsigned int i,j;

for(i=0;i<itime;i++)
for(j=0;j<135;j++);
}
void I2CWait(){
        while ( ( SSPCON2 & 0x1F ) || ( SSPSTAT & 0x04 ) );		/* wait for any pending transfer */

}

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

void I2CStart(){
		I2CWait(); 
        SSPCON2bits.SEN = 1;         	
        while(SSPCON2bits.SEN);    /*Start Condition Enable*/
                    	
}

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

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

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

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

void I2CSend(unsigned char dat){
	
        SSPBUF = dat;    		/* Move data to SSPBUF */
        while(SSPSTATbits.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 */
        SSPCON2bits.RCEN = 1;        		/* Enable data reception */
        while(!SSPSTATbits.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;
MSDelay(1);
LCD_EN = 0;

	}

void lcdcmd(unsigned char value)
	{
LCD_DATA = value;
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 1;
MSDelay(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 lcd_init(){

	TRISD	= 0;
	TRISB	= 0;
	TRISCbits.TRISC7  = 0;
	TRISCbits.TRISC6  = 0;
	LCD_EN =0;
	MSDelay(175);
	lcdcmd(0x38);
	lcdcmd(0x0c);
	lcdcmd(0x01);
	lcdcmd(0x80);
				}


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 display (){
	unsigned int i,j;
	lcdcmd(0x80);
	for (i=0;i<5;i++)
			{
		lcddata(time[i]);
			}
	bcdToascii(I2CData[2]);
	lcddata(':');
	bcdToascii(I2CData[1]);
	lcddata(':');
	bcdToascii(I2CData[0]);
	
	lcdcmd(0xc0);
	for (j=0;j<5;j++)
			{
		lcddata(date[j]);
			}
	bcdToascii(I2CData[4]);
	lcddata('-');
	bcdToascii(I2CData[5]);
	lcddata('-');
		
	lcddata('2');lcddata('0');
//bcdToascii(I2CData[5]);
	bcdToascii(I2CData[6]);
}
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(); /*this line when enabled, makes the timer to reset after 2 minutes but LCD faces no fluctuation in displaying*/	
			I2CNak();
	 		I2CStop(); /* Send stop */								
}

void main(){ 
TRISCbits.TRISC0  = 0;
TRISCbits.TRISC1  = 0;
TRISCbits.TRISC2  = 0;
        I2CInit();
        lcd_init();       
		I2Cwrite();
display();
lcdcmd(0x94);
		lcddata('A');
while(1){

        I2Cread();
		display();
				
}
}
 
Last edited by a moderator:

Have you connected pullup resistors to SCL and SDA lines? Have you written the time to ds1307? Are you using C18 compiler?

When you call i2c_write() it has i2c_stop() function inside. So the i2c is stopped. Then when you call i2c_read() it has i2c_start() inside and i2c is started. But that is not the way. You should not stop and start the i2c. remove the stop_i2c() from i2c_write() and remove i2c_start() from i2c_read()
 
Last edited:

In your Code I dont see you sending ACK and NACK command to the Slave (DS1307). After sending a byte to ds1307 send ACK command.
here is what you can do
Code:
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]);
	I2CAck();				/* send I2C data one by one */			
        }
 

The LCD is displaying time and date along with some symbols in between in a fluctuating manner.

Dear ARAVINDHANK;

You made ​​one(?) usual fatal error in your code:

Code:
.....
unsigned char I2CData[]   = {0x00,0x01,0x40,0x03,0x04,0x05,0x06};
unsigned char I2CInitval[]= {0x00,0x00,0x12,0x01,0x23,0x01,0x13};
       [COLOR="#0000FF"]The above arrays have[/COLOR] [COLOR="#FF0000"]7[/COLOR] [COLOR="#0000FF"]emements: name[0] to[/COLOR] [COLOR="#FF0000"]name[6] !!!!!!!!!![/COLOR]
.....
void I2Cwrite(){
.....
     for(i=0;i < [COLOR="#FF0000"]8[/COLOR] ;i++) { /* Loop to write [COLOR="#FF0000"]8[/COLOR] bytes */
        I2CSend(I2CInitval[i]); [COLOR="#FF0000"]//the last I2CInitval[7] is a garbage !!![/COLOR]
     }
...
}
.....
void I2Cread(){
.....
    for(i=0;i<7;i++) {
	
      I2CData[i] = I2CRead();	 [COLOR="#0000FF"]// OK, the last I2CData[6] is valid[/COLOR]
      I2CAck();    
    }

/*this line when enabled, makes the timer to reset after 2 minutes but LCD faces no fluctuation ..*/
    //I2CData[i] = I2CRead(); 
[COLOR="#FF0000"]//because now 'i' is equal to 7 and I2CData[7] is an invalid address, overwrite anything.[/COLOR]
....
}

Better to get any help: upload your DSN and also the source.
zuisti
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…