реклама на сайте
подробности

 
 
> Кнопки, таймеры, АЦП, взрыв мозга, Помогите новичку
Turbo_enot
сообщение Aug 2 2013, 08:49
Сообщение #1


Участник
*

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



Здравствуйте!
Есть у меня задачка, которую никак не могу решить. У меня есть 6 кнопок (картинка прилагается), подключены они по две штуки к одному пину. Необходимо сделать так, чтобы при нажатии на каждую кнопку, происходило какое-то своё действие: светодиод мигал с разной чистотой, или динамик гудел различными тонами. И, вот, если одну пару кнопок я уже научился контролировать, то другие никак не могу. Подробности в комментариях к коду.
Сам я программировать и разбираться с МК начал меньше месяца назад. Прошу не судить строго за любые возможные глупые ляпы. Буду благодарен вам за любую помощь! Мозг уже разрывается на части wacko.gif
Прогаю в 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;
  }

Прикрепленное изображение
Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 14)
Turbo_enot
сообщение Aug 2 2013, 12:08
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 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;
}
Go to the top of the page
 
+Quote Post
d7d1cd
сообщение Aug 2 2013, 13:41
Сообщение #3


Местный
***

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



Я может чего то не понимаю, но как микроконтроллер поймет, что нажата та или иная кнопка, каждая из которых подключена к одному и тому же пину?
Go to the top of the page
 
+Quote Post
Turbo_enot
сообщение Aug 5 2013, 05:49
Сообщение #4


Участник
*

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



Цитата(d7d1cd @ Aug 2 2013, 16:41) *
Я может чего то не понимаю, но как микроконтроллер поймет, что нажата та или иная кнопка, каждая из которых подключена к одному и тому же пину?

АЦП. При помощи него я измеряю напряжение на пине. На схеме, которую я прикрепил, видно, что напряжение будет меняться при различных вариантах нажатия. Кнопки две - варианта четыре. Это всё находится у меня в прерывании АЦП - взгляните.
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Aug 5 2013, 07:33
Сообщение #5


Беспросветный оптимист
******

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



Вообще-то, на один вход АЦП можно повесить все ваши кнопки, используя резистивную матрицу
Запараллелив на вход компаратора, можно будет получать прерывание по нажатию/отпусканию (но не по смене комбинации)



Статью гуглите сами.

Хотя, вот она.


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
Turbo_enot
сообщение Aug 5 2013, 09:44
Сообщение #6


Участник
*

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



Цитата(MrYuran @ Aug 5 2013, 10:33) *
Вообще-то, на один вход АЦП можно повесить все ваши кнопки, используя резистивную матрицу
Запараллелив на вход компаратора, можно будет получать прерывание по нажатию/отпусканию (но не по смене комбинации)



Статью гуглите сами.

Хотя, вот она.


Это здорово, что можно повесить все, но у меня всё именно так, как на схеме, которую я приложил в самом начале. И это не исправить. Простите, из вашего ответа не пойму: АЦП или компаратор? Я понимаю, что компаратор тоже АЦП, но в моём случае это 10-битное АЦП, и в ссылке, что вы мне скинули, тоже АЦП. Там лишь небольшое упоминание о компараторе в конце. Но он не имеет регистра, в котором хранит текущее значение, которое (ADC10MEM) я так удобно сравниваю, дабы выискать нажатую кнопку))) Тогда как? Сопротивление измерять? Буду очень рад, если дообъясните)
И, да, да, насчёт "прерывание по нажатию/отпусканию (но не по смене комбинации)" - Какие комбинации? Я вроде через нажатие/отпускание делаю... sad.gif
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Aug 5 2013, 10:20
Сообщение #7


Беспросветный оптимист
******

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



Цитата(Turbo_enot @ Aug 5 2013, 12:44) *
Там лишь небольшое упоминание о компараторе в конце. Но он не имеет регистра, в котором хранит текущее значение, которое (ADC10MEM) я так удобно сравниваю, дабы выискать нажатую кнопку))) Тогда как? Сопротивление измерять? Буду очень рад, если дообъясните)
И, да, да, насчёт "прерывание по нажатию/отпусканию (но не по смене комбинации)" - Какие комбинации? Я вроде через нажатие/отпускание делаю... sad.gif

Компаратор фиксирует момент нажатия (переход через порог), формирует прерывание, а дальше запускается АЦП.
Это альтернатива постоянному опросу.


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
Turbo_enot
сообщение Aug 5 2013, 10:32
Сообщение #8


Участник
*

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



Цитата(MrYuran @ Aug 5 2013, 13:20) *
Компаратор фиксирует момент нажатия (переход через порог), формирует прерывание, а дальше запускается АЦП.
Это альтернатива постоянному опросу.


Идея хороша, НО:
Вы имеете ввиду, если напряжение, которое фиксируется компаратором больше некоего порога, то -> АЦП прерывание, верно?
Если я понял верно, ТО: у меня напряжение при нажатии 2й кнопки < напряжения при нажатии обеих кнопок < напряжения при не нажатых кнопках < напряжения при нажатой 1й. -> у меня не порог, а некие определённые значения, которые мне как раз и приходится опрашивать при помощи АЦП.
Если я понял неверно, то простите мне мою тупость, и я подумаю тщательнее.
Go to the top of the page
 
+Quote Post
Turbo_enot
сообщение Aug 5 2013, 12:30
Сообщение #9


Участник
*

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



В принципе, проблему мне удалось решить. Все диоды мигают по-разному. Правда, с динамиками так не выходит. Всё равно пробелы в знаниях и навыках остались..
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Aug 5 2013, 13:25
Сообщение #10


Беспросветный оптимист
******

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



Код
ADC10CTL1 = ADC10SSEL_1 + CONSEQ_0; // Буду благодарен, если кто-нибудь объянит мне, что меняет,
                                      // и на практике делает CONSEQ, т.к. в моём случае, его изменение ни к чему не приводит.
                                      // и я не понимаю чего люди пытаются им добиться.

CONSEQ - это режим выборки. От него зависит однократный/многократный запуск и распределение данных по регистрам ADC_MEM.
Но поскольку здесь регистр данных всего один, назначение не столь очевидно. А вот в ADC12 забавные вещи можно делать. Например, за один проход последовательно опросить все входы и разложить данные в соответствующие регистры. Или оцифровать подряд несколько раз один вход и по прерыванию получить уже не одну, а несколько выборок, разложенных в разные регистры. Ну и всякие промежуточные комбинации.
С ADC10, как я понял, подобные вещи можно делать, используя модуль DTC, который каждую выборку автоматически переносит из ADC10MEM в заданные ячейки памяти


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
Turbo_enot
сообщение Aug 6 2013, 06:11
Сообщение #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 означает? a14.gif
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Aug 6 2013, 08:03
Сообщение #12


Беспросветный оптимист
******

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



Цитата(Turbo_enot @ Aug 6 2013, 09:11) *
А можете человеческим языком объяснить что OUTMOD в TACCTL1 означает? a14.gif

Означает, что можно управлять соответствующими ногами "железно" по совпадению TA и TACCRx, без входа в прерывание и соответственно без джиттера и накладных расходов.


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
Turbo_enot
сообщение Aug 6 2013, 11:56
Сообщение #13


Участник
*

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



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


Спасибо!
Go to the top of the page
 
+Quote Post
Turbo_enot
сообщение Aug 9 2013, 09:44
Сообщение #14


Участник
*

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



Ребят, ещё такой вопрос: Как сделать короткий ШИМ сигнал? Нужно, чтобы динамик пикнул на секунду, одновременно с нажатием кнопки. Подскажите свои идеи, пожалуйста.
Go to the top of the page
 
+Quote Post
VasyaT
сообщение Aug 9 2013, 20:43
Сообщение #15





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



Цитата(Turbo_enot @ Aug 9 2013, 13:44) *
Ребят, ещё такой вопрос: Как сделать короткий ШИМ сигнал? Нужно, чтобы динамик пикнул на секунду, одновременно с нажатием кнопки. Подскажите свои идеи, пожалуйста.

1. Включить ШИМ.
2. Подождать 1 сек
3. Выключить ШИМ.
Как-то так наверное laughing.gif
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 31st July 2025 - 13:36
Рейтинг@Mail.ru


Страница сгенерированна за 0.01455 секунд с 7
ELECTRONIX ©2004-2016