Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

PIC12F629 counter

Status
Not open for further replies.

Mat22

New Member
Hello,

I am trying to turn LED on GP1 if I press push button on GP2 2 times, and if I press it 3 times I would like to turn LED on GP4. Is this a good way to start?

Code:
void main() {

  /* Project name:
     Detect low voltage
* Description:
     Car direction indicators
* Test configuration:
     MCU:             PIC12F629
     Dev.Board:       EasyPIC5
     Oscillator:      04.0000 MHz, Internal
     SW:              mikroC PRO for PIC
*/
unsigned char i;
bit oldstate;                       // Old state flag

{

CMCON = 0b00000111;                 // disable comparators
GPIO = 0b00000000;
TRISIO = 0b00000100;                     // gp2= input, gp1, gp4 = outputs
OPTION_REG = 0b11110100;                 // Counter TMR0 receives pulses through the RA2 pin, Prescaler rate is 1:32
TMR0 = 0 ;


  while (1)
   {

    if (TMR0 == 2)              // while GP2 is switched 2 times turn on gpio.F1
        {
        gpio.F1 = 1;
        }
    if (TMR0 == 3)              // while GP2 is switched 3 times turn on gpio.F4
        {
        gpio.F4 = 1;
        }
     }
       }

        }
 
When a button is pressed it "bounces" producing short pulses for a while until it stabilizes. This happens to all except, perhaps, very best buttons. If you count pulses, you'll get all these short pulses from bouncing and won't be able to tell the real button press.
 
If you read the state of the switches at say 50 hz then you'll leave enough time inbetween to ignore bounces, nearly all of my software does this.
 
Using a timer to count button press is a waste cause it counts really fast it will count
All the bounce of the switch.
I would use a loop
Like if button down wait 50ms is button still down we have a press
 
I have tried on another way:

Code:
/*******************************************************************************
  CONFIG = 0x31D4
  Project > PIC12F629:
                        Oscillator: Internal RC No Clock (fixed 4MHz)
                        WDT: Off
                        PUT: Off
                        MCLRE: Diasbled (Internal Pull-up)
                        BOD: On
                        CP: Off
                        Data EE RP: Off
*******************************************************************************/

unsigned short int i;

void interrupt(){

    if (INTCON.INTF){                       // if interrupt comming...
      GPIO.F0 = 1;                          //GPIO.F0 is always ON when program starts
      if      (i==1) {GPIO.F1 = 1;}         // when we press 1 time GPIO.F1 is ON
//debounce routine??
      else if (i==2) {GPIO.F4 = 1;}         // when we press 2 times GPIO.F4 is ON
//debounce routine??
      else if (i==3) {GPIO.F5 = 1;}         // when we press 3 times GPIO.F5 is ON
//debounce routine??
    }
    INTCON.INTF = 0;                         // GP2 interrupt flag
}

void main() {
     INTCON = 0b11010000;
     CMCON = 0b00000111;
     TRISIO = 0b00000100;
     GPIO = 0b00001100;                      // all LEDs are OFF
     OPTION_REG.INTEDG = 0;                  // interrupt on falling edge

     while(1){
          for(i=1; i<4; i++){
             delay_ms(5);
          }
     }
}

it works but not in a way I would like, after restart of program it executes in different manner. On the begining GPIO.F0 is ON but when I press push button ones GPIO.F5 or F4 is ON. After GPIO.F0, GPIO.F1 should turn on, after that F4 and F5 at the end.
Where should I put debounce routine, in the code where I have put notes, or?

thanks
 
In the program you wrote, i advances regardless of what you do with buttons.

You need something like that (pseudo-code):

Code:
i = 1;
while(1) {
  while (button is up) ;
  wait(50ms);
  if (button is down) {
      switch(i++) {
         case ...
      }
  }
}
 
If you want to read the button you have to think about what happens when it's pressed. First the button bounces for any where from 0 to 100ms some even more. So what happens is you look for the change say on press the button goes low.

Ok code it like this
if button = low then
DelayMs (100)
If button = low then
update count
Do what you want to happen based on count
Clear count
 
Thank you for your help,

I make code:
Code:
/*******************************************************************************
  CONFIG = 0x31D4
  Project > PIC12F629:
                        Oscillator: Internal RC No Clock (fixed 4MHz)
                        WDT: Off
                        PUT: Off
                        MCLRE: Diasbled (Internal Pull-up)
                        BOD: On
                        CP: Off
                        Data EE RP: Off
*******************************************************************************/

unsigned short int i;
void main() {
     INTCON = 0b11010000;
     CMCON = 0b00000111;
     TRISIO = 0b00000100;
     GPIO = 0b00001100;                      // all LEDs are OFF

    GPIO.F0 = 1;                             //GPIO.F0 is always ON when program starts
    i=0;                                     // start value of counter
    while(1) {
    if (GPIO.F2=1)                             // if button is pressed
    {
      delay_ms(200);
      if  (GPIO.F2=1)                          //if button is still pressed
      {                                        // increment counter by 1
     i=i+1;
      }
      if (i==1)
      {GPIO.F1 = 1;}                           // when we press 1 time GPIO.F1 is ON

      if (i==2)                                // when we press 2 times GPIO.F1,GPIO.F4 is ON
      {GPIO.F1 = 1;GPIO.F4 = 1;GPIO.F5 = 0;}

      if (i==3)                                // when we press 3 times GPIO.F1, GPIO.F4,GPIO.F5 is ON
      {GPIO.F1 = 1;GPIO.F4 = 1;GPIO.F5 = 1;}

    }
}
}

and it works only when I am holding push button pressed all the time - outputs are turning ON in a sequence like in the code.
I would like to press PB ones to turn on GPIO.F1. tvice to turn F1 and F2.
Where is mistake?
 
Your still not turning off the ADC
I wrote a little code to play with last night and you can't read a button without turning off the adc
Code:
bit oldstate;                                    // Old state flag
void main() {
  ANSEL = 0x00;                                 // clears the ANSEL makes pin I/O don't need on the 12f629
  CMCON = 0b00000111;                   // turns off the compare mod
  TRISIO = 0b00100000;                  // set input on gp5 outputs the rest
  GPIO = 0b00000000;                     // clears gpio
  GPIO.GP0 = 1;                                 // turns on the led to start to show the chips running
  oldstate = 0;                                      //sets oldstate to 0
  do {
    if (Button(&GPIO, 5, 0, 0)) {               // Detect logical lows
      oldstate = 1;                              // Update flag
    }
    if (oldstate && Button(&GPIO, 5, 0, 1)) {   // Detect low to high transition
      GPIO.GP0 = ~GPIO.GP0;                              // Invert gpio.gp0
     // you could add count code here and remove the gpio stuff above the invert part only
      oldstate = 0;                              // Update flag
    }
    // put code here to act on count
  } while(1);                                    // Endless loop
}
The Button code is from the help file I just made changes to use with the 12f629 chip
 
Last edited:
I think that ANSEL isn't valid SFR for 12F629?
You are right i used the 12f675 sorry bout that i added that to my comment.
but there both the same all but the ADC so code i posted will work. Just add a count var
and what you want to happen based o count and go from there
 
Last edited:
Burt, you are great :), thank you very much for your help,

code works:

Code:
bit oldstate;                                    // Old state flag
unsigned short int i;
void main() {

  CMCON = 0b00000111;                    // turns off the compare mod
  TRISIO = 0b00000100;                   // set input on gp2 outputs the rest are outputs
  GPIO = 0b00000000;                     // clears gpio
  GPIO.GP0 = 1;                                 // turns on the led to start to show the chips running
  oldstate = 0;                                      //sets oldstate to 0
  i=0;
  do {
    if (Button(&GPIO, 2, 0, 0)) {               // Detect logical lows
      oldstate = 1;                              // Update flag
    }
    if (oldstate && Button(&GPIO, 2, 0, 1)) {   // Detect low to high transition
                                               // increment counter by 1
     i=i+1;
                                                  // increment counter
      oldstate = 0;                              // Update flag
    }
      if (i==1)                                 // put code here to act on count
      {GPIO.F1 = 1;}                           // when we press 1 time GPIO.F1 is ON

      if (i==2)                                // when we press 2 times GPIO.F1,GPIO.F4 is ON
      {GPIO.F1 = 1;GPIO.F4 = 1;GPIO.F5 = 0;}

      if (i==3)                                // when we press 3 times GPIO.F1, GPIO.F4,GPIO.F5 is ON
      {GPIO.F1 = 1;GPIO.F4 = 1;GPIO.F5 = 1;}

  } while(1);                                    // Endless loop
}
 
Is it possible to add delay function to work like this:
if (i==1) // put code here to act on count
{GPIO.F1 = 1;} // when we press 1 time GPIO.F1 is ON
//add delay 1 minute then
GPIO.F1=0; // turn OFF GP1!
if (i==2) // when we press 2 times GPIO.F1,GPIO.F4 is ON
{GPIO.F1 = 1;GPIO.F4 = 1;GPIO.F5 = 0;}
//add delay 2 minutes then
GPIO.F1=0; GPIO.F4=0; // turn OFF GP1, GP4!
if (i==3) // when we press 3 times GPIO.F1, GPIO.F4,GPIO.F5 is ON
{GPIO.F1 = 1;GPIO.F4 = 1;GPIO.F5 = 1;}
//add delay 3 minutes then
GPIO.F1=0; GPIO.F4=0;GPIO.F5=0; // turn OFF GP1, GP4,GP5!
 
I was play with that idea myself going to use the port change interrupts to run the button read code then do what needs to be done.
I got side tracked with some software pwm. But yes u can do that but you need interrupts on change to read the buttons or you'll not get updated press of the
button.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top