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;
}
いやぁ、やればできる!