|
PIC16F1827を使って、周波数カウンタを作ってみました。
これまで、PIC16F88,PIC16F628Aなどで製作した「電子工作etc」というサイトで紹介された「周波数カウンタV7」と基本的には同じアルゴリズムです。
残念ながら「電子工作etc」というサイトは既に見えなくなっているようです。
PIC 1個で、どのようにして周波数カウンタを作るかを簡単に説明します。
周波数カウンタを作るには、周波数を測定するカウンタとカウント時間(普通は1秒)を発生するタイムベースが必要です。
PICは、内部に複数のタイマー(カウンタ)を持っています。そのうち16bitタイマーであるTimer1(TMR1)を周波数を測定するカウンタに使い、8bitタイマーTimer2(TMR2)を使って1秒を発生させます。
TMR2を利用したタイムベースからの1秒の合図で、TMR1へのゲートを開けたり閉めたりして、周波数をカウントします。
詳細は、JH7UBCホームページのここを見てください。
回路図です。
入力信号は、2SC1815GRの簡単なアンプを通して、T1CKI(RB6)に加えます。 クロックは、正確に測定するために20MHzのクリスタルオシレータを使い、外部クロック入力CLKIN(RA7)に入れます。
周波数表示は、I2Cアダプタ付きのLCD1602を使いました。
動作確認のために、TMR1のゲートが開いている間点灯するLEDをつけました。
ブレッドボードです。自作SGからの1MHz(1000000Hz)の信号を測定しています。
プログラムです。 ------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <xc.h> // CONFIG1
#pragma config FOSC = ECH //外部クロック CLKIN (4-32MHz) #pragma config WDTE = OFF #pragma config PWRTE = ON #pragma config MCLRE = OFF #pragma config CP = OFF #pragma config CPD = OFF #pragma config BOREN = ON #pragma config CLKOUTEN = OFF #pragma config IESO = OFF #pragma config FCMEN = OFF // CONFIG2
#pragma config WRT = OFF #pragma config PLLEN = OFF #pragma config STVREN = ON #pragma config BORV = HI #pragma config LVP = OFF #define _XTAL_FREQ 20000000 //クロック20MHz
#define LED RA4 //LCD関係定義
#define LCD_EN 0b00000100 //Enable #define LCD_BL 0b00001000 //Back Light #define LCD_CMD 0x00 #define LCD_CHR 0x01 #define LCD_LINE1 0x80 #define LCD_LINE2 0xC0 #define LCD_addr 0x4E //0x27<<1 /* I2C 初期化*/
void I2C_init(){ SSP1CON1 = 0x28; //SSPEN = 1,I2C Master Mode SSP1STATbits.SMP = 1; //標準速度モード(100KHz) SSP1ADD = 0x31; //Fosc/(4*Clock)-1 Clock=100kHz,Fosc=20MHz } /* スタートコンディション */
void I2C_start(){ SSP1CON2bits.SEN = 1; while(SSP1CON2bits.SEN); } /* ストップコンディション */
void I2C_stop(){ SSP1IF = 0; SSP1CON2bits.PEN = 1; while(SSP1CON2bits.PEN); SSP1IF = 0; } /* I2Cに1byte送信 */
void I2C_write(unsigned char dat){ SSP1IF = 0; SSP1BUF = dat; while(!SSP1IF); } void Write_data(unsigned char data){
I2C_start(); I2C_write(LCD_addr); I2C_write(data | LCD_EN | LCD_BL); I2C_write(data | LCD_BL); I2C_stop(); __delay_us(100); } void LCD_write(unsigned char bits,unsigned char mode){
//send High 4bits Write_data((bits & 0xF0) | mode); //send Low 4bits Write_data(((bits << 4) & 0xF0) | mode); } void LCD_init(){ LCD_write(0x33,LCD_CMD); LCD_write(0x32,LCD_CMD); LCD_write(0x06,LCD_CMD); LCD_write(0x0C,LCD_CMD); LCD_write(0x28,LCD_CMD); LCD_write(0x01,LCD_CMD); __delay_ms(1); } void LCD_clear(){
LCD_write(0x01,LCD_CMD); __delay_ms(1); } void LCD_home(){
LCD_write(0x02,LCD_CMD); __delay_ms(1); } void LCD_cursor(unsigned char x,unsigned char y){
if (y == 0){ LCD_write(LCD_LINE1+x,LCD_CMD); } if (y == 1){ LCD_write(LCD_LINE2+x,LCD_CMD); } } void putch(unsigned char ch){
LCD_write(ch,LCD_CHR); } static unsigned int MeassuremmentCnt;
/*TMR2のオーバーフロー割り込み*/
void interrupt isr(){ TMR2IF = 0;//TMR2割り込みフラッグクリア MeassuremmentCnt --; if (MeassuremmentCnt == 0){ TMR1ON = 0;//ゲートを閉める。 TMR2ON = 0;//TMR2を停止する。 } } /*周波数測定*/
unsigned long FreqMeassurement(){ static unsigned long freq; /*TIMERの初期化*/ TMR1IF = 0; //TMR1割り込みフラッグクリア TMR1L = 0; //TMR1クリア TMR1H = 0; /*TMR2の初期化*/ TMR2IF = 0; //TMR2割り込みフラッグクリア MeassuremmentCnt = 1221; TMR2 = 0x4C; /*counter 初期化*/ freq = 0; /*割り込み許可*/ PEIE = 1; GIE = 1; //count start TMR2ON = 1; /*gate time調整 NOP 25*/ NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); /*ゲートを開ける*/ TMR1ON = 1; while(TMR2ON){ if(TMR1IF == 1){ TMR1IF = 0; freq ++; } } if(TMR1IF == 1){ TMR1IF = 0; freq ++; } /*換算*/ freq = freq * 65536; freq = freq + ((unsigned)TMR1H * 256) + (unsigned)TMR1L; return(freq); } void main() { ANSELA = 0b00000000 ; // AN0-AN4は使用しない ANSELB = 0b00000000 ; // AN5-AN11は使用しない TRISA = 0b10000000 ; // RA7は入力 他は出力(RA5は入力) TRISB = 0b01010010 ; // RB1(SDA),RB4(SDA),RB6は入力他は出力 PORTA = 0b00000000 ; // PORTA初期化 PORTB = 0b00000000 ; // PORTB初期化 I2C_init(); LCD_init(); LCD_cursor(12,0); printf("Hz"); /*TMR2の設定*/ TMR2IE = 1; //TMR2割り込み許可 TMR2IF = 0; //TMR2割り込みフラッグクリア T2OUTPS0 = 0; //TMR2 output poststscaler 1:1 T2OUTPS1 = 0; T2OUTPS2 = 0; T2OUTPS3 = 0; TMR2ON = 0; //TMR2 off T2CKPS0 = 0; //TMR2 prescaler 1:16 T2CKPS1 = 1; TMR2 = 0; //TMR2 clear /*TMR1の設定*/ TMR1IE = 0; //TMR1割り込み禁止 TMR1IF = 0; //TMR1割り込みフラッグクリア T1CKPS0 = 0; //TMR1 prescaler 1:1 T1CKPS1 = 0; T1OSCEN = 0; //TMR1 Clock source = T1CKI TMR1CS1 = 1; TMR1CS0 = 0; nT1SYNC = 1; TMR1ON = 0; //TMR1 stop TMR1L = 0; //TMR1 clear TMR1H = 0; while(1){ /*周波数の測定*/ LED = 1;//RA4 LED ON unsigned long frequency = FreqMeassurement(); LED = 0;//RA4 LED OFF LCD_cursor(2,0); printf("%9ld",frequency); __delay_ms(500); } }
|

- >
- コンピュータとインターネット
- >
- コンピュータ
- >
- その他コンピュータ



