2017-09-26 20 views
0

タイマ割り込み(精度時間付き)でADチャネルを読み取る必要があるコードがあります。中断PIC CCS

私はちょうどADを読んでも大丈夫です。しかし、私は、デジタルフィルタを使用する必要がある、と私はちょうど乗算を置けば内部警告持っ中断:

これはokです:

#int_RTCC 
void RTCC_isr(void) 
{ 
    set_adc_channel(0);  
    delay_us(40); 
    unsigned int16 aD = read_adc(); 
} 

をしかし、この取得警告:

#int_RTCC 
void RTCC_isr(void) 
{ 
    set_adc_channel(0);  
    delay_us(40); 
    unsigned int16 aD = read_adc(); 
    aDfilter = aDfilter * 8 + aD * 2; 
} 

(MUL3232)

私は精度が必要なので、私はタイマーを無効にしたくありません。これをどうすれば解決できますか?

+0

警告は何ですか?おそらく次のような計算をする必要があります: 'aDfilter =(float)aDfilter * 0.8f +(float)aD * 0.2f;' Btw、割り込みを無効にしてリエントラント*を防止したいですか?理にかなっていないか、多分あなたは別の言葉が必要です*再帰を防ぐ*? – tilz0R

+0

ソーリー、正しいです:aDfilter = aDfilter * 8 + aD * 2 フロートが必要ありません。 問題は、割り込みの内側と外側の乗算を使用していることです。これを行う方法はありますか? –

+0

基本的にはすべての問題がこの点で発生します.PICはPCではありません。 – Lundin

答えて

0

問題1:PICは通常8ビットCPUを意味します。 8ビットCPUは、16ビット値をアトミックに読み取ることができません(aDfilter)。メインプログラムが値の半分しか読み込んでいない間にRTC割り込みがトリガされた場合、プログラムはクラッシュして焼損します。コンパイラーがあなたに伝えている、再入門の手段が必要です。

問題2:通常、PICは非常に遅いCPUを意味し、大きな割り込み待ち時間があります。したがって、ISR内で算術演算を行うべきではありません。これには浮動小数点計算が含まれます。整数の乗算は、十分に悪い場合もあります。

問題3:通常、PICはFPUのないひどい低速CPUを意味します。つまり、浮動小数点数を使用しないでください。フロートをサポートするソフトウェアライブラリを呼び出すことになりますが、それは非常に遅いです。表示されているコードには、このプログラムで浮動小数点を使用する必要があることを示していません。

解決方法:整数を使用してください。同期化手段を用いて再エンティティを実装する。割り込みが常に割り込みをブロックするシングルコアマイクロコントローラでは、これはかなり簡単です。simple example。次に、デジタルフィルター計算を呼び出し側アプリケーションに委託します。利用可能な新しいデータがあることを伝えるフラグを追加するだけです。

+1

'浮動小数点サポート付きのソフトウェアライブラリを呼び出すことになりますが、これは非常に遅いです。さらに、割り込みの外側でFPを使用する場合、再入可能なFPライブラリが必要です(PICを使用しない場合十分な問題)。 –

+0

悪意のある - FPライブラリは、再入可能であれば、スタックを使用します。つまり、中断されたものは、それをサポートするのに十分なスタックを持っているか、別の割り込みスタックにスワップしている必要があります。すべての使用時に長時間の 'FPinit()'関数を呼び出す必要があるかもしれません。 ( –

+0

@MartinJamesそして... PIC ...固定されたスタック深度を持つ1970年代のアーキテクチャを意味します。フロートライブラリはどれだけ深い呼び出しを使用するのですか?ISRの中でそれを持つのは非常に面白いです。 – Lundin

0

あなたは、何かシフトすることにより、INT32乗算の使用を避けることができます。

#int_RTCC 
void RTCC_isr(void) 
{ 
    set_adc_channel(0);  
    delay_us(40); 
    unsigned int16 aD = read_adc(); 
    aDfilter = aDfilter << 3 + aD * 2; 
} 
0

を(メッセージ)(MUL3232 @)再入を防ぐために、通話中に割り込み禁止
私はタイマーを無効にしたくありません、私は精度が必要なので。

これは間違いです。

コードは、良いデザインが起きることを避けることができるという珍しい状況から自分自身を保護するだけです。タイマ割り込みサービスルーチン(ISR)を実行している場合


、別のタイミング割り込みの再entrantcyは、通常は2例のみで起こる:

  1. タイマーISRの頻度が高すぎます。これは、1タイマーISRを処理するのに時間がかかることを意味します。これが完了する前にもう1つのISRが発生しています。これは良いデザインではありません。解決するには、タイマーの周波数があまり高くないことを確認してください。

  2. 遅延。時間がかかっている他のISRを処理中にタイマーISRが発生し、このタイマーISRコールがブロックされました。このISRが実行されるまでに、別のタイマ割り込みが発生しました。解決するには、すべてのISRが一緒にタイマー期間より長くかからないようにします。

第2タイマ割り込みは発生せず、一時的に乗算を行う時間を無効にしても、タイマ割り込みの発生はブロックされません。


または@MUL3232コールを必要とする単純化コードが

aDfilter * 8数学を締結弱い最適化又はの不必要な使用を意味します。符号なし演算を使用してコンパイラのコードを簡単にします。

// some_signed_32_bit_type aDfilter 
uint32_t aDfilter; 

// and if that is not enough change code 
// aDfilter = aDfilter * 8 + aD * 2; 
aDfilter = (aDfilter << 3) + aD * 2; 

潜在的なパフォーマンスの改善。全体的なデザインによっては、delay_us(40);を削除する必要があります。 1チャンネルのみを使用する場合は、さまざまな要件に応じて以下のことが可能です。

#int_RTCC 
void RTCC_isr(void) { 
    // delay_us(40); // not needed is timer period >> 40us 
    unsigned int16 aD = read_adc(); 
    set_adc_channel(0); // select channel now (also at initialization) 
    aDfilter = aDfilter * 8 + aD * 2; 
} 

潜在的なバグを修正しました。 read_adc()が最上位桁が設定されている(例えば、10ビット変換が6つ左にシフトされた)モードであり、コンパイラが16ビットのint/unsignedを有する場合、aD*2がオーバーフローする。その場合は次のようにしてください:

uint32_t aDfilter; 
... 
aDfilter = aDfilter*8 + (uint32_t)read_adc()*2;