在 C 中中断更新后,我的 while 循环没有中断

My while loop is not breaking after my interrupt updates in C

我正在实施 simon says 作为学校每周的一个小项目。使用 arduino Uno,我制作了 10 个关卡,每个关卡内部都有一个额外的模式。例如:1 级:[1],2 级:[1,2],等等……我的盾牌上有三个按钮。中断工作,一切都是 gucci。我的问题出在这个片段

bool readInput(uint8_t pattern[], uint8_t length)
{
    sei();
    uint8_t current = 0;
    while (current < length)
    {
        btnPushed = false;
        while (!btnPushed)
        {
#ifdef DEBUG
            _delay_ms(1);
#endif
        }
        printf("here");
        cli();
        _delay_ms(200);
        if (currentPushed == pattern[current])
        {
            printf("correct, you pushed %d\n", currentPushed);
        }
        else
        {
            printf("incorrect, lets try again\n");
            return false;
        }
    }
    btnPushed = false;
    return true;
}

所以基本上我将 buttonPushed 设置为 false,并开始侦听中断,一旦单击后为 true,我希望退出循环并检查输入,但是我的中断是正确的,并且我得到了带有指示灯的视觉反馈一旦我按下按钮,它就会亮起。

这是我的 ISR

ISR(PCINT1_vect)
{
    uint8_t buttonCurr = currentButton();
    if (buttonCurr != -1)
    {
        if (!btn1Pushed && buttonCurr == 0)
        {
            btn1Pushed = true;
        }
        currentPushed = buttonCurr;
        blinkLed(currentPushed, 1);
        btnPushed = true;
    }
}

我的当前按钮 returns 0-2 代表被点击的按钮,-1 如果没有被点击。

这是我的其余代码,可以正常工作

int currentPushed = -1;
bool won;
bool btnPushed = false;
bool btn1Pushed = false;

ISR(PCINT1_vect)
{
    uint8_t buttonCurr = currentButton();
    if (buttonCurr != -1)
    {
        if (!btn1Pushed && buttonCurr == 0)
        {
            btn1Pushed = true;
        }
        currentPushed = buttonCurr;
        blinkLed(currentPushed, 1);
        btnPushed = true;
    }
}

int main(void)
{
    enableAllButtons();
    enableAllLeds();
    lightDownAllLeds();

    prepareButtonsForInterrupt();
    initUSART();
    init();

    play();
    if (won)
    {
        printf("Simon says you win");
    }
    else
    {
        printf("simon says do better");
    }
    return 0;
}

void init(void)
{
    printf("LETS PLAY SIMON SAYS\nPress button 1 to start!\n");

    int seed = 0;
    while (!btn1Pushed)
    {
        blinkLed(3, 4);
        seed++;
    }
    srand(seed);

    printf("Get ready!\n");
    btnPushed = false;
    cli();
}

void createRandomPattern(uint8_t array[], uint8_t length)
{
    for (int i = 0; i < length; i++)
    {
        array[i] = rand() % 3;
    }
}

void play(uint8_t pattern[])
{
    uint8_t fullPattern[MAX_PATTERN_LENGTH];
    createRandomPattern(fullPattern, MAX_PATTERN_LENGTH);
    for (int i = 1; i <= MAX_PATTERN_LENGTH; i++)
    {
        printf("========LEVEL %d===========\n", i);
        playPuzzle(fullPattern, i);
#ifdef DEBUG
        printPuzzle(fullPattern, i);
#endif
        readInput(fullPattern, i) ?: i--;
    }
}

bool readInput(uint8_t pattern[], uint8_t length)
{
    sei();
    uint8_t current = 0;
    while (current < length)
    {
        btnPushed = false;
        while (!btnPushed)
        {
        }
        cli();
        if (currentPushed == pattern[current])
        {
            printf("correct, you pushed %d\n", currentPushed);
        }
        else
        {
            printf("incorrect, lets try again\n");
            return false;
        }
        current++;
    }
    btnPushed = false;
    return true;
}

void printPuzzle(uint8_t pattern[], uint8_t length)
{
    printf("[ ");
    for (int i = 0; i < length; i++)
    {
        printf("%d ", pattern[i]);
    }
    printf("]\n");
}

void playPuzzle(uint8_t pattern[], uint8_t length)
{
    for (int i = 0; i < length; i++)
    {
        lightUpOneLed(pattern[i]);
        _delay_ms(500);
        lightDownOneLed(pattern[i]);
    }
}

btnPushed 定义为 bool btnPushed = false;.

所以当你写的时候:

    while (!btnPushed)
    {
#ifdef DEBUG
        _delay_ms(1);
#endif
    }

循环中的任何内容都不会更改 btnPushed,因此编译器没有必要再次检查 btnPushed。所以编译器看到的是这样的:

    if (!btnPushed)
        while(true)
        {
#ifdef DEBUG
            _delay_ms(1);
#endif
        }

你必须告诉编译器当中断触发时 btnPushed 的值会意外改变:

volatile bool btnPushed = false;