|
Кнопки, таймеры, АЦП, взрыв мозга, Помогите новичку |
|
|
|
Aug 2 2013, 08:49
|
Участник

Группа: Участник
Сообщений: 39
Регистрация: 2-08-13
Пользователь №: 77 769

|
Здравствуйте! Есть у меня задачка, которую никак не могу решить. У меня есть 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; }
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 14)
|
Aug 2 2013, 12:08
|
Участник

Группа: Участник
Сообщений: 39
Регистрация: 2-08-13
Пользователь №: 77 769

|
Прошу прощения, в комментариях немного ошибся: Что делает CONSEQ я знаю, я OUTMOD имел ввиду. Добавил ещё один таймер, и сделал небольшой опрос в прерывании АЦП. Теперь работают две пары кнопок. Но какую частоту выдаёт мне TAxCCR1? Явно не ту, которую я ожидаю. Если динамик и гудит различными тонами, то светодиод ведёт себя неадекватно. (Когда вывожу на диод, то TACCR задаю, естественно, выше) CODE //Создаём ещё один таймер для удобного моргания через прерывания //TA1R = 112;// смещение относительно первого - не знаю нужно или нет TA1CCR0 = 14; // Задержка таймера для мигания TA1CCR1 = 7; TA1CCTL0 = CCIE; // Разрешаем прерывание таймера по достижении CCR0 TA1CCTL1 = OUTMOD_0 + CCIE; TA1CTL = TASSEL_1 + MC_1 + TAIE; // + TACLR; // ACLK, Прямой счёт, обнуление таймера //******************************* #pragma vector = ADC10_VECTOR __interrupt void ADC10_ISR (void) { if ((ADC10CTL1 & INCH_3) == INCH_3) { if (0x03FC < ADC10MEM && ADC10MEM < 0x0400) // Если нажата SB1 { P1OUT &= ~RED_LEDS; //flash3 = GREEN_LED; flash3 = SPKR; flash4 = 0; } else if (0x025A < ADC10MEM && ADC10MEM < 0x03FA) // Если кнопки не нажаты { P1OUT &= ~GREEN_LED; P1OUT &= ~RED_LEDS; flash3 = 0; flash4 = 0; } else if (0x0246 < ADC10MEM && ADC10MEM < 0x025A) // Если обе кнопки нажаты { P1OUT &= ~GREEN_LED; P1OUT |= RED_LEDS; flash3 = 0; flash4 = 0; } else if (0x017F < ADC10MEM && ADC10MEM < 0x0193) // Если нажата SB2 { P1OUT &= ~RED_LEDS; //flash3 = GREEN_LED; flash4 = SPKR; flash3 = 0; } } else if ((ADC10CTL1 & INCH_0) == INCH_0) { if (0x03FC < ADC10MEM && ADC10MEM < 0x0400) // Если нажата SB1 { P1OUT &= ~RED_LEDS; //flash = GREEN_LED; 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; flash2 = SPKR; flash = 0; } } LPM3_EXIT; }
|
|
|
|
|
Aug 5 2013, 05:49
|
Участник

Группа: Участник
Сообщений: 39
Регистрация: 2-08-13
Пользователь №: 77 769

|
Цитата(d7d1cd @ Aug 2 2013, 16:41)  Я может чего то не понимаю, но как микроконтроллер поймет, что нажата та или иная кнопка, каждая из которых подключена к одному и тому же пину? АЦП. При помощи него я измеряю напряжение на пине. На схеме, которую я прикрепил, видно, что напряжение будет меняться при различных вариантах нажатия. Кнопки две - варианта четыре. Это всё находится у меня в прерывании АЦП - взгляните.
|
|
|
|
|
Aug 5 2013, 07:33
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Вообще-то, на один вход АЦП можно повесить все ваши кнопки, используя резистивную матрицу Запараллелив на вход компаратора, можно будет получать прерывание по нажатию/отпусканию (но не по смене комбинации)  Статью гуглите сами. Хотя, вот она.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Aug 5 2013, 09:44
|
Участник

Группа: Участник
Сообщений: 39
Регистрация: 2-08-13
Пользователь №: 77 769

|
Цитата(MrYuran @ Aug 5 2013, 10:33)  Вообще-то, на один вход АЦП можно повесить все ваши кнопки, используя резистивную матрицу Запараллелив на вход компаратора, можно будет получать прерывание по нажатию/отпусканию (но не по смене комбинации)  Статью гуглите сами. Хотя, вот она. Это здорово, что можно повесить все, но у меня всё именно так, как на схеме, которую я приложил в самом начале. И это не исправить. Простите, из вашего ответа не пойму: АЦП или компаратор? Я понимаю, что компаратор тоже АЦП, но в моём случае это 10-битное АЦП, и в ссылке, что вы мне скинули, тоже АЦП. Там лишь небольшое упоминание о компараторе в конце. Но он не имеет регистра, в котором хранит текущее значение, которое (ADC10MEM) я так удобно сравниваю, дабы выискать нажатую кнопку))) Тогда как? Сопротивление измерять? Буду очень рад, если дообъясните) И, да, да, насчёт "прерывание по нажатию/отпусканию (но не по смене комбинации)" - Какие комбинации? Я вроде через нажатие/отпускание делаю...
|
|
|
|
|
Aug 5 2013, 10:20
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(Turbo_enot @ Aug 5 2013, 12:44)  Там лишь небольшое упоминание о компараторе в конце. Но он не имеет регистра, в котором хранит текущее значение, которое (ADC10MEM) я так удобно сравниваю, дабы выискать нажатую кнопку))) Тогда как? Сопротивление измерять? Буду очень рад, если дообъясните) И, да, да, насчёт "прерывание по нажатию/отпусканию (но не по смене комбинации)" - Какие комбинации? Я вроде через нажатие/отпускание делаю...  Компаратор фиксирует момент нажатия (переход через порог), формирует прерывание, а дальше запускается АЦП. Это альтернатива постоянному опросу.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Aug 5 2013, 10:32
|
Участник

Группа: Участник
Сообщений: 39
Регистрация: 2-08-13
Пользователь №: 77 769

|
Цитата(MrYuran @ Aug 5 2013, 13:20)  Компаратор фиксирует момент нажатия (переход через порог), формирует прерывание, а дальше запускается АЦП. Это альтернатива постоянному опросу. Идея хороша, НО: Вы имеете ввиду, если напряжение, которое фиксируется компаратором больше некоего порога, то -> АЦП прерывание, верно? Если я понял верно, ТО: у меня напряжение при нажатии 2й кнопки < напряжения при нажатии обеих кнопок < напряжения при не нажатых кнопках < напряжения при нажатой 1й. -> у меня не порог, а некие определённые значения, которые мне как раз и приходится опрашивать при помощи АЦП. Если я понял неверно, то простите мне мою тупость, и я подумаю тщательнее.
|
|
|
|
|
Aug 5 2013, 12:30
|
Участник

Группа: Участник
Сообщений: 39
Регистрация: 2-08-13
Пользователь №: 77 769

|
В принципе, проблему мне удалось решить. Все диоды мигают по-разному. Правда, с динамиками так не выходит. Всё равно пробелы в знаниях и навыках остались..
|
|
|
|
|
Aug 5 2013, 13:25
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Код ADC10CTL1 = ADC10SSEL_1 + CONSEQ_0; // Буду благодарен, если кто-нибудь объянит мне, что меняет, // и на практике делает CONSEQ, т.к. в моём случае, его изменение ни к чему не приводит. // и я не понимаю чего люди пытаются им добиться. CONSEQ - это режим выборки. От него зависит однократный/многократный запуск и распределение данных по регистрам ADC_MEM. Но поскольку здесь регистр данных всего один, назначение не столь очевидно. А вот в ADC12 забавные вещи можно делать. Например, за один проход последовательно опросить все входы и разложить данные в соответствующие регистры. Или оцифровать подряд несколько раз один вход и по прерыванию получить уже не одну, а несколько выборок, разложенных в разные регистры. Ну и всякие промежуточные комбинации. С ADC10, как я понял, подобные вещи можно делать, используя модуль DTC, который каждую выборку автоматически переносит из ADC10MEM в заданные ячейки памяти
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Aug 6 2013, 06:11
|
Участник

Группа: Участник
Сообщений: 39
Регистрация: 2-08-13
Пользователь №: 77 769

|
Цитата(MrYuran @ Aug 5 2013, 16:25)  Код ADC10CTL1 = ADC10SSEL_1 + CONSEQ_0; // Буду благодарен, если кто-нибудь объянит мне, что меняет, // и на практике делает CONSEQ, т.к. в моём случае, его изменение ни к чему не приводит. // и я не понимаю чего люди пытаются им добиться. CONSEQ - это режим выборки. От него зависит однократный/многократный запуск и распределение данных по регистрам ADC_MEM. Но поскольку здесь регистр данных всего один, назначение не столь очевидно. А вот в ADC12 забавные вещи можно делать. Например, за один проход последовательно опросить все входы и разложить данные в соответствующие регистры. Или оцифровать подряд несколько раз один вход и по прерыванию получить уже не одну, а несколько выборок, разложенных в разные регистры. Ну и всякие промежуточные комбинации. С ADC10, как я понял, подобные вещи можно делать, используя модуль DTC, который каждую выборку автоматически переносит из ADC10MEM в заданные ячейки памяти Спасибо. Надо бы внимательнее изучить ADC12. Любопытные вещи. А можете человеческим языком объяснить что OUTMOD в TACCTL1 означает?
|
|
|
|
|
Aug 6 2013, 11:56
|
Участник

Группа: Участник
Сообщений: 39
Регистрация: 2-08-13
Пользователь №: 77 769

|
Цитата(MrYuran @ Aug 6 2013, 11:03)  Означает, что можно управлять соответствующими ногами "железно" по совпадению TA и TACCRx, без входа в прерывание и соответственно без джиттера и накладных расходов. Спасибо!
|
|
|
|
|
Aug 9 2013, 09:44
|
Участник

Группа: Участник
Сообщений: 39
Регистрация: 2-08-13
Пользователь №: 77 769

|
Ребят, ещё такой вопрос: Как сделать короткий ШИМ сигнал? Нужно, чтобы динамик пикнул на секунду, одновременно с нажатием кнопки. Подскажите свои идеи, пожалуйста.
|
|
|
|
|
Aug 9 2013, 20:43
|

Группа: Участник
Сообщений: 12
Регистрация: 10-05-11
Пользователь №: 64 909

|
Цитата(Turbo_enot @ Aug 9 2013, 13:44)  Ребят, ещё такой вопрос: Как сделать короткий ШИМ сигнал? Нужно, чтобы динамик пикнул на секунду, одновременно с нажатием кнопки. Подскажите свои идеи, пожалуйста. 1. Включить ШИМ. 2. Подождать 1 сек 3. Выключить ШИМ. Как-то так наверное
|
|
|
|
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|