#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();
}
}