C 这是与按钮/操纵杆交互的正确方式吗?

C 这是与按钮/操纵杆交互的正确方式吗?,c,microcontroller,avr,C,Microcontroller,Avr,我目前正在尝试用LED灯制作记忆游戏,但它变成了一场羞辱性的斗争。从想法开始更符合逻辑。这个想法是,在两个二极管的帮助下,播放一些序列,你必须用操纵杆重复它。我的程序应该是这样的 void main() { generateNewGame(); blinkLeds(); for (uint8_t index = 0; i < Game_Length; index++) { if(waitForPress() != GameArray[index])

我目前正在尝试用LED灯制作记忆游戏,但它变成了一场羞辱性的斗争。从想法开始更符合逻辑。这个想法是,在两个二极管的帮助下,播放一些序列,你必须用操纵杆重复它。我的程序应该是这样的

void main() {
    generateNewGame();
    blinkLeds();
    for (uint8_t index = 0; i < Game_Length; index++) {
        if(waitForPress() != GameArray[index])
            blinkFail();
            return;
        }
    }
    blinkSuccess();
}
我对这个函数有问题

waitForPress()
我的“游戏数组”中充满了1和0。 我想这样做,如果我向左转动操纵杆,那么函数“waitForPress()”将返回1,主要是我想将这个1与我的“GameArray”进行比较,如果这是真的,检查下一个元素。与“游戏”阵列进行比较对我不起作用。此外,由于某些原因,我的左侧led一直亮着,操纵杆没有响应。我希望我的话有意义,如果你有任何问题,我准备补充这个问题。 我现在的代码

#define F_CPU 2000000UL
#include <avr/io.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>

// Global
uint8_t Game[8];
int i;


const uint16_t n = 500;

void delay(uint16_t n) {
    for(uint16_t i = 0; i < n ; i++) {
        for(uint16_t j = 0; j < 200 ; j++) {
            asm volatile ("NOP");
        }
    }
}
// Function for filling the game array with ones and zeros 
void RandomNumber() {
    
    srand((unsigned int)time(NULL));
    for(unsigned int i = 0; i < sizeof(Game)/sizeof(Game[0]); i++) {
        int v = rand() % 2;
        Game[i] = v;
    }
}
// Function for flashing the Game array sequence
void PlayDemo() {
    int i;
    for(i = 0; i <= 8; i++) {
        if(Game[i] == 1) {
            PORTA = 0x80;
            delay(n);
            PORTA = 0x00;
            delay(n);
        }
        else if (Game[i] == 0) {
            PORTA = 0x01;
            delay(n);
            PORTA = 0x00;
            delay(n);
        }
        else {
            PORTA = 0x00;
        }
    }
}

int waitForPress() {

    uint8_t x = PINF;
    // Until the button is off, do nothing
    while(!(x & 0x20) && !(x & 0x08)) {
        x = PINF;
    }
    // Check if we press to the left
    if(x & 0x20) {
        // Last LED ON
        PORTA = 0x80;
        // Wait ( Debouncing )
        delay(n);
        return 1;
    }
    // Check if we press to the right side
    if(x & 0x08) {
        // First LED ON
        PORTA = 0x01;
        // Wait ( Debouncing )
        delay(n);
        return 0;
    }
    return 0;
}


int main(void) {
    MCUCR |= 0x80;
    MCUCR |= 0x80;
    DDRA = 0xFF;
    PORTF = 0x20;
    
    RandomNumber();
    PlayDemo();
    
    while(1)
    {
        // Check all elements of the "Game" array
        for(uint8_t index = 0; index < 8; index++) {
            // If the output of the function "waitForPress()" is not equal to "Game" array element
            if(waitForPress() != Game[index]) {
                // End the game
                break;
            } else if(waitForPress() == Game[index]) {
                // Turn all led ON
                PORTA = 0xFF;
                // Wait
                delay(n);
                // Turn all led OFF
                PORTA = 0x00;
                // Wait
                delay(n);
            }
        }
    }
}
#定义F#u CPU 200000ul
#包括
#包括
#包括
#包括
//全球的
uint8_t游戏[8];
int i;
常数16_t n=500;
无效延迟(uint16\n){
对于(uint16_t i=0;i对于(i=0;i),您的程序可能存在多个问题:

(1) 首先:在将用户输入与游戏数组进行比较的FOR循环中,当用户输入正确答案时,您调用了两次
waitForPress()
。这不是您想要的,您的代码应该如下所示:

//...
if (waitForPress() != Game[index])
{
    //...
    break;
}
else
{
    //... (correct answer)
}
//...
或者你可以:

//...
int userInput = waitForPress();
if (userInput != Game[index])
{
    //...
    break;
}
else
{
    //... (correct answer)
}
//...
(2) 假设(1)中的代码正确,我认为另一个主要问题是处理用户输入的方式。让我来说明这个问题:

  • 开始时,没有按下任何键。您的主程序名为
    waitForPress()
    ,并且“卡在”WHILE循环中,等待用户按下操纵杆
  • 当用户最后按下操纵手柄时,该功能返回1或0
  • 在主程序中,该返回值根据FOR循环中的IF语句进行处理(请参见(1))
  • 在此之后不久,
    waitForPress()
    再次被调用(如果输入错误,则几乎立即调用;如果延迟后输入正确;我假设这意味着所有LED都会短暂“闪烁”,持续几百毫秒)
  • 由于按钮仍被按下(人类的速度很慢!),
    waitForPress()
    会立即返回。现在,您的程序认为您再次进行了相同的输入,尽管您的理解是您甚至没有进行第二次输入
要解决此问题,您需要检测信号边缘。最简单的方法是确保在等待一个按钮打开之前释放操纵杆。您可以修改
waitForPress()
如下:

int waitForPress() {
    uint8_t x = PINF;

    // Make sure that the user released the joystick
    while((x & 0x20) || (x & 0x08)) {
        x = PINF;
    }

    // Until one button comes on, do nothing
    while(!(x & 0x20) && !(x & 0x08)) {
        x = PINF;
    }

    //...
此外,您可能希望添加处理反弹的机制

(3) 您永远不会退出
main()
函数中的WHILE循环。因此,您的程序始终处于期望用户输入的状态


(4) 在函数
PlayDemo()
中,您正在访问一个“不存在的”游戏数组元素(
Game[8]
),因为FOR循环的条件是
i您应该从等待循环中的寄存器更新
x
。@EugeneSh。谢谢您的评论。我需要这样更新x值吗?“x=PINF”
int waitForPress() {
    uint8_t x = PINF;

    // Make sure that the user released the joystick
    while((x & 0x20) || (x & 0x08)) {
        x = PINF;
    }

    // Until one button comes on, do nothing
    while(!(x & 0x20) && !(x & 0x08)) {
        x = PINF;
    }

    //...