How to toggle on/off momentary pushbutton with PIC12F629

私のIOT

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.)

hardware

Hope your help.

— In Japanese
PIC12F629にモーメンタリースイッチを取り付けて、オン、オフしたいと考える人は多いと思う。

ずーっとコーディング例を調べていたけれども具体的なものはなかった。

私の開発したサンプルを置いておく。

以下、前提情報

  1. まず、PIC12F629の特性に注目する。
    PORT3はリセットもしくは入力専用ポートとしてつかわれる。
  2. PORT3はそのため他のポートと違って、プログラムでプルアップ(抵抗を介して電圧をかける)できない
  3. ポートの変化による割り込みは、通常はGIEをオンにすると割り込みがかかる
  4. ポートの変化による割り込みは、SLEEP中はGIEをオンにしなくてもポート変化割り込みの設定をしていれば起きる。この時、割り込みルーチンには飛ばない
  5. 確認のために記しておくが、GIEをオンにしてSLEEPすると起きてから割り込みルーチンに飛ぶ
/*
 *
*/
#include <xc.h>
// #pragma config statements should precede project file includes.
// CONFIG
#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){
//Initialization
    
    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;
    __delay_ms(500);
    LED = 0;
    req_sleep = 1;
    
    while(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
            SLEEP();
            NOP();
            __delay_ms(300);
            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.

コメント