So I wanted to buy a Macetech ChronoDot but they were constantly out of stock. So I drew up something similar and had some boards made. They work great.

Mine uses a CR2032 cell rather than the smaller CR1632 that the ChronoDot uses. I use the bigger cell because I get my battery holders off old PC mainboards.

I had the boards made by DorkbotPDX. As usual they turned out great. Very simple boards. The chip is a SOIC-16 surface mount, which is large and super easy to solder. The two resistors and one capacitor are all 0805 size - also large and easy to solder. The battery holder mounts on top of the IC and other components. These pics are of my first run of boards. I've made a few minor improvements in the files offered for download here.

Here I'm controlling the RTC and LCD with a PIC 18F14K50. Just a very simple clock/calendar program running.

If you want to make your own board just download my Eagle schematic and board layout. You'll also need my Eagle library. This file set is for the DorkbotPDX PCB service. You may possibly have to make changes for other PCB services - I don't know.

Here's the schematic:

Here's the PIC18F14K50 code that's running in the pics above (header file at bottom):
#include "ds3231.h"
#include <stdio.h>

unsigned char string[] = "                ";

void main()
{
    unsigned char sec,sec10,min,min10,hour,hour10,ampm,dayofweek,date1,date10,mon,mon10,year1,year10;
    unsigned char seconds,minutes,hours,date,month,year;
    osccon = 0b01110010;    //16MHz
    trisb = 0b01010000;
    trisc = 0;
    sspadd = 0x27;
    sspcon1 = 0b00101000;
    lcd_init();
/*    start();
    i2c_write(0xd0);        //send ID code & write bit
    i2c_write(0x00);        //register address
    i2c_write(0x00);        //set seconds
    i2c_write(0x54);        //set minutes
    i2c_write(0x63);        //set hours
    i2c_write(0x07);        //set day
    i2c_write(0x09);        //set date
    i2c_write(0x04);        //set month
    i2c_write(0x11);        //set year
    restart();
    i2c_write(0xd0);        //ID code & write bit
    i2c_write(0x0e);        //register address
    i2c_write(0x40);        //enable 1Hz square wave
    stop();*/
    while(1){
        start();
        i2c_write(0xd0);
        i2c_write(0x00);
        restart();
        i2c_write(0xd1);
        seconds = i2c_read();
        minutes = i2c_read();
        hours = i2c_read();
        dayofweek = i2c_read();
        date = i2c_read();
        month = i2c_read();
        year = i2c_read_nack();
        stop();
        sec = seconds & 0x0f;
        sec10 = (seconds & 0x70) >> 4;
        min = minutes & 0x0f;
        min10 = (minutes & 0x70) >> 4;
        hour = hours & 0x0f;
        hour10 = (hours & 0x10) >> 4;
        ampm = hours & 0x20;
        date1 = date & 0x0f;
        date10 = (date & 0x30) >> 4;
        mon = month & 0x0f;
        mon10 = (month & 0x10) >> 4;
        year1 = year & 0x0f;
        year10 = (year & 0xf0) >> 4;
        line1;
        sprintf(string,"%01u",hour10);
        lcd_string(string);
        sprintf(string,"%01u:",hour);
        lcd_string(string);
        sprintf(string,"%01u",min10);
        lcd_string(string);
        sprintf(string,"%01u:",min);
        lcd_string(string);
        sprintf(string,"%01u",sec10);
        lcd_string(string);
        sprintf(string,"%01u ",sec);
        lcd_string(string);
        if(ampm)
            lcd_string("PM");
        else
            lcd_string("AM");
        line2;
        sprintf(string,"%01u",mon10);
        lcd_string(string);
        sprintf(string,"%01u:",mon);
        lcd_string(string);
        sprintf(string,"%01u",date10);
        lcd_string(string);
        sprintf(string,"%01u:",date1);
        lcd_string(string);
        sprintf(string,"20%01u",year10);
        lcd_string(string);
        sprintf(string,"%01u",year1);
        lcd_string(string);
        delay_ms(255);
    }    
}

//*****************
//* I2C functions *
//*****************
unsigned char i2c_write(unsigned char x){
    unsigned char ackn;
    busywait();
    sspbuf = x;
    while(sspstat.R_W);
    ackn = sspcon2.ACKDT;
    return(ackn);
}

unsigned char i2c_read(void){
    unsigned char dat;
    busywait();
    sspcon2.RCEN = 1;       //receive enable
    while(sspcon2.RCEN);
    dat = sspbuf;
    sspcon2.ACKDT = 0;      //send ack
    sspcon2.ACKEN = 1;
    while(sspcon2.ACKEN);
    return(dat);
}        

unsigned char i2c_read_nack(void){
    unsigned char dat;
    busywait();
    sspcon2.RCEN = 1;       //receive enable
    while(sspcon2.RCEN);
    dat = sspbuf;
    sspcon2.ACKDT = 1;      //send nack
    sspcon2.ACKEN = 1;
    while(sspcon2.ACKEN);
    return(dat);
}        

void busywait(void){
    unsigned char temp;
    while(sspstat.R_W);
    temp = sspcon2 & 0x1f;
    while(temp)
        temp = sspcon2 & 0x1f;
}    

void start(void){
    sspcon2.SEN = 1;
    while(sspcon2.SEN);
}

void restart(void){
    busywait();
    sspcon2.RSEN = 1;
    while(sspcon2.RSEN);
}    

void stop(void){
    sspcon2.PEN = 1;
    while(sspcon2.PEN);
}

//*****************
//* LCD functions *
//*****************
void lcd_cls(void){
    line1;
    lcd_string("                ");
    line2;
    lcd_string("                ");
}        

void lcd_string(char *senpoint)
{
    while(*senpoint != '\0')
    {
        lcd_char(*senpoint);
        senpoint++;
    }
}    

void lcd_cmd(unsigned char letter)
{
    unsigned char temp;
    temp = letter;
    temp = temp>>4;
    lcd_nybble(temp,0);
    temp = letter;
    temp = temp&0x0f;
    lcd_nybble(temp,0);
}

void lcd_char(unsigned char letter)
{
    unsigned char temp;
    temp = letter;
    temp = temp >> 4;
    lcd_nybble(temp,1);
    temp = letter;
    temp = temp & 0x0f;
    lcd_nybble(temp,1);
}

void lcd_nybble(unsigned char nyb,unsigned char rs)
{
    int i;
    data = 0;                   //clear the 174
    for(i=0;i<6;i++){           //repeat for 6 bits
        clock=1;delay_us(50);clock=0;        //write 0's to the 174
    }
    data=1;                     //output the AND value
    clock=1;delay_us(50);clock=0;
    data=rs;                    //output the RS bit value
    clock=1;delay_us(50);clock=0;
    for(i=0;i<4;i++){           //output the nybble
        if((nyb & 0x08) != 0)
            data=1;
        else
            data=0;
        clock=1;delay_us(50);clock=0;
        nyb=nyb<<1;
    }
    e_togg();
}

void lcd_init(void)
{
    delay_ms(250);
    lcd_nybble(0x03,0);
    delay_ms(5);
    e_togg();
    delay_us(160);
    e_togg();
    delay_us(160);
    lcd_nybble(0x02,0);
    delay_us(160);
    lcd_cmd(0x28);                    //set 4-bit mode and 2 lines
    delay_us(160);
    lcd_cmd(0x10);                    //cursor move & shift left
    delay_us(160);
    lcd_cmd(0x06);                    //entry mode = increment
    delay_us(160);
    lcd_cmd(0x0d);                    //display on - cursor blink on
    delay_us(160);
    lcd_cmd(0x01);                    //clear display
    delay_us(160);
}

void e_togg(void)
{
    data=1;
    delay_us(50);
    data=0;
}
ds3231.h
#include <system.h>

#pragma    CLOCK_FREQ    16000000
#pragma DATA    _CONFIG1H, _FOSC_IRC_1H & _PLLEN_OFF_1H
#pragma DATA    _CONFIG2H, _WDTEN_OFF_2H
#pragma DATA    _CONFIG3H, _MCLRE_ON_3H
#pragma DATA    _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L

#define mySDA   latc.5
#define mySCL   latc.4

#define    clock   latc.6
#define data    latc.7
#define line1   lcd_cmd(0x80);
#define line2   lcd_cmd(0xc0);

void rtc_burstread(void);
void rtc_burstwrite(void);
void start(void);
void restart(void);
void stop(void);
void ack(void);
void nack(void);
unsigned char i2c_read_nack(void);
void busywait(void);
void i2c_clock(void);
unsigned char i2c_read(void);
unsigned char i2c_write(unsigned char);

void lcd_cls();            //function prototypes
void lcd_cmd(unsigned char);
void lcd_char(char);
void e_togg(void);
void lcd_init(void);
void lcd_string(char *);
void lcd_nybble(unsigned char,unsigned char);

Next Post Previous Post