1

最初は、実行モード中に Timer0 が正常に動作していました。唯一の問題は、デバイスがスリープ モードになると、タイマー 0 が起動するまでカウントアップを停止することです。データシートでは、Timer1 を使用してスリープ モード中に時間を監視できるようになっています。timer0 の既存のコードを timer1 の新しい構成に変更しました。他のコードはほとんど同じです。ただし、timer1 はまったくカウントアップしないため、timer1 と timer0 の違いを見逃している可能性があります。私が使用している PIC は、MPLAB C18 を搭載したPIC18F87J11です。

関連すると思われるコードを共有し、要求に応じて必要に応じてさらに追加します。

Timer0スニペット コード (ヘッダー ファイルから)

#define TMR_IF          INTCONbits.TMR0IF
#define TMR_IE          INTCONbits.TMR0IE
#define TMR_IP          INTCON2bits.TMR0IP
#define TMR_ON          T0CONbits.TMR0ON
#define TMR_CON         T0CON
#define TMR_L           TMR0L
#define TMR_H           TMR0H 

Timer0 (C ファイルから)

TMR_CON = 0b00000000 | CLOCK_DIVIDER_SETTING;
TMR_IP = 1;
TMR_IF = 0;
TMR_IE = 1;
TMR_ON = 1;

Timer0 (時間をインクリメントする場所)

if(TMR_IF)
        {
        printf("\r\n Passed here");
        timer_counter_high++; 
        }

出力:ここに渡されます


Timer1スニペット コード (ヘッダー ファイルから)

#define TMR_IF          PIR1bits.TMR1IF
#define TMR_IE          PIE1bits.TMR1IE
#define TMR_IP          IPR1bits.TMR1IP
#define TMR_ON          T1CONbits.TMR1ON
#define TMR_CON         T1CON
#define TMR_L           TMR1L
#define TMR_H           TMR1H

Timer1 (C ファイルから)

TMR_CON = 0b11101101 | CLOCK_DIVIDER_SETTING;
TMR_IP = 1;
TMR_IF = 0;
TMR_IE = 1;
TMR_ON = 1;

Timer1 (時間をインクリメントする場所)

   if(TMR_IF)
        {
        printf("\r\n Passed here");
        timer_counter_high++; 
        }
        else
        {
        printf("\r\n Did not come through");
        }

出力:通らなかった

編集: 要求に応じて CLOCK_DIVIDER_SETTING コードを追加しました。これは timer0 と timer1 に使用されています。

#elif(CLOCK_FREQ <= 8000000)
        #define CLOCK_DIVIDER 32
        #define CLOCK_DIVIDER_SETTING 0x04
        #define SYMBOL_TO_TICK_RATE 8000000

デバイスをスリープ モードにして、その状態で timer1 をテストしていません。まず、run モードで timer1 がカウントアップしない理由を突き止めなければなりません。私の問題に関連するヘルプやアイデアをいただければ幸いです。ありがとうございます。

編集 2:回答してもらいたい質問

Q1 : Timer1 は、timer0 と同じように内部オシレータで引き続き使用できますか?

Q2 : T1CON の正しい CLOCK_DIVIDER_SETTING をどのように計算しますか? (T1SYNC とプリスケーラが設定されている場合、必要ですか?)

4

1 に答える 1

2

PIC18F87J11 FAMILY データシートによると、Timer1 オシレータから派生した Timer1 クロ​​ックを設定する場合 (T1CON レジスタの T1RUN ビットを設定して行う)、T1OSO および T1OSI ピンに外部クリスタルを追加する必要があります。

また、CLOCK_DIVIDER_SETTING を T0CON レジスタに割り当てるとクロック プリスケーラが正しく設定されますが、同じ CLOCK_DIVIDER_SETTING を T1CON レジスタに割り当てるのは誤りであることに注意してください。これは、異なるビット位置 (この場合、既に設定されているビット T1SYNC を効果的に設定している) と、プリスケーラ。

また、タイマーを有効にする前に、レジスタ TMR1H、TMR1L、TMR0L、および TMR0H をコードのどこかに設定してください。

EDIT追加の質問への回答を追加しました。

1:はい。Timer1 には、外部オシレータと内部クロック (Fosc/4) の 2 つのクロック ソースがあります。内部クロックを有効にするには、T1CON レジスタのビット TMR1CS をクリアする必要があります。

スリープ中は、Timer1 オシレータと INTRC (Timer1 では使用できない 31 kHz クロック) を除くすべてのクロックが無効になるため、Timer1 が外部オシレータによってクロックされる場合にのみ、スリープ中に Timer1 で時間を測定できることに注意してください。

2: T1CKPS ビットは T1CON レジスタのビット 4 と 5 であるため、クロック分周器の設定を 4 ビットシフトするだけで問題ありません。Timer1 クロ​​ック プリスケーラは 2 ビット幅しかなく、クロックを最大 8 倍に分周できることに注意してください。

内部クロックを使用する場合、T1SYNC ビットは無視されます。スリープ モード中に Timer1 で外部オシレータを使用する場合は、T1SYNC を設定して外部クロック入力の同期を無効にする必要があります (スリープ中は、同期する内部クロックがなく、Timer1 がカウントしないため、外部クロックを同期できません)。

Timer1 の構成は次のようになります。

#define CLOCK_DIVIDER_SETTING_T1 0x03 // divide clock by 8 (T1_clock/8)

// RD16 cleared
// T1OSCEN set - Timer1 oscillator is enabled
// T1SYNC set - Does not synchronize external clock input
// TMR1CS set - External clock from the RC0/T1OSO/T13CKI pin (on the rising edge)
// TMR1ON cleared - wait with enabling Timer1 until everything is configured
TMR_CON = 0b00001110 | (CLOCK_DIVIDER_SETTING_T1<<4);
TMR_IP = 1;
TMR_IF = 0;
TMR_IE = 1;
TMR_ON = 1;

内部クロックを使用する場合は、T1_clock = Fosc/4 です。

内部発振器をシステム クロックとして使用する場合、OSCCON レジスタの IRCF ビットに書き込むことでシステム クロックのポストスケーラを変更できますが、これはマイクロコントローラ全体の速度に影響します。

デフォルト設定は 4 MHz であるため、T1_clock は 1 MHz になり、T1 プリスケーラーの後は 125 kHz になります。

于 2013-07-19T08:45:03.483 に答える