C 这是与按钮/操纵杆交互的正确方式吗?
我目前正在尝试用LED灯制作记忆游戏,但它变成了一场羞辱性的斗争。从想法开始更符合逻辑。这个想法是,在两个二极管的帮助下,播放一些序列,你必须用操纵杆重复它。我的程序应该是这样的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])
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;
}
//...