Вообщем, я делаю небольшую поделку на основе микроконтроллера AVR,
но так как мне нужно было 6 кнопок, а выводов осталось мало, я решил
попробовать "выкрутиться" из этой ситуации таким образом, как это показано
на рисунке.
Нажмите для просмотра прикрепленного файла
PA0 и PA1 - ножки микроконтроллера, на которых постоянно находится
высокий уровень. В первый момент времени я устанавливаю на PB0 низкий
уровень, и, получается, что когда мы нажимаем кнопку S1 или S4, на одном из
входов МК так же установится низкий уровень напряжения. Таким образом,
можно отследить, какая кнопка нажата в момент времени. Остальные кнопки
опрашиваются по этому же алгоритму (подаём 0 на PB1, а потом на PB2).
За сим вопрос: правильно ли я вообще делаю? Когда я проводил эксперимент
с одной кнопкой, всё работало, и я с лёгкостью мог отследить её нажатие, но
когда я собрал эту схему на макетке, всё пошло крахом: ни одна кнопка не отзывается.
Если кто-нибудь сможет разобраться, есть ли у этой схемы шанс заработать,
буду премного благодарен. Код опроса этой конструкции так же прилагаю
(может быть, его можно было бы сделать изящнее, но получилось вот так).
Код
#define STEP1 1 //Метки для атомата
#define STEP2 2
#define STEP3 3
//...
DDRA |= (0<<PORTA0)|(0<<PORTA1); //Настройка ножек порта А на вход
DDRB |= (1<<PORTB0)|(1<<PORTB1)|(1<<PORTB2); //Настройка ножек порта B на выход
//..
int button_flag; //Флаг для цикла
int button_state; //Для хренения состояния автомата
//..
void key_polling()
{
button_state = STEP1; //Первое состояние
button_flag = 1; //Устанавливаем флаг
while(button_flag == 1)
{
switch(button_state)
{
case STEP1: //Опрашиваем кнопки 1 и 4
PORTB |= (0<<PORTB0)|(1<<PORTB1)|(1<<PORTB2); //На ножке PB0 устанавливаем низкий уровень
if((PINA & (1<<PORTA0) == 0)) //Если на PA0 - 0, то...
{
//Некое действие
button_state = STEP2; //Переходим к опрос следующей двойки
}
else if((PINA & (1<<PORTA1) == 0)) //Если на PA1 - 0, то...
{
//Что-то делаем
button_state = STEP2;
}
else //Если не получили низкий уровень ни на одной из ножек
{
button_state = STEP2;
}
break;
case STEP1: //Опрашиваем кнопки 2 и 5
PORTB |= (1<<PORTB0)|(0<<PORTB1)|(1<<PORTB2); //На PB1 устанавливаем низкий уровень
//Код, аналогичный блоку STEP1
break;
case STEP3: //Опрашиваем кнопки 3 и 6
PORTB |= (1<<PORTB0)|(1<<PORTB1)|(0<<PORTB2); //На PB2 устанавливаем низкий уровень
//Код, аналогичный блоку STEP1
button_flag = 0; //Так как все кнопки опросили, обнуляем флаг для выхода из цикла
break;
}
}
}
#define STEP2 2
#define STEP3 3
//...
DDRA |= (0<<PORTA0)|(0<<PORTA1); //Настройка ножек порта А на вход
DDRB |= (1<<PORTB0)|(1<<PORTB1)|(1<<PORTB2); //Настройка ножек порта B на выход
//..
int button_flag; //Флаг для цикла
int button_state; //Для хренения состояния автомата
//..
void key_polling()
{
button_state = STEP1; //Первое состояние
button_flag = 1; //Устанавливаем флаг
while(button_flag == 1)
{
switch(button_state)
{
case STEP1: //Опрашиваем кнопки 1 и 4
PORTB |= (0<<PORTB0)|(1<<PORTB1)|(1<<PORTB2); //На ножке PB0 устанавливаем низкий уровень
if((PINA & (1<<PORTA0) == 0)) //Если на PA0 - 0, то...
{
//Некое действие
button_state = STEP2; //Переходим к опрос следующей двойки
}
else if((PINA & (1<<PORTA1) == 0)) //Если на PA1 - 0, то...
{
//Что-то делаем
button_state = STEP2;
}
else //Если не получили низкий уровень ни на одной из ножек
{
button_state = STEP2;
}
break;
case STEP1: //Опрашиваем кнопки 2 и 5
PORTB |= (1<<PORTB0)|(0<<PORTB1)|(1<<PORTB2); //На PB1 устанавливаем низкий уровень
//Код, аналогичный блоку STEP1
break;
case STEP3: //Опрашиваем кнопки 3 и 6
PORTB |= (1<<PORTB0)|(1<<PORTB1)|(0<<PORTB2); //На PB2 устанавливаем низкий уровень
//Код, аналогичный блоку STEP1
button_flag = 0; //Так как все кнопки опросили, обнуляем флаг для выхода из цикла
break;
}
}
}