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);