PICマイコンを使って測定ツールを作ってみよう(2) ―― クロック周波数やモータの回転数を測れるカウンタを作る(後編)
tag: 組み込み 電子回路 ディジタル・デザイン
エレキ系DIY 2009年9月28日
●カウンタの設定を行う
さて問題のカウンタの設定ですが,リスト3でタイマ0とタイマ1の設定を行っています.タイマを動作させるビットをONにして,プリスケーラの比率を設定しています.タイマ0とタイマ1の最大比率は違っていて,タイマ0は1:256まであり,タイマ1は1:8までしかありません.
リスト3 タイマ初期設定の記述(user.cの101~134行目)
void UserInit(void) { // InitializeUSART(); // InitializeI2C(); TRISC = 0x41; // ProtC RC0:SW2 GREEN,RC1:BLUE LED, RC2:YELLOW LED, // RC6:RX,RC7:TX/SDO PORTC|= 0x0F; // PortC TRISA = 0x3E; // PORTA RA0:ANALOG CURRENT,RA1:ANALOG VOLT, // RA2:SW4 YELLOW,RA3:SW1 BLUE, RA4:CLOCK IN/TXRX,RA5:#SS PORTA = 0x01; // PortA TRISB = 0x00; // PORTB RB4-RB7:LCD DB4-DB7, RB2:LCD E, // RB3:LCD RS 、RB0:SDA/SDI,RB1:SCL/SCK PORTB|= 0xF3; // PortB T0CON = 0xB7; // タイマ0の設定, 16ビットモード, 割込み使用 //外部クロック、1:256プリスケーラ T1CON = 0xB1; //タイマ1の設定,16ビットモード、割込み使用 //内部クロック、1:8プリスケーラ CCP1CON = 0; //***** 優先順位割込み使用宣言 RCONbits.IPEN=1; IPR1bits.TMR1IP=1; //***** 低レベル使用周辺の定義 INTCON2bits.TMR0IP = 0; //***** 割込み許可 INTCONbits.GIEH=1; // 高レベル許可 INTCONbits.GIEL=1; // 低レベル許可 INTCONbits.T0IE = 1; // タイマ0割込み許可 PIE1bits.TMR1IE = 1; // タイマ1割込み許可 UIE = 0x7F; // USB割込み許可 |
前述したように,比率を落とせば精度は高くなりますが,PIC18F2550のデータシートによるとタイマ0で測定できる最大クロック周期は20nsです.周波数にすると50MHzです.プリスケーラなしの1:1にすると,これが11MHzまで落ちます.最低比率の1:2にしても,16MHz程度となります.
これは,「プリスケーラは基本クロックと非同期で動作しているが,タイマ・レジスタは基本クロックに同期して動作しているため」と推測します.PIC18F2550のデータシートでタイマのブロック図を見てみると,タイマ・レジスタの前にプリスケーラ出力の同期化処理のブロックがあります.ここで基本サイクルの2サイクル分遅延すると記述されています.基本サイクルは基本クロックの4倍ですので,周期でいうと約80nsに相当します.データシートの式に当てはめると,上記の値になります.
このカウンタ回路ではkHz単位の周波数が見れればいいので,1:256と1:8の組み合わせで問題ありません.これ以上の精度が必要な場合は,測定時間を100msではなく1秒かそれ以上にすれば,より多くのけた数が得られます.ただし,表示更新速度は落ちます.両タイマともプリスケーラなしの1:1にすれば,更新速度が速いまま,けた数も増えます.ただし,もともとPLLのクロックなので,表示の下のけたでは値が変動し,正確な値のダイナミック表示は無理です.1回1回動作させて測定する方法をとる必要があります.
さらに精度の高い測定が必要であれば,USBによるデータ転送はあきらめて,PLLの使用をやめることです.こうすると,原発振の水晶発振子の精度で測定できます.ここでの目標は簡易的な測定なので,そこまではやりません.
これでカウンタを設定できましたが,実際のカウントはどのように実現するのでしょう.それはカウント値の更新と表示になります.