/****************************************************************
*
* www.payitforward.edu.vn
*
****************************************************************/
/****************************************************************
*
* PIC Training Course
*
****************************************************************/
/****************************************************************
*
* Module : DS1307.c
* Description : Reading time through UART & Writing on Real-time
* clock DS1307 through I2C Communication
* Tool : HI-TECH PIC
* Chip : 16F887
* History : 07/05/2011
*
* Author : Nguyen Tien Manh, CLB NCKH
* Notes : C3-K09
*
*
****************************************************************/
/****************************************************************
* IMPORT
****************************************************************/
#include <htc.h>
__CONFIG(XT & WDTDIS & PWRTEN & MCLREN & UNPROTECT & SWBOREN &
IESODIS & FCMDIS & LVPDIS & DEBUGDIS); //1st config. Word
__CONFIG(BORV21); //2st config. Word
#define _XTAL_FREQ 4000000
#include "lcd.h" // lcd definition
#include "i2c.h" // i2c definition
#include "uart.h" // uart definition
// DS1307 7-bit address = 0b 110 1000 = 0x68 (I2C address)
#define SLAVE_ADD 0x68
#define READ 1
#define WRITE 0
/****************************************************************
* EXTERN
****************************************************************/
//extern void Exit(void);
/*none...*/
/*****************************************************************
GLOBAL VARIABLE
******************************************************************/
unsigned char sec, min, hour, day, date, month, year, tm0i = 0, c[30];
/*****************************************************************
* ROUTINES
******************************************************************/
void timer0_init()
{
T0CS = 0; // T0 internal Clock Source
PSA = 0; // Prescale Assignment: Timer0
// PS Prescale Rate Select
PS2 = 1;
PS1 = 1;
PS0 = 1; // Timer0 rate: 1:256
TMR0 = 0x00 ; // T0 Module Register
// Set up Interrupt
GIE = 1; // Gobal Interrupt Enable
T0IE = 1; //T0 Interrupt Enable
T0IF = 0; // Set off T0 Interrupt Flag
}
void clock_write() // Write data to DS1307 through I2C
{
/*/// Input data for setting manually
sec = 0x00 ; // CH=0 (bit7, clock-counting) and seconds = 00
min = 0x40 ; // minutes = 40
hour = 0x19 ; // hour-mode = 24-hour (bit 6) and hours = 19
day = 0x01 ; // day = sunday
date = 0x08 ; // date = 08
month = 0x05 ; // month = 05
year = 0x11 ; // year = 2011
///.. */
/// Writing..
//Send Start condition
i2c_start();
//Send Slave address + WRITE command
i2c_write((SLAVE_ADD<<1)|WRITE);
// ((SLAVE_ADD<<1)| WRITE) = ((0x68<<1)|0) = 0xD0
//Send register address (register of Slave – the first register need to read data)
i2c_write(0x00);
//write data
i2c_write(sec); // write to 0x00
i2c_write(min); // write to 0x01
i2c_write(hour); // write to 0x02
i2c_write(day); // write to 0x03
i2c_write(date); // write to 0x04
i2c_write(month); // write to 0x05
i2c_write(year); // write to 0x06
//Send Stop condition
i2c_stop();
///..
}
void clock_read() // Read data from DS1307 through I2C
{
//Send Start condition
i2c_start();
//Send Slave address + WRITE command
i2c_write((SLAVE_ADD<<1)|WRITE);
// ((SLAVE_ADD<<1)| WRITE) = ((0x68<<1)|0) = 0xD0
//Send register address (register of Slave – the first register need to read data)
i2c_write(0x00);
//ReStart condition
i2c_stop();
i2c_start();
//Send Slave address + READ command
i2c_write((SLAVE_ADD<<1)|READ);
// ((SLAVE_ADD<<1)| READ) = ((0x68<<1)|1) = 0xD1
//read data
sec = i2c_read(0); //read from 0x00 & ACK
min = i2c_read(0); //read from 0x01 & ACK
hour = i2c_read(0); //read from 0x02 & ACK
day = i2c_read(0); //read from 0x03 & ACK
date = i2c_read(0); //read from 0x04 & ACK
month = i2c_read(0); //read from 0x05 & ACK
year = i2c_read(1); //read from 0x06 & NACK
//Send Stop condition
i2c_stop();
}
void lcd_display() //Display Data on LCD
{
lcd_gotoxy(0,0);
switch (day)
{
case 2: lcd_puts("Mon"); break;
case 3: lcd_puts("Tue"); break;
case 4: lcd_puts("Wed"); break;
case 5: lcd_puts("Thu"); break;
case 6: lcd_puts("Fri"); break;
case 7: lcd_puts("Sat"); break;
default: lcd_puts("Sun"); break;
}
lcd_gotoxy(6,0);
lcd_putc((date>>4) + 0x30);
lcd_putc((date&0x0F) + 0x30);
lcd_putc('/');
lcd_putc((month>>4) + 0x30);
lcd_putc((month&0x0F) + 0x30);
lcd_puts("/20");
lcd_putc((year>>4) + 0x30);
lcd_putc((year&0x0F) + 0x30);
lcd_gotoxy(0,1);
lcd_puts("T.MANH");
lcd_gotoxy(8,1);
lcd_putc((hour>>4) + 0x30);
lcd_putc((hour&0x0F) + 0x30);
lcd_putc(':');
lcd_putc((min>>4) + 0x30);
lcd_putc((min&0x0F) + 0x30);
lcd_putc(':');
lcd_putc((sec>>4) + 0x30);
lcd_putc((sec&0x0F) + 0x30);
}
unsigned char num(unsigned char c) // check char c
{
if (c<'0' || c>'9')
return 0;
else
return 1; // return 0 if char c is a number.
}
void time_receive()
{
/* Time format:
d dd/mm/yyyy hh:mm:ss ==> 21 character before Enter
Ex: 1 08/05/2011 08:45:00 is Sunday, 8/5/2011, 8h45m (24 hour mode)
*/
unsigned i, ok = 0;
uart_puts("\r\n\r\nMoi nhap thoi gian. Dinh dang: d dd/mm/yyyy hh:mm:ss.");
while (!ok)
{
uart_puts("\r\n Chuoi nhap: ");
for (i=0; i<22; i++) // Wait & Receive 22 character
{
c[i] = uart_getc();
if (c[i] == '\r') break;
uart_putc(c[i]);
}
if (num(c[0])&&num(c[2])&&num(c[3])&&num(c[5])&&num(c[6])
&&num(c[8])&&num(c[9])&&num(c[10])&&num(c[11])
&&num(c[13])&&num(c[14])&&num(c[16])&&num(c[17])&&num(c[19])&&num(c[20])) // check for numbers
{
ok = 1;
uart_puts("\r\n Da nhap thoi gian.");
}
else
{
ok = 0;
uart_puts("\r\n Nhap sai dinh dang! Moi nhap lai.");
}
};
}
unsigned char char2bcd (unsigned char c) // convert char type to BCD type.
{
return (c - 0x30);
}
void time_convert() // Convert input time into format of register in DS1307.
{
sec = (char2bcd(c[19])<<4) + char2bcd(c[20]) ;
min = (char2bcd(c[16])<<4) + char2bcd(c[17]) ;
hour = (char2bcd(c[13])<<4) + char2bcd(c[14]) ;
day = char2bcd(c[0]) ;
date = (char2bcd(c[2])<<4) + char2bcd(c[3]) ;
month = (char2bcd(c[5])<<4) + char2bcd(c[6]) ;
year = (char2bcd(c[10])<<4) + char2bcd(c[11]) ;
}
void interrupt isr() // interrupt service rountine
{
if (T0IF && T0IE) //Interrupt Flag is on
{
T0IF =0;
TMR0 = 0;
tm0i++;
if (tm0i == 4)
{
// Display Time in DS1307 on LCD through interrupt of timer0.
clock_read();
lcd_display();
tm0i = 0;
}
}
}
/****************************************************************
* MAIN
****************************************************************/
/* -- void main (void) -----------------------------------------
*
* Description : UART, PIC, I2C & DS1307
* Notes :
*/
void main(void)
{
timer0_init();
i2c_init();
uart_init();
lcd_init();
__delay_ms(10);
lcd_clear();
lcd_puts("..starting...");
__delay_ms(80);
lcd_clear();
clock_read(); // Display the old time on DS1307.
lcd_display();
while(1)
{
//Reading time through UART & Writing on DS1307 through I2C.
time_receive();
time_convert();
clock_write();
uart_puts("\r\n Da cau hinh lai DS1307.");
__delay_ms(10);
};
}
/****************************************************************
* END OF DS1307.c
****************************************************************/