Timer with button PIC16F877A

Thread Starter

emalper

Joined Aug 4, 2016
24
Hi guys i am developing a timer for my homemade uv exposure box. I wrote some codes and succesfully implement timer into those codes. But what i need is i need a push button which will turn on the timer. For example i have one led connected to RB0 pin and when i plug in the circuit timer starts to count down and the led toggle with every flow. But when i plug in the circuit i dont want the timer to start counting. I want it to start when i push the button. So can anyone help me with this? I am using micro c language.
C:
sbit LCD_RS at RC2_bit;
sbit LCD_EN at RC3_bit;
sbit LCD_D4 at RC4_bit;
sbit LCD_D5 at RC5_bit;
sbit LCD_D6 at RC6_bit;
sbit LCD_D7 at RC7_bit;
sbit LCD_RS_Direction at TRISC2_bit;
sbit LCD_EN_Direction at TRISC3_bit;
sbit LCD_D4_Direction at TRISC4_bit;
sbit LCD_D5_Direction at TRISC5_bit;
sbit LCD_D6_Direction at TRISC6_bit;
sbit LCD_D7_Direction at TRISC7_bit;
sbit LED at RB0_bit;
char message1[] = "PCB UV";
char message2[] = "EXPOSURE UNIT";
char message3[] = "PHOTORESIST";
char message4[] = "SOLDER MASK";
char message5[] = "REMAINING:";
unsigned short time;

void interrupt() {
  time++ ;
  if (time == 100) {          // if time is 76
      LED  = ~LED;        // then toggle led and
      time = 0;                // reset time
      }
  PIR1.TMR1IF = 0;            // clear TMR1IF
  TMR1H = 128;
  TMR1L = 0;
}
void main() {
  PORTB = 0x00;               // Initialize PORTB
  TRISB = 0;                  // PORTB is output
  T1CON = 1;                  // Timer1 settings
  PIR1.TMR1IF = 0;            // clear TMR1IF
  TMR1H = 128;               // Initialize Timer1 register
  TMR1L = 0;
  PIE1.TMR1IE  = 1;           // enable Timer1 interrupt
  time =   0;                  // initialize cnt
  INTCON = 0xC0;              // Set GIE, PEIE
  start:
  Lcd_Init();                        // Initialize LCD
  Lcd_Cmd(_LCD_CLEAR);               // Clear display
  Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off
  Lcd_Out(1,6,message1);
  Lcd_Out(2,3,message2);
  do {

    } while (1);
}
 
Last edited by a moderator:

JohnInTX

Joined Jun 26, 2012
4,787
I would reorganize the code to control the timer on/off in the while loop. Since you have only 2 conditions, use a flag to indicate whether the timing is running. Toggle the flag with the button. Something like:

while (1){
process_the_button_toggle_flag()

if(flag_changed)
if(flag==1) // it was 0 before..
init_timer_interrupt_stuff();
start_timer();
else // flag was 1, now is 0
stop_timer();
LED_off();
}//while

Processing the button would incorporate debouncing as necessary. I don't usually do IO an interrupt routine preferring instead to set a flag indicating an event has occurred (timeout in this case) then processing in the main loop but it's OK for now.

Good luck!
 

Thread Starter

emalper

Joined Aug 4, 2016
24
Hi guys i am developing a timer for my homemade uv exposure box. I wrote some codes and succesfully implement timer into those codes. But what i need is i need a push button which will turn on the timer. For example i have one led connected to RB0 pin and when i plug in the circuit timer starts to count down and the led toggle with every flow. But when i plug in the circuit i dont want the timer to start counting. I want it to start when i push the button. So can anyone help me with this? I am using micro c language.
C:
sbit LCD_RS at RC2_bit;
sbit LCD_EN at RC3_bit;
sbit LCD_D4 at RC4_bit;
sbit LCD_D5 at RC5_bit;
sbit LCD_D6 at RC6_bit;
sbit LCD_D7 at RC7_bit;
sbit LCD_RS_Direction at TRISC2_bit;
sbit LCD_EN_Direction at TRISC3_bit;
sbit LCD_D4_Direction at TRISC4_bit;
sbit LCD_D5_Direction at TRISC5_bit;
sbit LCD_D6_Direction at TRISC6_bit;
sbit LCD_D7_Direction at TRISC7_bit;
sbit LED at RB0_bit;
char message1[] = "PCB UV";
char message2[] = "EXPOSURE UNIT";
char message3[] = "PHOTORESIST";
char message4[] = "SOLDER MASK";
char message5[] = "REMAINING:";
unsigned short time;

void interrupt() {
  time++ ;
  if (time == 100) {          // if time is 76
      LED  = ~LED;        // then toggle led and
      time = 0;                // reset time
      }
  PIR1.TMR1IF = 0;            // clear TMR1IF
  TMR1H = 128;
  TMR1L = 0;
}
void main() {
  PORTB = 0x00;               // Initialize PORTB
  TRISB = 0;                  // PORTB is output
  T1CON = 1;                  // Timer1 settings
  PIR1.TMR1IF = 0;            // clear TMR1IF
  TMR1H = 128;               // Initialize Timer1 register
  TMR1L = 0;
  PIE1.TMR1IE  = 1;           // enable Timer1 interrupt
  time =   0;                  // initialize cnt
  INTCON = 0xC0;              // Set GIE, PEIE
  start:
  Lcd_Init();                        // Initialize LCD
  Lcd_Cmd(_LCD_CLEAR);               // Clear display
  Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off
  Lcd_Out(1,6,message1);
  Lcd_Out(2,3,message2);
  do {

    } while (1);
}
When i try to reorganize the code to control the timer on/off in the while loop and implement you example i got a error. Why does it say there is a error?
Code:
sbit LCD_RS at RC2_bit;
sbit LCD_EN at RC3_bit;
sbit LCD_D4 at RC4_bit;
sbit LCD_D5 at RC5_bit;
sbit LCD_D6 at RC6_bit;
sbit LCD_D7 at RC7_bit;
sbit LCD_RS_Direction at TRISC2_bit;
sbit LCD_EN_Direction at TRISC3_bit;
sbit LCD_D4_Direction at TRISC4_bit;
sbit LCD_D5_Direction at TRISC5_bit;
sbit LCD_D6_Direction at TRISC6_bit;
sbit LCD_D7_Direction at TRISC7_bit;
sbit LED at RB0_bit;
char message1[] = "PCB UV";
char message2[] = "EXPOSURE UNIT";
char message3[] = "PHOTORESIST";
char message4[] = "SOLDER MASK";
char message5[] = "REMAINING:";
unsigned short time;

void interrupt() {
  time++ ;
      time = 0;                // reset time
      }
  PIR1.TMR1IF = 0;            // clear TMR1IF
  TMR1H = 128;
  TMR1L = 0;
}
void main() {
  PORTB = 0x00;               // Initialize PORTB
  TRISB = 0;                  // PORTB is output
  T1CON = 1;                  // Timer1 settings
  PIR1.TMR1IF = 0;            // clear TMR1IF
  TMR1H = 128;               // Initialize Timer1 register
  TMR1L = 0;
  PIE1.TMR1IE  = 1;           // enable Timer1 interrupt
  time =   0;                  // initialize cnt
  INTCON = 0xC0;              // Set GIE, PEIE
  start:
  Lcd_Init();                        // Initialize LCD
  Lcd_Cmd(_LCD_CLEAR);               // Clear display
  Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off
  Lcd_Out(1,6,message1);
  Lcd_Out(2,3,message2);
  do {

    } while (1)
process_the_button_toggle_flag()

if(flag_changed)
if(flag==1) // it was 0 before..
init_timer_interrupt_stuff();
start_timer();
else // flag was 1, now is 0
stop_timer();
LED_off();
}
And also it doesnt have to toggle the led. When i press the push button led will turn on and the timer will start and when times run out the led turns off.
 
Last edited:

JohnInTX

Joined Jun 26, 2012
4,787
What I wrote was something called 'pseudo-code' to show the basic idea of what the code would look like. process_the_button_toggle_flag() is pseudo-code. It means that in my suggested design, you would have to write a C function that sampled the button and toggled a flag. The function would be called where it was shown in the pseudo-code. Pseudo-code allows ideas to be communicated showing the basic structure and function of the code without getting hung up on details and syntax.

The compiler is complaining because it expects a function of that name and there isn't one yet. It will also complain about the missing ';' but that's not the important thing here.

BTW, what I wrote was just a suggestion. You might think of a better way.
 

Thread Starter

emalper

Joined Aug 4, 2016
24
Okey now i get it thank you) and also i have one more question about the timer. The timer code which is written is toggle the led about 3s and i want to make it lets say 5 min. How can i calculate it. There is a lot of example on the internet but how much i read it i cant implement this idea into my code. So can you help me with this too?
 

JohnInTX

Joined Jun 26, 2012
4,787
I like to use 'derived timers' i.e. create a short system timer of 1ms - 10ms or so per interrupt. On each interrupt, decrement one or more 1 byte variables to zero and leave them there. To flash something like the LED, assign it a derived timer, load it and then check it for zero. When it is zero, toggle the LED and reload the timer. Note that with this approach, you don't have to wait around for timeout, you can do other things between sampling the LED timer - other things like processing the button.

With a PIC, TMR2/PR2 is ideal for creating a system tik. Once set up, it can generate periodic interrupts with no further intervention. Your service routine would look something like this:
C:
unsigned char LEDtimer;  // two derived timers
unsigned char debounceTimer;

void interrupt(void)
{
    if(timer 2 interrupt){
     clear interrupt flag;
     if(LEDtimer) LEDtimer--;  // dec to 0 and leave at 0
    if(debounceTimer) debounceTimer--;
}//if timer 2 IRQ
}
In main you would do something like this in your while loop:

C:
while (1){
  if(LEDtimer==0){ // if timed out..
     toggleLED;  // toggle the LED
     LEDtimer = reload_value; // and reset the timer for next time
  }
  //... do other things in the while loop
}// while
Choose the timer period so that times fit into one byte. If you have a wide range of times that can't be accommodated use one of the derived timers as a prescaler to another set of longer timers. For example if your systik was 10ms in the interrupt routine you would add something like:
C:
 unsigned char sec1prescaler;  // one second prescaler

sec1prescaler--;  // decrement the prescaler
  if(unsigned char sec1prescaler==0){ .. when it times out..
    sec1prescaler=100;  // reload the prescaler 100 * 10ms systik = one second
    if(LEDtimer) LEDtimer==0;    // now LEDtimer runs at a 1 second period.
That's how I do general timing FWIW. Its not perfect but works for many cases.
 

Picbuster

Joined Dec 2, 2013
1,047
Hi guys i am developing a timer for my homemade uv exposure box. I wrote some codes and succesfully implement timer into those codes. But what i need is i need a push button which will turn on the timer. For example i have one led connected to RB0 pin and when i plug in the circuit timer starts to count down and the led toggle with every flow. But when i plug in the circuit i dont want the timer to start counting. I want it to start when i push the button. So can anyone help me with this? I am using micro c language.
C:
sbit LCD_RS at RC2_bit;
sbit LCD_EN at RC3_bit;
sbit LCD_D4 at RC4_bit;
sbit LCD_D5 at RC5_bit;
sbit LCD_D6 at RC6_bit;
sbit LCD_D7 at RC7_bit;
sbit LCD_RS_Direction at TRISC2_bit;
sbit LCD_EN_Direction at TRISC3_bit;
sbit LCD_D4_Direction at TRISC4_bit;
sbit LCD_D5_Direction at TRISC5_bit;
sbit LCD_D6_Direction at TRISC6_bit;
sbit LCD_D7_Direction at TRISC7_bit;
sbit LED at RB0_bit;
char message1[] = "PCB UV";
char message2[] = "EXPOSURE UNIT";
char message3[] = "PHOTORESIST";
char message4[] = "SOLDER MASK";
char message5[] = "REMAINING:";
unsigned short time;

void interrupt() {
  time++ ;
  if (time == 100) {          // if time is 76
      LED  = ~LED;        // then toggle led and
      time = 0;                // reset time
      }
  PIR1.TMR1IF = 0;            // clear TMR1IF
  TMR1H = 128;
  TMR1L = 0;
}
void main() {
  PORTB = 0x00;               // Initialize PORTB
  TRISB = 0;                  // PORTB is output
  T1CON = 1;                  // Timer1 settings
  PIR1.TMR1IF = 0;            // clear TMR1IF
  TMR1H = 128;               // Initialize Timer1 register
  TMR1L = 0;
  PIE1.TMR1IE  = 1;           // enable Timer1 interrupt
  time =   0;                  // initialize cnt
  INTCON = 0xC0;              // Set GIE, PEIE
  start:
  Lcd_Init();                        // Initialize LCD
  Lcd_Cmd(_LCD_CLEAR);               // Clear display
  Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off
  Lcd_Out(1,6,message1);
  Lcd_Out(2,3,message2);
  do {

    } while (1);
}
Switch enables off during power up and activate them in main ( use one pin to toggle ==> enable=! enable)
Picbuster
 
Top