1

C8051F020 MCU のタイマーを作成する方法を見つけようとしています。init_Timer2()次のコードは、次の式で渡された値を使用します。

65535-(0.1 / (12/2000000)=48868.

タイマーが実行されるたびにカウントするように設定し、10 カウントごとに 1 秒カウントします。これは上記の式に基づいています。48868 を渡すとinit_Timer2、0.1 秒の遅延が発生します。1 秒あたり 10 個かかることになります。ただし、タイマーをテストすると、少し速いです。10 秒でタイマーは 11 秒を報告し、20 秒でタイマーは 22 秒を報告します。できる限り完璧な秒に近づけたいと思っています。

これが私のコードです:

#include <compiler_defs.h>
#include <C8051F020_defs.h>

void init_Clock(void);
void init_Watchdog(void);
void init_Ports(void);
void init_Timer2(unsigned int counts);
void start_Timer2(void);
void timer2_ISR(void);

unsigned int timer2_Count;
unsigned int seconds;
unsigned int minutes;

int main(void)
{
    init_Clock();
    init_Watchdog();
    init_Ports();
    start_Timer2();

    P5 &= 0xFF;

    while (1);
}

//=============================================================
//Functions
//=============================================================
void init_Clock(void)
{
    OSCICN = 0x04;  //2Mhz
    //OSCICN = 0x07;    //16Mhz
}

void init_Watchdog(void)
{
    //Disable watchdog timer
    WDTCN = 0xDE;
    WDTCN = 0xAD;
}

void init_Ports(void)
{
    XBR0    = 0x00;
    XBR1    = 0x00;
    XBR2    = 0x40;

    P0      = 0x00;
    P0MDOUT = 0x00;
    P5      = 0x00; //Set P5 to 1111
    P74OUT  = 0x08; //Set P5 4 - 7 (LEDs) to push pull (Output)
}

void init_Timer2(unsigned int counts)
{
    CKCON = 0x00;   //Set all timers to system clock divided by 12

    T2CON = 0x00;   //Set timer 2 to timer mode

    RCAP2 = counts; 

    T2 = 0xFFFF;    //655535

    IE |= 0x20;     //Enable timer 2

    T2CON |= 0x04;  //Start timer 2
}

void start_Timer2(void)
{
    EA = 0;

    init_Timer2(48868);

    EA = 1;
}

void timer2_ISR(void) interrupt 5
{    
    T2CON &= ~(0x80);

        P5 ^= 0xF0;

        timer2_Count++;

        if(timer2_Count % 10 == 0)
        {
            seconds++;
        }

        if(seconds % 60 == 0  && seconds != 0)
        {
            minutes++;
        }
}
4

4 に答える 4

1

問題の原因となっているコードはおそらく何もありません。

内部発振器が正確に 2Mhz であると想定しています。ほとんどの場合、あなたのマイクロはそこにありません。データシートの公差を見ると、2Mhz に設定すると、仕様上の最小値は 1.5Mhz、最大値は 2.4Mhz であることがわかります。したがって、意図した頻度の 75% から 120% の間のどこでも実行できます。(これは通常、温度によっても変化します...)

したがって、カウンターに表示されている 10% のエラーは、単なるハードウェアである可能性があります。

コードをフラッシュするための 2 つ目のマイクロはありますか? OSC は異なる周波数で実行される場合があり、時間の感覚が異なる場合があります。

補足:変更をお勧めします

if(seconds % 60 == 0  && seconds != 0)
{
    minutes++;
}

if(seconds >= 60)
{
    seconds = 0;
    minutes++;
}

等値チェックは、モジュロよりもサイクルのコストが低くseconds、報告された秒数をクリアしないと、最初の 1 分以降は不正確になります。

于 2012-10-17T13:28:45.740 に答える
1

この特定のマイクロコントローラーのデータシートを開き、timetick 割り込みを探します。n ミリ秒ごとに割り込みを発行する方法を調べます。通常、これを計算する式はクロック速度に依存し、特定のマイクロコントローラーのデータシート/プログラミング ガイドに記載されていることがよくあります。

于 2012-10-17T07:41:05.057 に答える
0

この質問に答えたことを、私は完全に信用することはできません。全員が貢献しました。22.1184Mhz の外部クロックを使用することになりました。次のコード スニペットは、機能するように変更された元のポスト コードのセクションです。

void init_Clock(void)
{
    OSCXCN = 0x67;  //External 22.1184Mhz

    while ( !(OSCXCN & 0x80) );

    OSCICN = 0x88;
}

void start_Timer2(void)
{
    EA = 0;

    //External clock
    init_Timer2(47103);

    EA = 1;
}

私のテストから、これは非常に正確です。

于 2012-10-17T21:00:04.660 に答える
0

内部発振器を使用しています。これは非常に不正確で、正確には 2 MHz ではありません。

于 2012-10-17T16:56:58.320 に答える