How to toggle on/off momentary pushbutton with PIC12F629


Do you think adding on/offf switch on pic12F629 ?

One of the best way is using interruption.

Many developers had made this type of question on the net.

But I have never found any sample source code. Most of all people just give suggestions.

Therefore, I put here my sample source code for other developers.

It was not easy. For example, sw_count variable is from my experience.

Switch part schematics is as follows (Xtal is not mandatory)

(9/21/2016: For long bouncing switch, wait is inserted.)


Hope your help.

— In Japanese




  1. まず、PIC12F629の特性に注目する。
  2. PORT3はそのため他のポートと違って、プログラムでプルアップ(抵抗を介して電圧をかける)できない
  3. ポートの変化による割り込みは、通常はGIEをオンにすると割り込みがかかる
  4. ポートの変化による割り込みは、SLEEP中はGIEをオンにしなくてもポート変化割り込みの設定をしていれば起きる。この時、割り込みルーチンには飛ばない
  5. 確認のために記しておくが、GIEをオンにしてSLEEPすると起きてから割り込みルーチンに飛ぶ
#include <xc.h>
// #pragma config statements should precede project file includes.
#pragma config FOSC = HS        // (HS oscillator: High speed crystal/resonator on GP4/OSC2/CLKOUT and GP5/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON       // Power-Up Timer Enable bit (PWRT enabled) DO NOT ON
#pragma config MCLRE = OFF      // GP3/MCLR pin function select (GP3/MCLR pin function is digital I/O)
#pragma config BOREN = OFF      // Brown-out Detect Enable bit (BOD disabled) DO NOT USE
#pragma config CP = ON          // Code Protection bit (Program Memory code protection is enabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)

#define _XTAL_FREQ 10000000     
#define BTN GPIO3 // Pic12F629 use this port as MCLR, but I want to use on/off switch.

volatile unsigned int sw_count;
volatile unsigned int req_sleep; // sleep request flag

// main
void main(void){
    CMCON = 7; //GPIO use all digital port

    TRISIO = 0b00001000; //GPIO port3 is input, others output
    IOC = 0b00001000; // port3 interruption enable
    GPIO = 0b00000000; //GPIO initialize
    GPIE = 1; // INTCON port interrupt enable
    INTEDG = 0; // pin down, raise interrupt
    GIE = 0;
    LED = 0;
    req_sleep = 1;
        if (req_sleep == 1){
            GIE = 0; // After SLEEP, for waking up, you don't need GIE up.
                    // And if you GIE is off, interruption routine is not inserted.
            __delay_ms(400); // wait for chattering
            sw_count = 0;
            req_sleep = 0; // SLEEP request reset
            GIE = 1; // for switch on detection during running. 
      * here is main work.

void interrupt ISR(void){
    char temp;
    GIE = 0;

    if (GPIF){
       temp = GPIO; // Read for synchronize status.
       GPIF = 0; // Once off to protect interruption
       sw_count++; // chattering count
       if (sw_count >2){ // Tentative value 3 
                req_sleep = 1; // Enough. DO NOT allow interruption any more
        } else {
          GIE = 1; // Still allow interruption


If you know better code, please let me know.