Есть у меня задачка, которую никак не могу решить. У меня есть 6 кнопок (картинка прилагается), подключены они по две штуки к одному пину. Необходимо сделать так, чтобы при нажатии на каждую кнопку, происходило какое-то своё действие: светодиод мигал с разной чистотой, или динамик гудел различными тонами. И, вот, если одну пару кнопок я уже научился контролировать, то другие никак не могу. Подробности в комментариях к коду.
Сам я программировать и разбираться с МК начал меньше месяца назад. Прошу не судить строго за любые возможные глупые ляпы. Буду благодарен вам за любую помощь! Мозг уже разрывается на части

Прогаю в IAR EW на MSP430f2112.
Код
#include "msp430f2112.h"
#define RED_LEDS (BIT0) //красненький светодиодик
#define GREEN_LED (BIT2) //зелёненький
#define SPKR (BIT3) // Динамик (здесь я смотрю результат через осциллограф)
#define BUTTON1 (BIT0) // Две кнопки (SB1 и SB2), подсоединённые к P2.0
#define BUTTON2 (BIT3) // Две кнопки (SB3 и SB4), подсоединённые к P2.3
#define BUTTON3 (BIT4) // Две кнопки (SB5 и SB6), подсоединённые к P2.4
volatile char flash = 0;
volatile char flash2 = 0;
void TA_init(void);
void ADC_init(void);
//***********************Главная функция*************************
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Останавливаем сторожевой таймер
BCSCTL3 = LFXT1S1; // Источником сигнала ACLK будет низкочастотный встроенный генератор со сверхнизким
// энергопотреблением VLO. Частота ACLK = 12 кГц
P1DIR |= GREEN_LED; // Устанавливаем порт на выход
P1OUT &= ~GREEN_LED; // Отключаем диод
P1DIR |= RED_LEDS;
P1OUT &= ~RED_LEDS;
P1DIR |= SPKR;
P1REN |= SPKR; // Устанавливаем резистор подтяжки, в нашем случае он уменьшает громкость динамика в ~4раза
P1OUT &= ~SPKR;
TA_init();
ADC_init();
__bis_SR_register(GIE); // Разрешаем прерывания
while(1)
{
/*ADC10CTL0 &= ~ENC;
ADC10CTL1 = INCH_4;
ADC10CTL0 |= ENC + ADC10SC; // Если здесь снять комментарии, то мигать светодиод будет
LPM3; // только при нажатии трёх! кнопок одновременно.
ADC10CTL0 &= ~ENC; // Т.е., допустим, чтобы мигать по таймеру А0, нужно
ADC10CTL1 = INCH_3; // нажать SB1, SB3 и SB5. По отдельности они вызывают
ADC10CTL0 |= ENC + ADC10SC; // какие-то отдельные колебания, которые только складываясь
LPM3;*/ // вместе, дают желаемый сигнал.
ADC10CTL0 &= ~ENC;
ADC10CTL1 = INCH_0;
ADC10CTL0 |= ENC + ADC10SC;
LPM3;
}
}
//***********************Инициализируем АЦП*************************
void ADC_init(void)
{
ADC10CTL0 = MSC + SREF_1 + ADC10SHT_2 + REFON + ADC10ON + ADC10IE; // настраиваем и включаем АЦП, разрешаем прерывания
ADC10CTL1 = ADC10SSEL_1 + CONSEQ_0; // Буду благодарен, если кто-нибудь объянит мне, что меняет,
// и на практике делает CONSEQ, т.к. в моём случае, его изменение ни к чему не приводит.
// и я не понимаю чего люди пытаются им добиться.
ADC10AE0 |= BUTTON1 + BUTTON2 + BUTTON3; // Пины с кнопками как входы АЦП
}
//***********************Инициализируем Таймер*************************
void TA_init(void)
{
//Создаём таймер для удобного моргания через прерывания
TA0CCR0 = 56;
TA0CCR1 = 28;
TA0CCTL0 = CCIE; // Разрешаем прерывание таймера по достижении CCR0
TA0CCTL1 = OUTMOD_3 + CCIE;
TA0CTL = TASSEL_1 + MC_1 + TAIE; // ACLK, Прямой счёт
}
//***********************Инициализируем Прерывания*************************
#pragma vector = TIMER0_A0_VECTOR
__interrupt void T0_A0(void)
{
P1OUT ^= flash; // если flash == 0, светодиод не горит
// если flash == GREEN_LED, мигаем светодиодом
LPM3_EXIT;
}
#pragma vector = TIMER0_A1_VECTOR
__interrupt void T0_A1(void)
{
P1OUT ^= flash2; // если flash2 == 0, светодиод не горит
// если flash2 == GREEN_LED, мигаем светодиодом
TA0IV = 0x00; //чистим регистр вектора
LPM3_EXIT;
}
#pragma vector = ADC10_VECTOR
__interrupt void ADC10_ISR (void)
{
if (0x03FC < ADC10MEM && ADC10MEM < 0x0400) // Если нажата SB1
{
P1OUT &= ~RED_LEDS;
//flash = GREEN_LED; //мигает светодиод по таймеру A0
flash = SPKR; // или гудит динамик
flash2 = 0;
}
else if (0x025A < ADC10MEM && ADC10MEM < 0x03FA) // Если кнопки не нажаты
{
P1OUT &= ~GREEN_LED;
P1OUT &= ~RED_LEDS;
flash = 0;
flash2 = 0;
}
else if (0x0246 < ADC10MEM && ADC10MEM < 0x025A) // Если обе кнопки нажаты
{
P1OUT &= ~GREEN_LED;
P1OUT |= RED_LEDS;
flash = 0;
flash2 = 0;
}
else if (0x017F < ADC10MEM && ADC10MEM < 0x0193) // Если нажата SB2
{
P1OUT &= ~RED_LEDS;
//flash2 = GREEN_LED; //мигает светодиод по таймеру A1
flash2 = SPKR; //или гудит динамик
flash = 0;
}
LPM3_EXIT;
}
#define RED_LEDS (BIT0) //красненький светодиодик
#define GREEN_LED (BIT2) //зелёненький
#define SPKR (BIT3) // Динамик (здесь я смотрю результат через осциллограф)
#define BUTTON1 (BIT0) // Две кнопки (SB1 и SB2), подсоединённые к P2.0
#define BUTTON2 (BIT3) // Две кнопки (SB3 и SB4), подсоединённые к P2.3
#define BUTTON3 (BIT4) // Две кнопки (SB5 и SB6), подсоединённые к P2.4
volatile char flash = 0;
volatile char flash2 = 0;
void TA_init(void);
void ADC_init(void);
//***********************Главная функция*************************
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Останавливаем сторожевой таймер
BCSCTL3 = LFXT1S1; // Источником сигнала ACLK будет низкочастотный встроенный генератор со сверхнизким
// энергопотреблением VLO. Частота ACLK = 12 кГц
P1DIR |= GREEN_LED; // Устанавливаем порт на выход
P1OUT &= ~GREEN_LED; // Отключаем диод
P1DIR |= RED_LEDS;
P1OUT &= ~RED_LEDS;
P1DIR |= SPKR;
P1REN |= SPKR; // Устанавливаем резистор подтяжки, в нашем случае он уменьшает громкость динамика в ~4раза
P1OUT &= ~SPKR;
TA_init();
ADC_init();
__bis_SR_register(GIE); // Разрешаем прерывания
while(1)
{
/*ADC10CTL0 &= ~ENC;
ADC10CTL1 = INCH_4;
ADC10CTL0 |= ENC + ADC10SC; // Если здесь снять комментарии, то мигать светодиод будет
LPM3; // только при нажатии трёх! кнопок одновременно.
ADC10CTL0 &= ~ENC; // Т.е., допустим, чтобы мигать по таймеру А0, нужно
ADC10CTL1 = INCH_3; // нажать SB1, SB3 и SB5. По отдельности они вызывают
ADC10CTL0 |= ENC + ADC10SC; // какие-то отдельные колебания, которые только складываясь
LPM3;*/ // вместе, дают желаемый сигнал.
ADC10CTL0 &= ~ENC;
ADC10CTL1 = INCH_0;
ADC10CTL0 |= ENC + ADC10SC;
LPM3;
}
}
//***********************Инициализируем АЦП*************************
void ADC_init(void)
{
ADC10CTL0 = MSC + SREF_1 + ADC10SHT_2 + REFON + ADC10ON + ADC10IE; // настраиваем и включаем АЦП, разрешаем прерывания
ADC10CTL1 = ADC10SSEL_1 + CONSEQ_0; // Буду благодарен, если кто-нибудь объянит мне, что меняет,
// и на практике делает CONSEQ, т.к. в моём случае, его изменение ни к чему не приводит.
// и я не понимаю чего люди пытаются им добиться.
ADC10AE0 |= BUTTON1 + BUTTON2 + BUTTON3; // Пины с кнопками как входы АЦП
}
//***********************Инициализируем Таймер*************************
void TA_init(void)
{
//Создаём таймер для удобного моргания через прерывания
TA0CCR0 = 56;
TA0CCR1 = 28;
TA0CCTL0 = CCIE; // Разрешаем прерывание таймера по достижении CCR0
TA0CCTL1 = OUTMOD_3 + CCIE;
TA0CTL = TASSEL_1 + MC_1 + TAIE; // ACLK, Прямой счёт
}
//***********************Инициализируем Прерывания*************************
#pragma vector = TIMER0_A0_VECTOR
__interrupt void T0_A0(void)
{
P1OUT ^= flash; // если flash == 0, светодиод не горит
// если flash == GREEN_LED, мигаем светодиодом
LPM3_EXIT;
}
#pragma vector = TIMER0_A1_VECTOR
__interrupt void T0_A1(void)
{
P1OUT ^= flash2; // если flash2 == 0, светодиод не горит
// если flash2 == GREEN_LED, мигаем светодиодом
TA0IV = 0x00; //чистим регистр вектора
LPM3_EXIT;
}
#pragma vector = ADC10_VECTOR
__interrupt void ADC10_ISR (void)
{
if (0x03FC < ADC10MEM && ADC10MEM < 0x0400) // Если нажата SB1
{
P1OUT &= ~RED_LEDS;
//flash = GREEN_LED; //мигает светодиод по таймеру A0
flash = SPKR; // или гудит динамик
flash2 = 0;
}
else if (0x025A < ADC10MEM && ADC10MEM < 0x03FA) // Если кнопки не нажаты
{
P1OUT &= ~GREEN_LED;
P1OUT &= ~RED_LEDS;
flash = 0;
flash2 = 0;
}
else if (0x0246 < ADC10MEM && ADC10MEM < 0x025A) // Если обе кнопки нажаты
{
P1OUT &= ~GREEN_LED;
P1OUT |= RED_LEDS;
flash = 0;
flash2 = 0;
}
else if (0x017F < ADC10MEM && ADC10MEM < 0x0193) // Если нажата SB2
{
P1OUT &= ~RED_LEDS;
//flash2 = GREEN_LED; //мигает светодиод по таймеру A1
flash2 = SPKR; //или гудит динамик
flash = 0;
}
LPM3_EXIT;
}
Нажмите для просмотра прикрепленного файла