AtomSoft
Well-Known Member
hey some of you know i have been working on a clock using a DS1306 and i wanted to post this for anyone who wants to see it. at the moment you can only set the time. Its a huge file.
You can study about BCD conversions, SPI, Shift Registers(74LS165 & 74LS164). I say you can study mainly because it all works so far. And if it works then maybe it can help some people.
Im in the process of adding code to Set the Date including Day, month, year, actual day... take a look.
I rewrote my old code. This should be a nice read for some.
You can study about BCD conversions, SPI, Shift Registers(74LS165 & 74LS164). I say you can study mainly because it all works so far. And if it works then maybe it can help some people.
Im in the process of adding code to Set the Date including Day, month, year, actual day... take a look.
I rewrote my old code. This should be a nice read for some.
Code:
#include <p18F248.h>
#include <stdio.h>
#include <delays.h>
#include <spi.h>
#pragma config WDT = OFF, LVP = OFF, OSC = HS
/************************************
Prototypes
*************************************/
void initSPI(void);
void e_togg(void);
void lcd_line(char line);
void lcd_cmd(unsigned char letter);
void lcd_char(unsigned char letter);
void lcd_string(char *senpoint);
void lcd_init(void);
void delay_ms(int mS);
void delay_us(int uS);
void delay_s(int S);
void lcdByte(unsigned char dNyb,unsigned char rs);
char RTCRegRead(char adx);
void RTCRegWrite(char adx, char data);
void showMenu(void);
void setDate(void);
void setTime(char type);
static unsigned char uint2bcd(unsigned char ival);
char readBtn(void);
unsigned char bcd2dec(unsigned char aBCD, char type);
/************************************
Definitions
************************************/
#define CS LATCbits.LATC2
#define CS_T TRISCbits.TRISC2
#define SCL_T TRISCbits.TRISC3
#define SDA_T TRISCbits.TRISC4
#define SDO_T TRISCbits.TRISC5
#define LCD_DAT_T TRISCbits.TRISC0
#define LCD_CLK_T TRISCbits.TRISC1
#define LCD_DAT LATCbits.LATC0
#define LCD_CLK LATCbits.LATC1
#define LCD_E_T TRISCbits.TRISC6
#define LCD_E LATCbits.LATC6
#define PL LATBbits.LATB0
#define CP2 LATBbits.LATB1
#define SDL PORTBbits.RB2
#define PL_T TRISBbits.TRISB0
#define CP2_T TRISBbits.TRISB1
#define SDL_T TRISBbits.TRISB2
#define setupBtn 0x08
#define downBtn 0x02
#define upBtn 0x01
#define selectBtn 0x10
/************************************
Variables
************************************/
char string[] = " ";
char string2[] = " ";
unsigned char time[17];
unsigned char theDay;
unsigned char theDate[2];
unsigned char theMonth[2];
unsigned char theYear[2];
unsigned char theHour[2];
unsigned char theMin[2];
unsigned char theSec[2];
unsigned char decHour;
unsigned char decMin;
unsigned char decSec;
unsigned char decAMPM;
/************************************
Main
************************************/
void main(void){
unsigned char tmp,tmp2;
unsigned char buff[40];
char i;
time[16] = 0;
ADCON1 = 0x0E;
initSPI();
lcd_init();
PL_T = 0;
CP2_T = 0;
SDL_T = 1;
lcd_line(1);
sprintf(string," AtomSoftTech",0);
lcd_string(string);
lcd_line(2);
sprintf(string," 2-Wire 74LS164",0);
lcd_string(string);
delay_s(1);
lcd_line(2);
sprintf(string," DS1306 TEST. ",0);
lcd_string(string);
delay_s(1);
while(1){
lcd_line(1);
sprintf(string," AtomSoftTech",0);
lcd_string(string);
tmp = RTCRegRead(0x02);
time[15] = (tmp >> 4) & 0x02;
if(time[15] == 0)
time[15] = 'A' ;
else
time[15] = 'P';
time[14] = 0x20;
tmp = RTCRegRead(0x00);
decSec = tmp;
theSec[1] = time[13] = (tmp & 0x0F) + 0x30;
theSec[0] = time[12] = ((tmp >> 4) & 0x0F ) + 0x30;
time[11] = ':';
tmp = RTCRegRead(0x01);
decMin = tmp;
theMin[1] = time[10] = (tmp & 0x0F) + 0x30;
theMin[0] = time[9] = ((tmp >> 4) & 0x0F ) + 0x30;
time[8] = ':';
tmp = RTCRegRead(0x02);
decHour = tmp;
theHour[1] = time[7] = (tmp & 0x0F) + 0x30;
theHour[0] = time[6] = ((tmp >> 4) & 0x01 ) + 0x30;
time[5] = 0x20;
time[4] = ':';
time[3] = 'e';
time[2] = 'm';
time[1] = 'i';
time[0] = 'T';
lcd_line(2);
lcd_string(time);
tmp = readBtn();
if(tmp == setupBtn)
showMenu();;
delay_ms(10);
}
}
/***********************************
RTC Tools
************************************
Convert Char(byte) to BCD
************************************/
unsigned char uint2bcd(unsigned char ival)
{
return ((ival / 10) << 4) | (ival % 10);
}
/************************************
Convert BCD to Char(byte)
************************************/
unsigned char bcd2dec(unsigned char aBCD, char type)
{
char lowNyb = aBCD & 0x0F;
char highNyb = aBCD >> 4;
char MyDec = lowNyb;
char x;
switch(type){
case 0:
highNyb &= 0x0F;
break;
case 1:
highNyb &= 0x01;
break;
case 2:
highNyb &= 0x03;
break;
case 3:
highNyb &= 0x07;
break;
}
for(x=0;x<highNyb;x++){
MyDec += 10;
}
return MyDec;
}
/************************************
Read a Register off the DS1306
************************************/
char RTCRegRead(char adx){
char tmp;
CS = 1;
WriteSPI(adx); //sec
tmp = ReadSPI();
CS = 0;
return tmp;
}
/************************************
Write to a Register on the DS1306
************************************/
void RTCRegWrite(char adx, char data){
adx |= 0x80;
CS = 1;
WriteSPI(adx);
WriteSPI(data);
CS = 0;
}
/************************************
Initialize SPI
************************************/
void initSPI(void){
CS_T = 0; //CS is output
SCL_T = 0; //SCL is output
SDA_T = 1; //SDA is input
SDO_T = 0; //SDO is output
OpenSPI(SPI_FOSC_4,MODE_10,SMPEND);
CS = 1;
WriteSPI(0x8F);
WriteSPI(0x00);
CS = 0;
}
/***********************************
LCD Functions
************************************
Send String to LCD
************************************/
void lcd_string(char *senpoint){
delay_ms(1);
while(*senpoint != '\0'){
lcd_char(*senpoint);
senpoint++;
}
}
/************************************
Send Data(Nybble) to LCD
************************************/
void lcdByte(unsigned char dNyb,unsigned char rs){
int i;
LCD_DAT=0; //Clear 74LS164 set initial bit to 0
for(i=0;i<8;i++){ //repeat for 8 bits
LCD_CLK=1;LCD_CLK=0; //write 0's to the 164
}
for(i=0;i<4;i++){ //output the nybble
if((dNyb & 0x08) != 0)
LCD_DAT=1;
else
LCD_DAT=0;
LCD_CLK=1;LCD_CLK=0;
dNyb=dNyb<<1;
}
LCD_DAT = rs; //output the RS bit value
LCD_CLK=1;LCD_CLK=0;
LCD_DAT = 0;
LCD_CLK=1;LCD_CLK=0;
LCD_CLK=1;LCD_CLK=0;
LCD_CLK=1;LCD_CLK=0;
e_togg();
}
/************************************
Toggle E Line
************************************/
void e_togg(void){
LCD_E=1;LCD_E=0;
}
/************************************
Set LCD Line
************************************/
void lcd_line(char line){
if(line == 0x01)
lcd_cmd(0x80);
else
lcd_cmd(0xc0);
}
/************************************
LCD Send Command
************************************/
void lcd_cmd(unsigned char letter){
unsigned char temp;
temp=letter;
temp=temp>>4;
lcdByte(temp,0);
temp=letter;
temp=temp&0x0f;
lcdByte(temp,0);
}
/************************************
LCD Send Character
************************************/
void lcd_char(unsigned char letter){
unsigned char temp;
temp=letter;
temp=temp>>4;
lcdByte(temp,1);
temp=letter;
temp=temp&0x0f;
lcdByte(temp,1);
}
/************************************
LCD Initialization
************************************/
void lcd_init(void){
LCD_E_T = 0;
LCD_CLK_T = 0;
LCD_DAT_T = 0;
lcdByte(0x03,0);
delay_ms(5);
e_togg();
delay_us(160);
e_togg();
delay_us(160);
lcdByte(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_ms(500);
}
/************************************
Delays (S,mS,uS) for 20Mhz
************************************/
/*********************
Delay Second(s)
**********************/
void delay_s(int S){
int y;
char x;
for(y=0;y<S;y++)
for(x=0;x<4;x++)
delay_ms(250);
}
/************************
Delay MilliSecond(s)
*************************/
void delay_ms(int mS){
int y;
for(y=0;y<mS;y++)
Delay1KTCYx(5);
}
/************************
Delay MicroSeconds
*************************
Lowercase 'u' is common
symbol for Micro
*************************/
void delay_us(int uS){
int y;
char x;
for(y=0;y<uS;y++)
for(x=0;x<5;x++)
Nop();
}
/***********************************
SN74LS165 Functions
************************************
Toggle Clock Pin
************************************/
void clk_togg(void){
LCD_CLK=1;LCD_CLK=0;
}
/************************************
readBtn
************************************/
char readBtn(void){
char x;
char buff;
delay_ms(100);
PL=0; PL=1;
for(x=0;x<8;x++){
buff <<= 1; // shift composed byte by 1
buff &= 0xFE; // clear bit 0
if (SDL) // is data line high
buff |= 0x01; // set bit 0 to logic 1
CP2 = 0; CP2 = 1;
}
delay_ms(100);
return buff & 0x1F;
}
/***********************************
LCD / RTC stuff
************************************
Show Menu
************************************/
void showMenu(void){
char item, isEnter;
isEnter = 0;
item = 1; //Default to first menu item
while(1){
/******************************
Which item are we viewing
*******************************/
switch(item){
case 0:
item=3; //user went do down too far start from 3
break;
case 1:
sprintf(string2,"1.Set Time ",0);
break;
case 2:
sprintf(string2,"2.Set Date ",0);
break;
case 3:
sprintf(string2,"3.Set Alarm ",0);
break;
case 4:
item=1; //user went too up far start them from 1
break;
}
/*****************************
Determine Button Pressed
******************************/
switch(readBtn()){
case upBtn:
item++;
break;
case downBtn:
item--;
break;
case selectBtn:
isEnter = 1;
break;
}
/*****************************
Enter is pressed
******************************/
if(isEnter == 1){
if(item==1)
setTime('t');
if(item==2){
setDate();
}
if(item==3){
//Set Alarm
}
item=9; //a overkill number incase i want to add more functions.
}
/*************************
Show Menu to the user
**************************/
lcd_line(1);
sprintf(string," Settings ",0);
lcd_string(&string);
lcd_line(2);
lcd_string(&string2);
/**************************
Check if user is done.
***************************/
if(item==9)
break; //leave while(1) loop
}//end of while loop
}
/*****************
Set the Date
******************/
void setDate(void){
}
/****************
Set the Time
****************/
void setTime(char type){
char bcdMin,bcdHour;
char x = 0;
decMin = bcd2dec(decMin,3);
decHour = bcd2dec(decHour,1);
decAMPM = (RTCRegRead(0x01) >> 5) & 0x01 ;
/********************
Main while loop
*********************/
while(1){
/**********************************
Determine which title to show
***********************************/
switch(x){
case 0:
sprintf(string,"Set Time: Hour ",0);
break;
case 1:
sprintf(string,"Set Time: Min ",0);
break;
case 2:
sprintf(string,"Set Time: AM/PM ",0);
break;
}
/*****************************************
Button pressed functions
******************************************/
switch(readBtn()){
case upBtn:
switch(x){
case 0:
decHour++;
break;
case 1:
decMin++;
break;
case 2:
decAMPM++;
break;
}
break;
case downBtn:
switch(x){
case 0:
decHour--;
break;
case 1:
if(decMin == 0)
decMin = 59;
else
decMin--;
break;
case 2:
decAMPM--;
break;
}
break;
case selectBtn:
x++;
break;
case setupBtn:
return; //User Pressed Setup aka Cancel
}
/**********************************************
Error Fix's:
***********************************************
ex: If hour is greater than 12 then set to 1
if its a 0 set it to 12 since this is 12 hr
there is no 00:00 hour only 1-12 AM/PM
***********************************************/
if(decHour >= 13)
decHour = 1;
if(decHour == 0)
decHour = 12;
if(decMin >= 60)
decMin = 0;
if(decAMPM >= 2)
decAMPM = 0;
if(decAMPM < 0)
decAMPM = 0;
if(x >= 3)
break;
if(x == 'c')
break;
/*****************************************
Convert to BCD for the RTC(DS1306)
******************************************/
bcdHour = uint2bcd(decHour);
if(decAMPM >= 1)
bcdHour = bcdHour | 0x20; //0b00100000
bcdMin = uint2bcd(decMin);
/*********************************************
Convert to seperate numbers or split BCD
and add 0x30 so it can be displayed on
LCD.
**********************************************/
time[6] = ((bcdHour >> 4) & 0x01) + 0x30;
time[7] = (bcdHour & 0x0F) + 0x30;
time[9] = (bcdMin >> 4) + 0x30;
time[10] = (bcdMin & 0x0F) + 0x30;
time[12] = time[13] = 0x30;
if(decAMPM == 1)
time[15] = 'P';
else
time[15] = 'A';
/*****************************************
Update the LCD with new info.
******************************************/
lcd_line(1);
lcd_string(string);
lcd_line(2);
lcd_string(&time);
}
/*****************************************
Done! Now write to RTC the new Data
******************************************/
RTCRegWrite(0x80,0x00); //Seconds = 00
RTCRegWrite(0x81,bcdMin); //Minutes
RTCRegWrite(0x82,bcdHour); //Hours
}
Last edited: