15

アプリケーションの目盛りを表示するカウンターを処理する必要があります。カウンターは32ビットなので、ラップするときの対処方法を知っておく必要があります。例えば:

aを返す関数と(timestamp + shifttime)、時間が経過したかどうかに応じて1または0を返す関数がありますが、カウンターがどのようにラップする可能性がありますか?これに対処しますか?


すべての回答者に感謝します。この編集でさらに詳しく説明します。

STM32Cortex-M3を使用しています。RTCカウンターを使用して、アプリケーションが特定の間隔で発生する必要のあるタスクをスケジュールするための目盛りとして使用したいと思います。RTCはオーバーフロー割り込みを生成できるため、割り込みの検出に問題はありません。私が抱えている主な問題(または少なくとも私が問題だと思う)は、特定のタスクがIEを取得するとき(timestamp+shift)です

int main( void )
{
    FlashLedTimeStamp = ReturnCounter( 20 );  // currentcounter value + a shift of 20
    StatusLedTimeStamp = ReturnCounter( 3 );  // currentcounter value + a shift of 3

// then later on ....
while(1)
{
    /* other tasks could go here */

    if( HasTimeElapsed( FlashLedTimeStamp ) )
    {
       /* do something and get another timestamp value */
       FlashLedTimeStamp = ReturnCounter( 20 );  // currentcounter value + a shift of 20
    }
    
    if( HasTimeElapsed( StatusLedTimeStamp ) )
    {
       /* do something and get another timestamp value */
       FlashLedTimeStamp = StatusLedTimeStamp( 3 );  // currentcounter value + a shift of 3
    }
}   
}

計算を簡単にするために、私のRTCカウンターの長さがわずか8ビットであると仮定しましょう。

タイムスタンプを取得したときに現在のカウンターが250になっている場合、それはそれを意味しFlashLedTimeStamp = 14、それが期限切れになっているStatusLedTimeStamp = 253ことを確認するにはどうすればよいですか?FlashLedTimeStamp

現在のカウンターが何であるか、特定のタイムスタンプが期限切れになっているかどうかを確認するために、必ずしも常にチェックするわけではないことに注意してください。これにより、私が抱えている問題が明確になることを願っています。

4

11 に答える 11

37

開始カウントと終了カウントの差が232未満であり、カウント値がラップポイントにまたがっていても、符号なし32ビット演算が実行される限り問題はありません。(符号付き演算を使用する場合、スパンは2 32/2未満である必要があります)

例えば:

Start count: 0xfffffff
End Count:   0x00000002 (incremented through 0,1,2 - i.e. three counts)

End - Start == 0x00000002 - 0xfffffff == 0x00000003

したがって、カウンタが組み込み整数型のビット幅であり、その型が使用されている限り、正しい答えが得られます。おそらくカウンタレジスタが組み込み整数型の幅ではない場合、上位の「オーバーフロー」ビットをマスクすることで同じ効果を得ることができます。

他の理由でより大きなカウントが必要な場合、または連続するタイムスタンプ間の差が大きすぎる場合は、下位カウンターがラップするときにインクリメントされる別の整数を使用できます。この整数は大きい方の整数の上位ビットを形成するため、2番目の整数のLSBはこの大きい方の整数の33番目のビットになります。

于 2010-06-22T22:24:40.267 に答える
14

2つのタイムスタンプの読み取り値を取得し、最初の読み取り値が2番目の読み取り値よりも大きい場合、カウンターはラップされています。これが、ラッピングカウンターを検出するための基本的な方法です。

ただし、これは、カウンターが複数回ラップされたかどうか、またはカウンターがラップされて最初の読み取り値よりも大きい場合は検出されません。これは組み込みシステムであり、説明によって「カウンター」が時計のように聞こえると言ったので、時計がゼロになるたびに割り込みを発生させることができるかどうかを確認してください(時計がリセットされるたびに割り込みが発生するようにします)。この割り込みが発生したら、別のカウンターをインクリメントします。これにより、時計の精度が効果的に向上し、問題を発生させることなくカウンターをラップできるようになります。

于 2010-06-22T17:50:32.560 に答える
5

符号なし減算の結果を符号付きにキャストし、ゼロと比較します。十分な頻度でチェックするときにオーバーフローを処理する必要があります(タイムアウトはタイマーの範囲の半分未満です)。

uint32_t timer( void);             // Returns the current time value
uint32_t timeout;

timeout = timer() + offset;

// wait until timer() reaches or exceeds timeout value
while ((int32_t)(timeout - timer()) > 0);
于 2010-06-22T22:56:40.423 に答える
5

符号なし変数を使用してカウンターとタイマーの有効期限を保存する場合は、次のテストを使用できます。

if (current_time - expiry_time < 0x80000000UL)
    /* timer has expired */

これは、0x80000000ティックごとに少なくとも1回有効期限をテストし、最長のタイマーが0x80000000ティック未満で有効期限が切れるように設定されていることを前提としています。

于 2010-06-23T00:23:14.730 に答える
2

質問は少し曖昧です。1つの可能性は、時間が経過したことに最初に気付いたときにフラグを設定することです。確実な方法は、最初のカウンターがオーバーフローしたときにインクリメントされる2番目のカウンターを追加することです。これにより、オーバーフローしない64ビットカウンターが実際に作成されます。

于 2010-06-22T17:44:19.343 に答える
1

カウンターがカウントダウンすると仮定しましょう(ロジックのゲートを節約するために多くのカウントダウンがあります)。

最初に2^32ティックに到達するのにかかる時間を知る必要があり、それを十分にオーバーサンプリングしていることを確認する必要があります。

2つのイベント間の期間を知りたい場合は、開始と終了と言います

start=タイマーの前回の読み取り=ロールオーバーの開始=0

物事が起こるのを待っている間

nowtime =読み取りタイマーif(nowtime> lasttime)rollover + = 1(これはダウンカウンターです)lasttime = nowtime

イベントが発生します:終了=タイマーの読み取り

合計時間=開始-終了(これはダウンカウンターであり、この計算はロールオーバーしても機能することに注意してください)

合計時間=合計時間/ティックから秒、分、合計時間まで取得するスケーリング係数+=ロールオーバー*秒/分/2^32カウントごとに何でも

あなたがアップカウンターを持っているなら、今時間

イベントが2^32カウント以内に発生することを保証できる場合は、前回のロールオーバーを実行する必要はありません。開始と終了のみが必要であり、合計ティック数=開始-終了は、カウンターが0x00000000から開始と終了の間の0xFFFFFFFF。

于 2010-06-23T17:46:28.073 に答える
1

これを行う最も簡単な方法は、ロールオーバーを明示的にカウントする「エポックカウンター」を作成することです。(例:秒0..59をカウントするハードウェアカウンターがあります。エポックカウンターは、秒カウンターがロールオーバーしたことに気付くたびに増分することにより、分をカウントします。)

次に、future_scheduler関数は現在のエポックと時刻を読み取り、イベントの新しいエポックと時刻を計算します。

または、パントして、タイマーティックごとにイベントスケジュールをゼロまでカウントするタイミング関数を作成することもできます。

于 2010-06-22T17:44:56.743 に答える
1

可能性の1つは、両方の変数を64ビット長にキャストしてから合計することです。その後、最大32ビット値と比較して、ラップされているかどうかを確認します。

于 2010-06-22T17:45:46.213 に答える
0

符号なし型を扱っていると仮定すると、ラッピングを非常に簡単にチェックできます-

if (timestamp + shifftime < timestamp) 
    it_wrapped();
于 2010-06-22T17:43:51.210 に答える
0

組み込みの場合、CPUオーバーフロービットにアクセスできる可能性があります。これは、追加がレジスターをオーバーフローしたときに設定されます。AddCarryチェーンを追加するのに便利です。

于 2010-06-22T17:50:49.490 に答える
0

これを行う最も簡単な方法の1つは、別のカウンター(ラップカウンターと呼び、これをタイマーモジュールの静的グローバルにする)を用意し、元の32ビットカウンターがラップされるたびにカウントアップすることだと思います。

カウンターが刻々と過ぎていく機能では、このカウンターが最大数に達するたびに、ラップカウンターが増加します。そのため、タイマーが経過したかどうかを返す関数を読み取るときは、ラップカウンターも読み取り、ラップした回数を確認します。重要なことは、これも行うことです。ラップカウンターを読み取るたびに、次の読み取りのためにそれをクリアする必要があります。

于 2010-06-23T00:32:00.210 に答える