CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

DS1302 digital clock with PIC16F887
Goto page 1, 2, 3, 4  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
princejude



Joined: 07 Aug 2010
Posts: 72

View user's profile Send private message

DS1302 digital clock with PIC16F887
PostPosted: Thu Jan 26, 2012 4:23 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Jan 26, 2012 4:01 pm     Reply with quote

Here is some push-button code for "Set" and "Select" buttons.
http://www.ccsinfo.com/forum/viewtopic.php?t=39585
You can add more buttons.
princejude



Joined: 07 Aug 2010
Posts: 72

View user's profile Send private message

PostPosted: Thu Feb 02, 2012 9:42 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Feb 23, 2012 4:08 am     Reply with quote

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

View user's profile Send private message

Buttons
PostPosted: Thu Feb 23, 2012 9:43 am     Reply with quote

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

View user's profile Send private message

ALL IZZ WELL! aLL IZZ WELL!! ALL IZZ WELL!!!
PostPosted: Fri Feb 24, 2012 7:40 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Feb 24, 2012 7:51 am     Reply with quote

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

View user's profile Send private message

00:00
PostPosted: Fri Feb 24, 2012 8:09 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Feb 24, 2012 9:22 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Feb 24, 2012 9:29 am     Reply with quote

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

View user's profile Send private message

00:00 ?
PostPosted: Fri Feb 24, 2012 9:43 am     Reply with 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.


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

View user's profile Send private message

PostPosted: Mon Feb 27, 2012 3:14 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Feb 27, 2012 5:14 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Feb 27, 2012 6:52 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Feb 27, 2012 8:17 am     Reply with quote

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 ?
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2, 3, 4  Next
Page 1 of 4

 
Jump to:  
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