|
|
View previous topic :: View next topic |
Author |
Message |
princejude
Joined: 07 Aug 2010 Posts: 72
|
DS1302 digital clock with PIC16F887 |
Posted: Thu Jan 26, 2012 4:23 am |
|
|
Hello Please can anyone help me with suggestions, ideas, sample codes or links on how to complete this my project.
I want to design a DS1302 RTC based digital clock using PIC16F887 and 7-segment display. I have designed the circuit and the code. The clock is working but the issue I have is how to include the Time setting in my code. I will like to set the time with 3 push-button switches, one switch to select the mode (hour or minute) the next switch is to increase the value selected and the next switch is to decrease the value.
My code is here:
Code: |
//#include "C:\Users\caleb\Documents\CLOCK_PROJECT\clock2.h"
#include <16F887.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT //No Power Up Timer
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOCPD //No EE protection
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES NOFCMEN //Fail-safe clock monitor disabled
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOWRT //Program memory not write protected
#FUSES BORV40 //Brownout reset at 4.0V
#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#define RTC_SCLK PIN_C3
#define RTC_IO PIN_C5
#define RTC_RST PIN_C2
#define D 1
#define setn PIN_E0
#define incr PIN_E1
#define decr PIN_E2
#define check PIN_B7
#include <ds1302.c>
#include <lcd.c>
byte day,mth,year,dow,hour,min,sec;
int decode(int8 sec)
{
int code;
switch(sec)
{
case 0: code = 0x40;break;
case 1: code = 0x79;break;
case 2: code = 0x24;break;
case 3: code = 0x30;break;
case 4: code = 0x19;break;
case 5: code = 0x12;break;
case 6: code = 0x02;break;
case 7: code = 0x78;break;
case 8: code = 0x00;break;
case 9: code = 0x10;break;
}
return code;
}
void display7seg()
{
int Sec_units, Min_units, Sec_tens, Min_tens, Hr_units, Hr_tens;
int Result;
rtc_get_time( hour, min, sec );
Sec_tens = sec/10;
Sec_units= sec%10;
Min_tens = min/10;
Min_units= min%10;
Hr_tens = hour/10;
Hr_units= hour%10;
output_A(0x01);
Result = decode(Hr_tens);
output_B(Result);
delay_ms(D);
output_A(0x02);
Result = decode(Hr_units);
output_B(Result);
delay_ms(D);
output_A(0x04);
Result = decode(Min_tens);
output_B(Result);
delay_ms(D);
output_A(0x08);
Result = decode(Min_units);
output_B(Result);
delay_ms(D);
output_A(0x10);
Result = decode(Sec_tens);
output_B(Result);
delay_ms(D);
output_A(0x20);
Result = decode(Sec_units);
output_B(Result);
delay_ms(D);
}
void get_clock()
{
rtc_get_time( hour, min, sec );
lcd_gotoxy(1,2);
printf(lcd_putc,"Time: %02d:%02d:%02d ",hour,min,sec);
}
void get_date()
{
rtc_get_date( day, mth, year, dow);
lcd_gotoxy(1,1);
printf(lcd_putc,"Date:%02d/%02d/20%02d",day,mth,year);
}
void set_clock()
{
// rtc_set_datetime(day,mth,year,dow,hour,min);
rtc_set_datetime(12, 10,15, 2,5,59);
}
void main()
{
rtc_init();
lcd_init();
set_clock();
while(true)
{
// get_date();
// get_clock();
display7seg();
}
}
|
Thanks in advance |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
princejude
Joined: 07 Aug 2010 Posts: 72
|
|
Posted: Thu Feb 02, 2012 9:42 am |
|
|
Thanks for your reply, I am still working on the code with some sample codes from the link above, no positive result yet (my buttons are not responding with my code - once the clock start running, the buttons will not control or set the time). I will post my code if am through with my testing and debugging. |
|
|
princejude
Joined: 07 Aug 2010 Posts: 72
|
|
Posted: Thu Feb 23, 2012 4:08 am |
|
|
The clock is now working on hardware(PIC Development kit) but there is still some issues with the time setting section.
Here is my code:
Code: | #include <16F887.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT //No Power Up Timer
#FUSES MCLR //Master Clear pin enabled
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOCPD //No EE protection
#FUSES NOBROWNOUT //No brownout reset
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOWRT //Program memory not write protected
#FUSES BORV40 //Brownout reset at 4.0V
#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#define RTC_SCLK PIN_C3
#define RTC_IO PIN_C5
#define RTC_RST PIN_C2
#define D 1
#define KEY1 PIN_B0
#define KEY2 PIN_B1
#define KEY3 PIN_B2
#define KEY4 PIN_B3
#include <ds1302.c>
//#include "flex_lcd.c"
byte day,mth,year,dow,hour,min,sec;
int decode(int8 sec)
{
int code;
switch(sec)
{
case 0: code = 0x40;break;
case 1: code = 0x79;break;
case 2: code = 0x24;break;
case 3: code = 0x30;break;
case 4: code = 0x19;break;
case 5: code = 0x12;break;
case 6: code = 0x02;break;
case 7: code = 0x78;break;
case 8: code = 0x00;break;
case 9: code = 0x10;break;
}
return code;
}
void display7seg()
{
int Sec_units, Min_units, Sec_tens, Min_tens, Hr_units, Hr_tens;
int Result;
rtc_get_time( hour, min, sec );
Sec_tens = sec/10;
Sec_units= sec%10;
Min_tens = min/10;
Min_units= min%10;
Hr_tens = hour/10;
Hr_units= hour%10;
output_A(0B11011111);
Result = decode(Hr_tens);
output_D(Result);
delay_ms(D);
output_A(0B11101111);
Result = decode(Hr_units);
output_D(Result);
delay_ms(D);
output_A(0B11110111);
Result = decode(Min_tens);
output_D(Result);
delay_ms(D);
output_A(0B11111011);
Result = decode(Min_units);
output_D(Result);
delay_ms(D);
output_A(0B11111101);
Result = decode(Sec_tens);
output_D(Result);
delay_ms(D);
output_A(0B11111110);
Result = decode(Sec_units);
output_D(Result);
delay_ms(D);
}
void main()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);// This device COMP currently not supported by the PICWizard
//Setup_Oscillator parameter not selected from Intr Oscillator Config tab
// TODO: USER CODE!!
rtc_init();
// lcd_init();
rtc_set_datetime(23,2,12,5,9,26);
// rtc_get_date( day, mth, year, dow);
while(true)
{
[b]/********* THIS IS WHERE THE PROBLEM START ****************[/b]
if(!input(KEY1)) //INCREASE HOUR
{
delay_ms(50);
hour++;
if(hour > 23) hour = 0;
rtc_set_datetime(day,mth,year,dow,hour,min);
}
if(!input(KEY2)) //DECREASE HOUR
{
delay_ms(50);
hour--;
if(hour == 0) hour = 23;
rtc_set_datetime(day,mth,year,dow,hour,min);
}
if(!input(KEY3)) //INCREASE MIN
{
delay_ms(50);
min++;
if(min > 59) min = 0;
rtc_set_datetime(day,mth,year,dow,hour,min);
}
if(!input(KEY4)) //DECREASE MIN
{
delay_ms(50);
min--;
if(min == 0) min = 59;
rtc_set_datetime(day,mth,year,dow,hour,min);
}
[b]***************** THE PROBLEM ENDS HERE *****************/ [/b]
display7seg();
}
} |
If I comment out the above 4 if(!input(KEY)) statements (used for setting the time) and program the chip, the clock will work normal, but if I include the time setting code section, the unit digit of the seconds will display 0 (i.e. zero) while the other digits will be partially on(or almost off because the numbers are not visible).
Pls I will like someone to help me on this.
Thanks in advance |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
Buttons |
Posted: Thu Feb 23, 2012 9:43 am |
|
|
You've not told / shown us how your buttons are wired.
Are you using switches to 0V with pull up resistors?
Or are you using switches to +ve rail with pull down?
You're going to get a problem with roll-over when you decrease. You want to roll-over when mins and/or hrs reach -1 NOT zero.
Mike |
|
|
princejude
Joined: 07 Aug 2010 Posts: 72
|
ALL IZZ WELL! aLL IZZ WELL!! ALL IZZ WELL!!! |
Posted: Fri Feb 24, 2012 7:40 am |
|
|
Yeah!!! I can set the time now. There was some hardware issues on the switches in my development board. It seems like some switches are partially on even if not pressed. I built the switch section on a bread board and connected them to different pins as shown in the code below and it started working.
@Mark;
my switch connections are active low i.e I/O pin to VCC through 10k and I/O pin to GND throgh switch. If (switch == pressed) {it will send zero to the pin} else if (switch == Not pressed) {it will send one to the pin}
Here is my code and the header file is same as above code:
Code: | #include "C:\Users\caleb\Documents\CLOCK_PROJECT\MYCLK.h"
#define RTC_SCLK PIN_C3
#define RTC_IO PIN_C5
#define RTC_RST PIN_C2
#define D 1
#define KEY1 PIN_C0
#define KEY2 PIN_C1
#define KEY3 PIN_E0
#define KEY4 PIN_E1
#include <ds1302.c>
//#include "flex_lcd.c"
int day,mth,year,dow,hour,min,sec;
int decode(int8 sec)
{
int code;
switch(sec)
{
case 0: code = 0x40;break;
case 1: code = 0x79;break;
case 2: code = 0x24;break;
case 3: code = 0x30;break;
case 4: code = 0x19;break;
case 5: code = 0x12;break;
case 6: code = 0x02;break;
case 7: code = 0x78;break;
case 8: code = 0x00;break;
case 9: code = 0x10;break;
}
return code;
}
void display7seg()
{
int Sec_units, Min_units, Sec_tens, Min_tens, Hr_units, Hr_tens;
int Result;
rtc_get_time( hour, min, sec );
Sec_tens = sec/10;
Sec_units= sec%10;
Min_tens = min/10;
Min_units= min%10;
Hr_tens = hour/10;
Hr_units= hour%10;
output_A(0B11011111);
Result = decode(Hr_tens);
output_D(Result);
delay_ms(D);
output_A(0B11101111);
Result = decode(Hr_units);
output_D(Result);
delay_ms(D);
output_A(0B11110111);
Result = decode(Min_tens);
output_D(Result);
delay_ms(D);
output_A(0B11111011);
Result = decode(Min_units);
output_D(Result);
delay_ms(D);
output_A(0B11111101);
Result = decode(Sec_tens);
output_D(Result);
delay_ms(D);
output_A(0B11111110);
Result = decode(Sec_units);
output_D(Result);
delay_ms(D);
}
/*
void get_clock()
{
rtc_get_time( hour, min, sec );
lcd_gotoxy(1,2);
printf(lcd_putc," %02d:%02d:%02d ",hour,min,sec);
}
void get_date()
{
rtc_get_date( day, mth, year, dow);
lcd_gotoxy(1,1);
printf(lcd_putc,"%02d/%02d/20%02d",day,mth,year);
switch(dow)
{
case 1: {lcd_gotoxy(12,1); lcd_putc("SUN");
break;}
case 2: {lcd_gotoxy(12,1); lcd_putc("MON");
break;}
case 3: {lcd_gotoxy(12,1); lcd_putc("TUE");
break;}
case 4: {lcd_gotoxy(12,1); lcd_putc("WED");
break;}
case 5: {lcd_gotoxy(12,1); lcd_putc("THUR");
break;}
case 6: {lcd_gotoxy(12,1); lcd_putc("FRI");
break;}
case 7: {lcd_gotoxy(12,1); lcd_putc("SAT");
break;}
default:{lcd_gotoxy(12,1); lcd_putc("ERROR");}
}
}
*/
void main()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);// This device COMP currently not supported by the PICWizard
//Setup_Oscillator parameter not selected from Intr Oscillator Config tab
// TODO: USER CODE!!
rtc_init();
// lcd_init();
rtc_set_datetime(23,2,12,5,9,26);
// rtc_get_date( day, mth, year, dow);
while(true)
{
if(!input(KEY1)) //INCR HOUR
{
delay_ms(200);
hour++;
if(hour > 23) hour = 0;
rtc_set_datetime(day,mth,year,dow,hour,min);
}
if(!input(KEY2)) //DECR HOUR
{
delay_ms(200);
hour--;
if(hour == 0) hour = 23;
rtc_set_datetime(day,mth,year,dow,hour,min);
}
if(!input(KEY3)) //INCR MIN
{
delay_ms(200);
min++;
if(min > 59) min = 0;
rtc_set_datetime(day,mth,year,dow,hour,min);
}
if(!input(KEY4)) //DECR MIN
{
delay_ms(200);
min--;
if(min == 0) min = 59;
rtc_set_datetime(day,mth,year,dow,hour,min);
}
display7seg();
}
} |
Still have one more issue to solve:
My dev. kit have six digit 7-segment display for HH:MM:SS, but my actual hardware will only use four digit 7-segments and two LEDs(for secs)as in HH:MM. From this my code, how can I make the two LEDs to toggle at every secs so that it will replace the 7-segments for the Seconds.
Thanks. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9245 Location: Greensville,Ontario
|
|
Posted: Fri Feb 24, 2012 7:51 am |
|
|
I don't have the DS1302( I use the DS1307) ,but it may have an output pin for generating and ISR to the PIC. It should be programmable for 1Hz rate. If so, just add appropriate resistor and wire to the LEDs.
That's the real easy way... |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
00:00 |
Posted: Fri Feb 24, 2012 8:09 am |
|
|
Can you decrease mins and hours to zero?
If you read seconds, the LSB will toggle every second. Could you connect the seconds LSB to the two LEDs and a resistor?
Mike |
|
|
princejude
Joined: 07 Aug 2010 Posts: 72
|
|
Posted: Fri Feb 24, 2012 9:22 am |
|
|
Quote: | Can you decrease mins and hours to zero? |
Yes Mr. mike(not Mark pls), I can decrease them to zero.
Quote: | If you read seconds, the LSB will toggle every second. Could you connect the seconds LSB to the two LEDs and a resistor? |
I am using 7-segment. Which of the segment of the LSB will I connect to the 2 LEDs ? |
|
|
princejude
Joined: 07 Aug 2010 Posts: 72
|
|
Posted: Fri Feb 24, 2012 9:29 am |
|
|
Quote: | ,but it may have an output pin for generating and ISR to the PIC. It should be programmable for 1Hz rate. If so, just add appropriate resistor and wire to the LEDs. |
@ temtronic:
Let me study the DS1302 datasheet again to check if I can see such pin. But can't this be achieved from the code ? |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
00:00 ? |
Posted: Fri Feb 24, 2012 9:43 am |
|
|
You've got these lines in your code
Code: |
if(!input(KEY2)) //DECREASE HOUR
{
delay_ms(50);
hour--;
if(hour == 0) hour = 23;
rtc_set_datetime(day,mth,year,dow,hour,min);
}
|
and
Code: |
if(!input(KEY4)) //DECREASE MIN
{
delay_ms(50);
min--;
if(min == 0) min = 59;
rtc_set_datetime(day,mth,year,dow,hour,min);
|
I was expecting them preventing you from DECREASING either hours or minutes to zero.
The line hour-- forces hours to 23 just after you decrease to zero.
The line min-- forces minutes to 59 just after you decrease to zero.
In both cases there is no opportunity to set time to 00 or update the display to 00.
To answer your question about seconds.
When you run the line
Code: |
rtc_get_time( hour, min, sec );
|
The function returns hours, minutes and seconds. The LSB of seconds changes every second. The bit which toggles every second is bit zero of your variable sec. I was asking if you could use that to drive the colon on your clock.
Mike |
|
|
princejude
Joined: 07 Aug 2010 Posts: 72
|
|
Posted: Mon Feb 27, 2012 3:14 am |
|
|
Thanks Mike for your advice. I used the bit 0 of sec as you suggested and is working but the LED will be ON for 1 sec and OFF for 1 sec, so in a minute the LED will flash 30 times instead of 60 times.
Here is the section of the code that I added to flash the LEDs with sec's bit0
Code: |
#bit sec_zero = sec.0
output_bit( PIN_C4, sec_zero); //This pin_c4 will drive the secs' LEDs
|
Is there anyway to edit the code to flash at the rate of half a second(500ms) instead of 1 sec (i.e. ON time =500ms and OFF time = 500ms) so that the LEDs will flash 60 times in a second. |
|
|
princejude
Joined: 07 Aug 2010 Posts: 72
|
|
Posted: Mon Feb 27, 2012 5:14 am |
|
|
Quote: | You've got these lines in your code
Code:
if(!input(KEY2)) //DECREASE HOUR
{
delay_ms(50);
hour--;
if(hour == 0) hour = 23;
rtc_set_datetime(day,mth,year,dow,hour,min);
}
and
Code:
if(!input(KEY4)) //DECREASE MIN
{
delay_ms(50);
min--;
if(min == 0) min = 59;
rtc_set_datetime(day,mth,year,dow,hour,min);
I was expecting them preventing you from DECREASING either hours or minutes to zero.
The line hour-- forces hours to 23 just after you decrease to zero.
The line min-- forces minutes to 59 just after you decrease to zero.
In both cases there is no opportunity to set time to 00 or update the display to 00. |
this section of code is working normal on my hard, but how do you want me to write the code ? |
|
|
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
|
Posted: Mon Feb 27, 2012 6:52 am |
|
|
Hi,
Your code only appears to work "normally" because you haven't tested it well enough.
Both Hour = 0 and Minute = 0 are valid conditions, but you'll never get to those states with your code. You need to change your test to look for values Less than zero.
John |
|
|
princejude
Joined: 07 Aug 2010 Posts: 72
|
|
Posted: Mon Feb 27, 2012 8:17 am |
|
|
Ok Mr. John (ezflyr), I understand what you and Mr. Mike is pointing at, I will watch the hardware closely and patiently while decreasing to zero to check if 00 will appear on the 7-segment,but do you know how I will make the LED to flash exactly 60 times in a minute instead of 30 times ? |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|