最初の質問
マイクロコントローラでの割り込みの処理について、一般的な質問があります。私はMSP430を使用していますが、質問は他のuCにも当てはまると思います。コードに沿って頻繁に割り込みを有効/無効にするのが良い方法かどうか知りたいのですが。つまり、割り込みの影響を受けないコードの一部がある場合(または、さらに悪いことに、何らかの理由で割り込みをリッスンしてはならない場合)、次のことを行う方がよいでしょう。
- クリティカルセクションの前に割り込みを無効にしてから、再度有効にします。
- それぞれのISR内にフラグを設定し、(割り込みを無効にする代わりに)クリティカルセクションの前にフラグをfalseに設定し、直後にtrueにリセットします。ISRのコードが実行されないようにするため。
- どちらもないので、提案は大歓迎です!
更新:割り込みと状態チャート
具体的な状況をお知らせします。4つのブロックで構成されるステートチャートを実装するとします。
- 遷移/効果。
- 終了条件。
- エントリー活動。
- 活動を行う。
これは大学で教授が私たちに教えたものです。おそらく、それを行う最良の方法は、このスキームに従うことではありません。
while(true) {
/* Transitions/Effects */
//----------------------------------------------------------------------
next_state = current_state;
switch (current_state)
{
case STATE_A:
if(EVENT1) {next_state = STATE_C}
if(d == THRESHOLD) {next_state = STATE_D; a++}
break;
case STATE_B:
// transitions and effects
break;
(...)
}
/* Exit activity -> only performed if I leave the state for a new one */
//----------------------------------------------------------------------
if (next_state != current_state)
{
switch(current_state)
{
case STATE_A:
// Exit activity of STATE_A
break;
case STATE_B:
// Exit activity of STATE_B
break;
(...)
}
}
/* Entry activity -> only performed the 1st time I enter a state */
//----------------------------------------------------------------------
if (next_state != current_state)
{
switch(next_state)
{
case STATE_A:
// Entry activity of STATE_A
break;
case STATE_B:
// Entry activity of STATE_B
break;
(...)
}
}
current_state = next_state;
/* Do activity */
//----------------------------------------------------------------------
switch (current_state)
{
case STATE_A:
// Do activity of STATE_A
break;
case STATE_B:
// Do activity of STATE_B
break;
(...)
}
}
また、たとえばSTATE_A
、(debouceシステムなどを使用した)ボタンのセットからの割り込みに敏感になりたいとしましょう。誰かがこれらのボタンの1つを押すと、割り込みが生成され、入力ポートに関連するフラグが変数にコピーされますbuttonPressed
。デバウンスが何らかの方法で200ミリ秒に設定されている場合(ウォッチドッグタイマー、タイマー、カウンターなど)、buttonPressed
200ミリ秒より前に新しい値で更新することはできません。これは私があなたに(そして私自身ももちろん)尋ねていることです)
終了STATE_A
する前に、DOアクティビティの割り込みを有効にし、無効にする必要がありますか?
/* Do activity */
//-------------------------------------
switch (current_state)
{
case STATE_A:
// Do activity of STATE_A
Enable_ButtonsInterrupt(); // and clear flags before it
// Do fancy stuff and ...
// ... wait until a button is pressed (e.g. LPM3 of the MSP430)
// Here I have my buttonPressed flag ready!
Disable_ButtonsInterrupt();
break;
case STATE_B:
// Do activity of STATE_B
break;
(...)
}
次の繰り返しでブロック1(遷移/効果)を次回実行するときに、遷移に沿ってチェックされた条件が、その前の値を上書きした後続の割り込みから来ていないことを確信してbuttonPressed
いる方法で必要(250ミリ秒が経過する必要があるため、これが発生することは不可能ですが)。