最初的问题
我有一个关于微控制器中断处理的一般性问题。我正在使用 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 系统等)的中断敏感。当有人按下其中一个按钮时,会产生一个中断,并且与输入端口相关的标志被复制到一个变量buttonPressed中。如果以某种方式(看门狗定时器、定时器、计数器……)将去抖动设置为 200 毫秒,我们确信buttonPressed在 200 毫秒之前无法使用新值进行更新。这就是我要问你(和我自己:)当然)
我是否需要在 DO 活动中启用中断STATE_A并在离开前禁用?
/* 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 毫秒)。