ITで遊ぶ

省電力一定時間点滅 スイッチ付プログラム

XC8で書いた。

普段はSLEEPし32.768KHzクリスタルでTimer1のシグナル入力とする。
Timer1がカウントアップすると割り込みをおこし、ポートをオン・オフする。(割り込みルーチン内で問題ないようだ)
プログラムは内部クロックで動くことになるが、ほとんどSLEEPしている。

PICの発想はTimer1が正確であれば、作業をするためのクロックは内部の4MHzでよい、という考えのようだ。

LEDを周波数にかかわらず一定時間で点滅させるためにsigned integerの最大値0x7fffから0xffff-(HI_VALUE* 0x10) – LOW_VALUE = タイマー割り込みがかかるカウントをマイナスしていくことにした。
これならば、遅い周波数のときは一秒あたりの割り込み回数は少ないが大きい値がひかれる。早い周波数のときは位置秒あたりの割り込み回数は多いが小さい値がひかれる。
いいかえると仮想一定時間0x7fffをカウントしているようなものだ。

なにかのトラブルでソースがなくなると困るので保管しておく。


/*
 * main.c
 * AUthor : Tsukasa Takao Mind Craft Co.ltd.
 * Created on 2020/09/12, 21:47
 *  This program is for MCLR switch. 
 */

// PIC12F629 Configuration Bit Settings

// 'C' source line config statements

// CONFIG
#pragma config FOSC = INTRCIO  // Oscillator Selection bits (INTOSC oscillator: CLKOUT function on GP4/OSC2/CLKOUT pin, I/O function on GP5/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON       // Power-Up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = ON       // GP3/MCLR pin function select (GP3/MCLR pin function is MCLR)
#pragma config BOREN = OFF      // Brown-out Detect Enable bit (BOD disabled)
#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)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include 

#define _XTAL_FREQ 4000000

#define HIGH_VALUE 0xF7
#define LOW_VALUE 0xD6  //7.836, if raise, 7.84


//#define HIGH_VALUE 0xFF  // max 5.494 KHz
// #define LOW_VALUE 0xeb   // 746-7 Hz (near by 741)
//#define LOW_VALUE 0xe7      // 635 (near by 639)

#define DUR_VALUE (0xFFFF - (HIGH_VALUE * 0x100) - LOW_VALUE)/2

#define COIL GP0
#define LED  GP2
#define BTN  GP3  // for MCLRE

signed int dur_value = DUR_VALUE;
signed int LED_count = 0x7FFF;

static void setup(){
    CMCON = 0x07; // do not use comparator
    TRISIO = 0b000111000; // all output except GP3 always in, GP4,5 used by clock
    GPIO = 0; // reset

    if (nPOR == 0)
    {
        nPOR = 1;
        GPIO=0;
        
        INTCONbits.GIE = 0; // required for sleep
        T1CONbits.TMR1ON = 0; // once OFF.
        
        SLEEP();
        NOP();
    } 
    
    if ( nTO == 1) 
    {
        nPOR = 0; 
    }

    //Timer 1 setup
    INTCONbits.PEIE = 1; // required on. don'T change
    PIE1bits.TMR1IE = 1; // required on. don't change
    
    PIR1bits.TMR1IF = 0; // reset
    
    T1CONbits.TMR1GE = 0; // no gate enable
    T1CONbits.T1CKPS1 = 0; // no prescaler
    T1CONbits.T1CKPS0 = 0; // no prescaler
    T1CONbits.T1OSCEN = 1; // required on. don't change LP oscilater run
    T1CONbits.nT1SYNC = 1; // asyncronous
    T1CONbits.TMR1CS = 1;  // External clock
    T1CONbits.TMR1ON = 0; // once OFF.
        
    // if set, 0x8000 on 32768Hz, it is 1 second.
    TMR1H = HIGH_VALUE;
    TMR1L = LOW_VALUE;
    
    T1CONbits.TMR1ON = 1; // start timer.
    INTCONbits.GIE = 1 ; // enable interruption
}

static void interrupt ISR(void){
    if (PIR1bits.TMR1IF){
        T1CONbits.TMR1ON = 0; // stop timer
        PIR1bits.TMR1IF = 0;
        // 
        COIL = !COIL;
        // LED brink slow and not related with frequency.
        LED_count -= dur_value;
        if (LED_count < 0){
            if (LED == 0){
                LED = 1;
                LED_count = 0x7fff / 4;
            } else {
                LED = 0;
                LED_count = 0x7fff ;
            }
        } 

        // reset timer
        TMR1H = HIGH_VALUE;
        TMR1L = LOW_VALUE;
        T1CONbits.TMR1ON = 1; // start timer
    }
}

void main(void) {
    setup();
    
    while(1){                
      SLEEP();  
      NOP();      
    }
    return;
}

いやぁ、やればできる!

関連記事

  1. ハッカソンって騒ぐだけ?

  2. 製品を作るおじさんの独り言

  3. スマホから機器をBluetoothでオン・オフ

  4. 進歩だけするラズパイOS

  5. micro:bit + BLE + ChromeブラウザーそしてPro…

  6. CodeIgniterのScaffolding

  7. やっぱりドットインストールは勉強にいい

  8. 水中のGoproをコンピューターで操作する

記事をプリント