Pic countdown timer

Thread Starter

emalper

Joined Aug 4, 2016
24
Hi guys i want to make a countdown timer for my uv box. I want to write it in ccs c language. As far as i know i need to use timer1 to make it real time. And i know how to use timer1 pin but i can write the digits which timer1 counts to a seven segment display. Can you guys please tell me how to do that?

My timer 1 code as an example but is just for blinking a led with timer one so i need to implement seven segment to that code for example?

C:
#include <16f877.h>    

#fuses XT,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD

#use delay (clock=4000000) 
#use fast_io(b) 

int i=0;

#int_timer1 
void  timer1_kesme ()   
{
   set_timer1(63036); 

   i++; 

   if (i==50)   
      output_high(pin_b0);
   if (i==100) 
   {
      output_low(pin_b0);
      i=0;
   }
}

void main ( )
{
   setup_psp(PSP_DISABLED);      
   setup_timer_2(T2_DISABLED,0,1); 
   setup_adc_ports(NO_ANALOGS);  
   setup_adc(ADC_OFF);             
   setup_CCP1(CCP_OFF);          


   set_tris_b(0x00);  

   output_b(0x00);    

   setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
   set_timer1(63036);  


   enable_interrupts(INT_timer1); 
   enable_interrupts(GLOBAL);     
   while(1); 

}
Moderators note: used code tags for C
 
Last edited:

AlbertHall

Joined Jun 4, 2014
12,346
If you can set up timer 1 for a 500mS overflow period then instead of the delay_ms(500) in your code above you can put a loop waiting for the timer 1 overflow flag. When the flag is detected, exit the loop and reset the flag ready for next time.

You can do fancier methods like setting timer 1 as above but enabling its interrupt then in the interrupt routine you advance the digit count. This allows the pic to do other stuff while waiting for the interrupt rather than being tied up all the time polling the overflow flag.
 

Thread Starter

emalper

Joined Aug 4, 2016
24
If you can set up timer 1 for a 500mS overflow period then instead of the delay_ms(500) in your code above you can put a loop waiting for the timer 1 overflow flag. When the flag is detected, exit the loop and reset the flag ready for next time.

You can do fancier methods like setting timer 1 as above but enabling its interrupt then in the interrupt routine you advance the digit count. This allows the pic to do other stuff while waiting for the interrupt rather than being tied up all the time polling the overflow flag.
hi thanks for your answer but can you please implement some example code please? because i really dont have any idea how and where to implement this code
 

AlbertHall

Joined Jun 4, 2014
12,346
Start with the polling method. It is easier to implement and will get you understanding the timer 1 overflow. When that's working and you understand what's going on, then convert it to the interrupt method.

The delay loop should look something like this:
Code:
while (! TMR1IF);
TMR1IF = 0;
 

Thread Starter

emalper

Joined Aug 4, 2016
24
Start with the polling method. It is easier to implement and will get you understanding the timer 1 overflow. When that's working and you understand what's going on, then convert it to the interrupt method.

The delay loop should look something like this:
Code:
while (! TMR1IF);
TMR1IF = 0;
so basicly when you write TMR1F=0 its mean the the overflow is now 0 and i need to sign a lets say int i and then i need to assigned this i to timer1? and everytime intterrupts overflow i need to add 1 to i lke i++ and write this output to seven segment display? am i going to correct way?
 

Thread Starter

emalper

Joined Aug 4, 2016
24
Yes, that's the idea.
can you look ay my codes? I can write this and it is blingking a led the led is on for 1 second and off for 1 second so now i need to change this leds with seven segment display and i need to write the numbers on that display do you have any idea how to do that? i know you dont know css c but just asking)

Code:
#include <16f877.h>    

#fuses XT,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD

#use delay (clock=4000000) 
#use fast_io(b) 

int i=0;

#int_timer1 
void  timer1_kesme ()   
{
   set_timer1(63036); 

   i++; 

   if (i==50)   
      output_high(pin_b0);
   if (i==100) 
   {
      output_low(pin_b0);
      i=0;
   }
}

void main ( )
{
   setup_psp(PSP_DISABLED);      
   setup_timer_2(T2_DISABLED,0,1); 
   setup_adc_ports(NO_ANALOGS);  
   setup_adc(ADC_OFF);             
   setup_CCP1(CCP_OFF);          


   set_tris_b(0x00);  

   output_b(0x00);    

   setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
   set_timer1(63036);  


   enable_interrupts(INT_timer1); 
   enable_interrupts(GLOBAL);     
   while(1); 

}
 

AlbertHall

Joined Jun 4, 2014
12,346
The code you originally had posted in post #1 was code to output numbers to a seven segment display on port b (I see you have changed it now to the timer 1 code). It used a for loop to iterate through values to output. If you include another counter in the interrupt routine for timer 1 which is incremented in the (i==100) branch, then output that to the display as you did in the LED code. Don't forget to reset that counter when it gets to its maximum value (15? 16?).
 

Thread Starter

emalper

Joined Aug 4, 2016
24
The code you originally had posted in post #1 was code to output numbers to a seven segment display on port b (I see you have changed it now to the timer 1 code). It used a for loop to iterate through values to output. If you include another counter in the interrupt routine for timer 1 which is incremented in the (i==100) branch, then output that to the display as you did in the LED code. Don't forget to reset that counter when it gets to its maximum value (15? 16?).
i understand now thanks a lot. With timer1 how much my timer will be exact? Or it wont be showing me the exact counting?
 

AlbertHall

Joined Jun 4, 2014
12,346
The ultimate accuracy achievable depends on the accuracy of the PIC clock - in your case (I think you are using a crystal) the accuracy of the crystal oscillator. Below is what I understand from your code:
Crystal oscillator: 4MHz
Timer 1 clock source: Fosc/4 = 1MHz = 1uS
Timer 1 prescaler: 1:8, so timer 1 counter input is 8uS
Timer 1 preset: 63036. This gives an overflow every (65536 - 63036) = 2500 cycles
Timer 1 overflow: 2500 * 8uS = 20,000uS = 20mS
Overflow counter: 100. So full cycle time is 100 * 20mS = 2 seconds.

So the 2 second timing is exact if the crystal is exact.
 

Thread Starter

emalper

Joined Aug 4, 2016
24
The ultimate accuracy achievable depends on the accuracy of the PIC clock - in your case (I think you are using a crystal) the accuracy of the crystal oscillator. Below is what I understand from your code:
Crystal oscillator: 4MHz
Timer 1 clock source: Fosc/4 = 1MHz = 1uS
Timer 1 prescaler: 1:8, so timer 1 counter input is 8uS
Timer 1 preset: 63036. This gives an overflow every (65536 - 63036) = 2500 cycles
Timer 1 overflow: 2500 * 8uS = 20,000uS = 20mS
Overflow counter: 100. So full cycle time is 100 * 20mS = 2 seconds.

So the 2 second timing is exact if the crystal is exact.
Code:
#include <16f877.h>    


#fuses XT,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD

#use delay(clock=4000000)   

int i; 

const int digit[16]={0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7C, 0x07, 0x7F, 0x6F, 0x77};

void main ()
{
   setup_psp(PSP_DISABLED);        
   setup_timer_1(T1_DISABLED);     
   setup_timer_2(T2_DISABLED,0,1); 
   setup_adc_ports(NO_ANALOGS);    
   setup_adc(ADC_OFF);            
   setup_CCP1(CCP_OFF);            
   setup_CCP2(CCP_OFF);         

   set_tris_a(0x00); 
   set_tris_b(0x00); 

   output_b(0x00);  
   output_a(0x02);  

   while(1)   
   {
      for(i=0;i<=15;i++)
      {
         output_b(digit[i]); 
         delay_ms(500);     
      }
   }
}
So i gave up on timer for a while and i just did this a a example for seven segmnet display but this one is just goes ip lie 1-2-3-4-5... and i want it to go down from 9 to 0. Do you have any idea how can i do that? What is wrong with it? I tried to change for(i=0;i<=15;i++) to for(i=9;i=0;i--) but when i do then it stops working entirely. Why?
 

AlbertHall

Joined Jun 4, 2014
12,346
Like I said I don't know the CCS compiler. i is declared as an int which I would expect to a signed int but, just to make sure declare i as signed int.
 

AlbertHall

Joined Jun 4, 2014
12,346
Also try for(i=9;i>=0;--i) depending on which order the compiler does things.
FWIW the Microchip XC8 compiler works with for(i=9;i>=0;i--)
 

Thread Starter

emalper

Joined Aug 4, 2016
24
Also try for(i=9;i>=0;--i) depending on which order the compiler does things.
FWIW the Microchip XC8 compiler works with for(i=9;i>=0;i--)
i understand thank you it works correctly now with this one. What about buttons. can you tell me how can i add them? I mean what is the idea of the buttons like rest? or set time which will start from counting up or down.
 

AlbertHall

Joined Jun 4, 2014
12,346
You can connect a button to any i/o pin and ground. You will need to either have a pullup resistor from the pin to VCC (22k not critical) or enable the weak pullup on the pin if it has one. You need to be aware that switch contacts bounce they don't just close once but umpteen times over a period of several milliseconds. There are plenty of routines about to debounce buttons but much the easiest way is to just read them no more often than about every 50mS (longer than the period of the bouncing).
 
Top