Здравствуйте ув. форумчане!
Обращаюсь к Вам за помощью в разъяснении некоторого вопроса.
Существует такая игра, как "лампочки", я хотел реализовать ее в "железе".
Имеется панель с 16 кнопками без фиксации и лампочкой внутри каждой кнопки. Кнопки расположены как матрица 4х4. Изначально кнопки светятся в заранее заданной последовательности (не имеет значения какой) и нажимая правильную комбинацию этих кнопок надо заставить их все потухнуть. После того, как это условие выполнено (потухли все) - они все разом зажигаются, и на свободную ножку МК подается импульс, и программа останавливается до Reset`а.
Вот простое условие, которое описывает всю суть этой, достаточно простой программы:
-При нажатии на горящую клавишу потухают все, что вокруг нее, в том числе и сама нажатая клавиша, а если они были потухшие — загораются.
-При нажатии на потухшую клавишу загораются все вокруг нее и сама клавиша. Если до этого горели — потухают.
-Необходимо нажимая правильную последовательность кнопок "потушить" все.
Написал код. Так как кнопок 16, а выводов не так много, чтобы их все задействовать, я решил использовать АЦП, и, подключив все 16 кнопок через разные резисторы к АЦП "снимаю" показания и вычисляю какая кнопка нажата.
Так же написал Инициализацию для всех светодиодов, функции включения и выключения, но код, почему-то не работает.
А если я непонятно объяснил суть программы, это, по сути игра. Я ее нашел вот здесь, очень простая и понятная игра "Лампочки". Как вариант она есть на этом сайте: http://flash-yes.ru/lampochki/ (перечитал правила форума, надеюсь можно оставить ссылку здесь).
В оригинале игра 5*5, мне необходима именно 4*4, реализованная в коде. Заранее извиняюсь за кривой код, пока только учусь. Уверен его можно написать куда более кратко и прозрачно, но, для начала необходимо добиться, чтобы он хотя бы выполнялся. И заранее извиняюсь за огромный прикрепленный код. Не совсем понял, как его можно было бы свернуть для читаемости.
Файл main:
#define F_CPU 16000000UL // Atmega 328P with 16MHz crystal
#include <avr/io.h>
#include <avr/interrupt.h> //подгружаем прерывание
#include "keyboard.h"
#include "leds.h"
#include <util/delay.h>
void InitADC(void);
void ButtonState(void);
void StartGame(void);
void GameWin(void);
// Прерывание по АЦП
ISR (ADC_vect)
{
Keyboard();
}
int main(void)
{
InitADC();
LedsOutput();
StartGame();
while(1)
{
if(num_ &(1<<7)) //если 7 бит в 1 то цифра записана
{
num_ &=~ (1<<7); //cброс 7 бита в регистре num_, остается код кнопки
}
ButtonState();
GameWin();
}
}
void StartGame(void)
{
// Рандомно заданные начальные условия игры
LED1_ON();
LED2_ON();
LED3_ON();
LED4_ON();
LED5_ON();
LED6_OFF();
LED7_OFF();
LED8_ON();
LED9_ON();
LED10_OFF();
LED11_OFF();
LED12_ON();
LED13_ON();
LED14_ON();
LED15_ON();
LED16_ON();
}
void ButtonState(void)
{
// Тушить саму кнопку при нажатии или зажигать, если не горела.
// Тушить все кнопки вокруг нажатой, если горели, зажигать, если нет.
/****BUTTON_1*****/
if (num_ == 1)
{
if (LED1_PIN & (1<<LED1_BIT)) LED1_OFF();
else LED1_ON();
if (LED2_PIN & (1<<LED2_BIT)) LED2_OFF();
else LED2_ON();
if (LED5_PIN & (1<<LED5_BIT)) LED5_OFF();
else LED5_ON();
}
/****BUTTON_2*****/
if (num_== 2)
{
if (LED2_PIN & (1<<LED2_BIT)) LED2_OFF();
else LED2_ON();
if (LED1_PIN & (1<<LED1_BIT)) LED1_OFF();
else LED1_ON();
if (LED3_PIN & (1<<LED3_BIT)) LED3_OFF();
else LED3_ON();
if (LED6_PIN & (1<<LED6_BIT)) LED6_OFF();
else LED6_ON();
}
/****BUTTON_3****/
if (num_ == 3)
{
if (LED3_PIN & (1<<LED3_BIT)) LED3_OFF();
else LED3_ON();
if (LED2_PIN & (1<<LED2_BIT)) LED2_OFF();
else LED2_ON();
if (LED4_PIN & (1<<LED4_BIT)) LED4_OFF();
else LED4_ON();
if (LED7_PIN & (1<<LED7_BIT)) LED7_OFF();
else LED7_ON();
}
/****BUTTON_4****/
if (num_ == 4)
{
if (LED4_PIN & (1<<LED4_BIT)) LED4_OFF();
else LED4_ON();
if (LED3_PIN & (1<<LED3_BIT)) LED3_OFF();
else LED3_ON();
if (LED8_PIN & (1<<LED8_BIT)) LED8_OFF();
else LED8_ON();
}
/****BUTTON_5****/
if (num_ == 5)
{
if (LED5_PIN & (1<<LED5_BIT)) LED5_OFF();
else LED5_ON();
if (LED1_PIN & (1<<LED1_BIT)) LED1_OFF();
else LED1_ON();
if (LED6_PIN & (1<<LED6_BIT)) LED6_OFF();
else LED6_ON();
if (LED9_PIN & (1<<LED9_BIT)) LED9_OFF();
else LED9_ON();
}
/****BUTTON_6****/
if (num_ == 6)
{
if (LED6_PIN & (1<<LED6_BIT)) LED6_OFF();
else LED6_ON();
if (LED2_PIN & (1<<LED2_BIT)) LED2_OFF();
else LED2_ON();
if (LED5_PIN & (1<<LED5_BIT)) LED5_OFF();
else LED5_ON();
if (LED7_PIN & (1<<LED7_BIT)) LED7_OFF();
else LED7_ON();
if (LED10_PIN & (1<<LED10_BIT)) LED10_OFF();
else LED10_ON();
}
/****BUTTON_7****/
if (num_== 7)
{
if (LED7_PIN & (1<<LED7_BIT)) LED7_OFF();
else LED7_ON();
if (LED3_PIN & (1<<LED3_BIT)) LED3_OFF();
else LED3_ON();
if (LED6_PIN & (1<<LED6_BIT)) LED6_OFF();
else LED6_ON();
if (LED8_PIN & (1<<LED8_BIT)) LED8_OFF();
else LED8_ON();
if (LED11_PIN & (1<<LED11_BIT)) LED11_OFF();
else LED11_ON();
}
/****BUTTON_8****/
if (num_== 8)
{
if (LED8_PIN & (1<<LED8_BIT)) LED8_OFF();
else LED8_ON();
if (LED4_PIN & (1<<LED4_BIT)) LED4_OFF();
else LED4_ON();
if (LED7_PIN & (1<<LED7_BIT)) LED7_OFF();
else LED7_ON();
if (LED12_PIN & (1<<LED12_BIT)) LED12_OFF();
else LED12_ON();
}
/****BUTTON_9****/
if (num_== 9)
{
if (LED9_PIN & (1<<LED9_BIT)) LED9_OFF();
else LED9_ON();
if (LED5_PIN & (1<<LED5_BIT)) LED5_OFF();
else LED5_ON();
if (LED10_PIN & (1<<LED10_BIT)) LED10_OFF();
else LED10_ON();
if (LED13_PIN & (1<<LED13_BIT)) LED13_OFF();
else LED13_ON();
}
/****BUTTON_10****/
if (num_ == 10)
{
if (LED10_PIN & (1<<LED10_BIT)) LED10_OFF();
else LED10_ON();
if (LED6_PIN & (1<<LED6_BIT)) LED6_OFF();
else LED6_ON();
if (LED9_PIN & (1<<LED9_BIT)) LED9_OFF();
else LED9_ON();
if (LED11_PIN & (1<<LED11_BIT)) LED11_OFF();
else LED11_ON();
if (LED14_PIN & (1<<LED14_BIT)) LED14_OFF();
else LED14_ON();
}
/****BUTTON_11****/
if (num_ == 11)
{
if (LED11_PIN & (1<<LED11_BIT)) LED11_OFF();
else LED11_ON();
if (LED7_PIN & (1<<LED7_BIT)) LED7_OFF();
else LED7_ON();
if (LED10_PIN & (1<<LED10_BIT)) LED10_OFF();
else LED10_ON();
if (LED12_PIN & (1<<LED12_BIT)) LED12_OFF();
else LED12_ON();
if (LED15_PIN & (1<<LED15_BIT)) LED15_OFF();
else LED15_ON();
}
/****BUTTON_12****/
if (num_ == 12)
{
if (LED12_PIN & (1<<LED12_BIT)) LED12_OFF();
else LED12_ON();
if (LED8_PIN & (1<<LED8_BIT)) LED8_OFF();
else LED8_ON();
if (LED11_PIN & (1<<LED11_BIT)) LED11_OFF();
else LED11_ON();
if (LED16_PIN & (1<<LED16_BIT)) LED16_OFF();
else LED16_ON();
}
/****BUTTON_13****/
if (num_ == 13)
{
if (LED13_PIN & (1<<LED13_BIT)) LED13_OFF();
else LED13_ON();
if (LED9_PIN & (1<<LED9_BIT)) LED9_OFF();
else LED9_ON();
if (LED14_PIN & (1<<LED14_BIT)) LED14_OFF();
else LED14_ON();
}
/****BUTTON_14****/
if (num_ == 14)
{
if (LED14_PIN & (1<<LED14_BIT)) LED14_OFF();
else LED14_ON();
if (LED10_PIN & (1<<LED10_BIT)) LED10_OFF();
else LED10_ON();
if (LED13_PIN & (1<<LED13_BIT)) LED13_OFF();
else LED13_ON();
if (LED15_PIN & (1<<LED15_BIT)) LED15_OFF();
else LED15_ON();
}
/****BUTTON_15****/
if (num_ == 15)
{
if (LED15_PIN & (1<<LED15_BIT)) LED15_OFF();
else LED15_ON();
if (LED11_PIN & (1<<LED11_BIT)) LED11_OFF();
else LED11_ON();
if (LED14_PIN & (1<<LED14_BIT)) LED14_OFF();
else LED14_ON();
if (LED16_PIN & (1<<LED16_BIT)) LED16_OFF();
else LED16_ON();
}
/****BUTTON_16****/
if (num_ == 16)
{
if (LED16_PIN & (1<<LED16_BIT)) LED16_OFF();
else LED16_ON();
if (LED12_PIN & (1<<LED12_BIT)) LED12_OFF();
else LED12_ON();
if (LED15_PIN & (1<<LED15_BIT)) LED15_OFF();
else LED15_ON();
}
}
void GameWin()
{
// Условие выйгрыша - все светодиоды потухли
if ()
{
}
WIN_PORT |= (1<<WIN_BIT);
}
void InitADC(void)
{
// Инициализация АЦП
PORTC &=~(1<<PC0);
DDRC &=~ (1<<PC0);
ADCSRA|=(1<<ADEN)|(1<<ADIE)|(1<<ADPS2)|(1<<ADSC)|(1<<ADATE);
ADMUX |=(1<<REFS0);
asm("sei");
}
Функция LED1_ON имеет такой вид:
void LED1_ON(void)
{
LED1_PORT |=(1<<LED1_BIT);
}
Функцию чтения данных с АЦП стащил с одного видеоурока
volatile unsigned char num_;
Keyboard()
{
static unsigned char Deistvie, Kol_Proverok, Temp;
unsigned char num;
//-----------------//
num = NumADC();
if(Deistvie & (1<<0))
{
if(num == 100)
{
if((Kol_Proverok++) < 250)
{
if(num != Temp)
{
Temp = num;
Kol_Proverok=0;
}
}
else
{
Kol_Proverok=0;
Deistvie &=~(1<<0);
}
return;
}
else
{
Temp =0;
Kol_Proverok=0;
}
}
//====================//
else
{
if(num_ != (1<<7))
{
if(num != 100)
{
Deistvie &=~(1<<1);
if((Kol_Proverok++) < 150)
{
if(num!= Temp)
{
Temp = num;
Kol_Proverok=0;
}
}
else
{
num_ = Temp|(1<<7);
Kol_Proverok=0;
Deistvie|=(1<<0);
}
return;
}
}
if(Deistvie != (1<<1))
{
Kol_Proverok=0;
Temp=100;
Deistvie|=(1<<1);
}
}
}
NumADC()
{
unsigned int ACP;
ACP = ADCW;
if(ACP < 45)
return 1;
if(ACP < 74)
return 2;
if(ACP < 94)
return 3;
if(ACP < 220)
return 4;
if(ACP < 280)
return 5;
if(ACP < 340)
return 6;
if(ACP < 400)
return 7;
if(ACP < 505)
return 8;
if(ACP < 580)
return 9;
if(ACP < 630)
return 10;
if(ACP < 710)
return 11;
if(ACP < 790)
return 12;
if(ACP < 870)
return 13;
if(ACP < 950)
return 14;
if(ACP < 1000)
return 15;
if(ACP <1024)
return 16;
return 100;
}
Заранее благодарю за ответ,
С уважением,
Максим.