/* 『簡易周波数カウンター(校正(Calibration)機能付き)』 <構成概要> ・内臓のクロック8MHzを使用する。 ・計測結果はRS232C(9600bps)で送信する。 ・校正機能により精度向上を可能とする。 ・ゲートタイムは1秒、0.1秒とする。 ・プリスケール値は1/1、1/8とする。 <SW割り当て> ・SW1:1(校正しない)、0(校正する) ・SW2:1(プリスケール値1/1)、0(プリスケール値1/8) ・SW3:1(ゲートタイム1秒)、0(ゲートタイム0.1秒) ・SW4:1(Hz表示)、0(kHz表示) <デフォルトの校正値> ・CAL100msec 25000=0.1/((1/8000000)*4*8) 0x9E58=65536-25000 ・CAL1sec 250000=1/((1/8000000)*4*8) 0x2F70=65536-(250000-(65536*3)) */ //********************************************************************** #define SW1 GPIO.F0 #define SW2 GPIO.F1 #define SW3 GPIO.F3 #define SW4 GPIO.F4 #define GATETIME_100MSEC 10 #define GATETIME_1SEC 1 static unsigned int CAL1sec; static unsigned int CAL100msec; //********************************************************************** static short interruptCnt; void interrupt() { if (PIR1.TMR1IF == 1) { PIR1.TMR1IF = 0; // interruptCnt--; if (interruptCnt == 0) { TRISIO.F2 = 0; // ゲートを閉める。 GPIO.F2 = 0; T1CON.TMR1ON = 0; // TIMER1を停止する。 } } } //********************************************************************** unsigned long FreqMeasurement(unsigned short gateTime) { unsigned long freq; // ゲートを閉める。 TRISIO.F2 = 0; GPIO.F2 = 0; // TIMER0の設定 INTCON.T0IF = 0; TMR0 = 0; // TIMER1の設定 PIR1.TMR1IF = 0; switch (gateTime) { case GATETIME_100MSEC: interruptCnt = 1; TMR1L = CAL100msec & 0xFF; TMR1H = (CAL100msec >> 8) & 0xFF; break; case GATETIME_1SEC: interruptCnt = 4; TMR1L = CAL1sec & 0xFF; TMR1H = (CAL1sec >> 8) & 0xFF; break; } // freq = 0; // 割り込みを許可する。 INTCON.PEIE = 1; INTCON.GIE = 1; // TIMER1を開始する。 T1CON.TMR1ON = 1; // 遅延する。 Delay_Cyc(2); asm nop asm nop asm nop asm nop asm nop asm nop asm nop asm nop // TRISIO.F2 = 1; // ゲートを開ける。 // 測定 while (T1CON.TMR1ON != 0) { if (INTCON.T0IF == 1) { INTCON.T0IF = 0; freq++; } } if (INTCON.T0IF == 1) { INTCON.T0IF = 0; freq++; } freq = (freq * 256) + TMR0; return (freq); } //********************************************************************** void Soft_Uart_Write_String(char *buf) { short len, i; len = strlen(buf); for (i = 0; i < len; i++) { INTCON.GIE = 0; Soft_Uart_Write(buf[i]); INTCON.GIE = 1; } } //********************************************************************** void main() { static unsigned long freq, temp; // 0...4294967295 static unsigned char buf[12], prescaler, gateTime; // OSCCON = 0b01110000; // クロックは8Mhz ANSEL = 0b00000000; // 今回は使用しない。 CMCON0 = 0b00000111; // 今回は使用しない。 TRISIO = 0b00011111; OPTION_REG.F7 = 0; // PORTをプルアップ設定する。 WPU.F0 = 1; WPU.F1 = 1; WPU.F4 = 1; // TIMER0の設定 INTCON.T0IE = 0; INTCON.T0IF = 0; OPTION_REG.T0CS = 1; OPTION_REG.T0SE = 0; OPTION_REG.PSA = 1; OPTION_REG.PS0 = 0; OPTION_REG.PS1 = 0; OPTION_REG.PS2 = 0; // TIMER1の設定 PIE1.TMR1IE = 1; PIR1.TMR1IF = 0; T1CON.T1CKPS0 = 1; T1CON.T1CKPS1 = 1; T1CON.TMR1ON = 0; // 保存されている校正値の取り込み CAL100msec = Eeprom_Read(1); CAL100msec = CAL100msec << 8; CAL100msec = CAL100msec | Eeprom_Read(0); if ((CAL100msec < (0x9E58 - 1000)) || (CAL100msec > (0x9E58 + 1000))) CAL100msec = 0x9E58; // CAL1sec = Eeprom_Read(3); CAL1sec = CAL1sec << 8; CAL1sec = CAL1sec | Eeprom_Read(2); if ((CAL1sec < (0x2F70 - 1000)) || (CAL1sec > (0x2F70 + 1000))) CAL1sec = 0x2F70; // 変数の初期化 prescaler = 1; gateTime = GATETIME_1SEC; // Soft_Uart_Init(GPIO, 3, 5, 9600, 0); Soft_Uart_Write_String("Frequency Counter (S) V2\r\n"); // while (1) { // 測定 freq = FreqMeasurement(gateTime); // 補正 freq *= prescaler * gateTime; // プリスケーラの切り替え if (SW2 == 1) { OPTION_REG.PSA = 1; OPTION_REG.PS1 = 0; prescaler = 1; } else { OPTION_REG.PSA = 0; OPTION_REG.PS1 = 1; prescaler = 8; } // ゲートタイムの切り替え if (SW3 == 1) { gateTime = GATETIME_1SEC; } else { gateTime = GATETIME_100MSEC; } // 表示レンジの切り替え&表示 if (SW4 == 1) { LongToStr(freq, buf); Soft_Uart_Write_String(buf); Soft_Uart_Write_String("Hz"); } else { temp = freq / 1000; if ((freq - (temp * 1000)) > 500) { temp++; } LongToStr(temp, buf); Soft_Uart_Write_String(buf); Soft_Uart_Write_String("kHz"); } // 校正 if (SW1 == 0) { if ((freq > 1000000) && (gateTime == GATETIME_100MSEC)) CAL100msec++; if ((freq < 1000000) && (gateTime == GATETIME_100MSEC)) CAL100msec--; if ((freq > 1000000) && (gateTime == GATETIME_1SEC)) CAL1sec++; if ((freq < 1000000) && (gateTime == GATETIME_1SEC)) CAL1sec--; // 校正値の保存 Eeprom_Write(0, (CAL100msec & 0xFF)); Delay_ms(20); Eeprom_Write(1, ((CAL100msec >> 8) & 0xFF)); Delay_ms(20); Eeprom_Write(2, (CAL1sec & 0xFF)); Delay_ms(20); Eeprom_Write(3, ((CAL1sec >> 8) & 0xFF)); Delay_ms(20); // 校正値の表示 if (gateTime == GATETIME_100MSEC) LongToStr(CAL100msec, buf); else LongToStr(CAL1sec, buf); Soft_Uart_Write_String(buf); Soft_Uart_Write_String("\r\n"); } else { Soft_Uart_Write_String("\r\n"); } } } //**********************************************************************