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

 
 
> Кнопки, таймеры, АЦП, взрыв мозга, Помогите новичку
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
 
Start new topic
Ответов
Turbo_enot
сообщение Aug 9 2013, 09:44
Сообщение #2


Участник
*

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



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





Группа: Участник
Сообщений: 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
Turbo_enot
сообщение Aug 12 2013, 06:46
Сообщение #4


Участник
*

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



Цитата(VasyaT @ Aug 9 2013, 23:43) *
1. Включить ШИМ.
2. Подождать 1 сек
3. Выключить ШИМ.
Как-то так наверное laughing.gif


Да, мне удалось. К счастью, я познакомился с командой __delay_cycles. Спасибо всем.
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Aug 12 2013, 07:21
Сообщение #5


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

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



Цитата(Turbo_enot @ Aug 12 2013, 09:46) *
Да, мне удалось. К счастью, я познакомился с командой __delay_cycles.

К несчастью, этот макрос совсем не для того, чтобы делать секундные задержки.
Так что курите дальше таймеры, системные тики и общепринятые методики отсчета временных интервалов.
К мсп430, правда, это уже никак не относится.


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


Участник
*

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



Цитата(MrYuran @ Aug 12 2013, 10:21) *
К несчастью, этот макрос совсем не для того, чтобы делать секундные задержки.
Так что курите дальше таймеры, системные тики и общепринятые методики отсчета временных интервалов.
К мсп430, правда, это уже никак не относится.


Спасибо, не курю, веду здоровый образ жизни. Ладно, шутка плоская. Я находил всевозможные способы, но для ACLK это самое ненапряжное. Да и пихать её можно куда угодно. Разве это может не относится к MSP430? Это же всё особенности её работы.
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Aug 12 2013, 11:36
Сообщение #7


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

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



Цитата(Turbo_enot @ Aug 12 2013, 13:44) *
Разве это может не относится к MSP430? Это же всё особенности её работы.

Ну вот раз уж у вас в коде встречается LPM3, то вероятно, речь идет об экономии батареек.
И в таком случае логично было бы секунду спокойно спать, вместо того чтобы молотить впустую __delay_cycles, которые к тому же будут плавать в зависимости от прерываний.
Можно настроить таймер на секундную задержку, но это не всегда возможно, да и задач много, а таймеров обычно намного меньше.
Поэтому обычно таймер настраивается на какой-нибудь типовой интервал (так называемый системный тик), а в прерывании инкрементируется переменная "системного времени" и выполняются необходимые проверки.
Это напрямую к архитектуре не относится, я это имел в виду. И вообще, лучше не привязываться к архитектурным особенностям конкретного контроллера без особых на то причин, если можно решить задачу программным способом.


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


Участник
*

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



Цитата(MrYuran @ Aug 12 2013, 14:36) *
Ну вот раз уж у вас в коде встречается LPM3, то вероятно, речь идет об экономии батареек.
И в таком случае логично было бы секунду спокойно спать, вместо того чтобы молотить впустую __delay_cycles, которые к тому же будут плавать в зависимости от прерываний.
Можно настроить таймер на секундную задержку, но это не всегда возможно, да и задач много, а таймеров обычно намного меньше.
Поэтому обычно таймер настраивается на какой-нибудь типовой интервал (так называемый системный тик), а в прерывании инкрементируется переменная "системного времени" и выполняются необходимые проверки.
Это напрямую к архитектуре не относится, я это имел в виду. И вообще, лучше не привязываться к архитектурным особенностям конкретного контроллера без особых на то причин, если можно решить задачу программным способом.


Да, вы правы, речь идёт об экономии. И, да, вы правы, таймеров намного меньше чем задач. Но на ошибках я постепенно совершенствую свой код, и стараюсь использовать ресурсы с умом. Я попробую воспользоваться вашим советом. Хотя частота тактового генератора в моём экономном случае 12кГЦ, и с ней трудно играть в точность. Мой код уже разросся, и сейчас я как раз хочу привести его в человеческий вид, увести всё что можно и где это возможно, в спячку. Не совсем понял про переменную "системного времени", я всё-таки ещё нуб в терминах.
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Aug 13 2013, 05:29
Сообщение #9


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

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



Цитата(Turbo_enot @ Aug 12 2013, 15:03) *
Не совсем понял про переменную "системного времени", я всё-таки ещё нуб в терминах.

Заводим специальную переменную, которая будет считать миллисекунды (допустим) или системные "тики".
unsigned int uiRealTime;

Настраиваем таймер на фиксированный интервал, например, 10мс.
В прерывании увеличиваем нашу переменную на величину интервала (10), получим время в мс. Или на 1, получим количество тиков.
Далее, в основной программе для каждого интервала заводим переменную-таймер.
Например:
unsigned int uiTimer1;

Засекаем временной интервал:
uiTimer1 = uiRealTime + SOME_TIME_INTERVAL;

Дальше нужно проверять, когда значение текущего времени превысит значение переменной uiTimer1.
Для экономии энергии это лучше сделать в прерывании таймера.
Далее, либо устанавливать флаг события и ловить его в основном цикле, либо выполнять действия прямо в прерывании.
Тут уже вариантов множество.


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- Turbo_enot   Кнопки, таймеры, АЦП, взрыв мозга   Aug 2 2013, 08:49
- - Turbo_enot   Прошу прощения, в комментариях немного ошибся: Что...   Aug 2 2013, 12:08
- - d7d1cd   Я может чего то не понимаю, но как микроконтроллер...   Aug 2 2013, 13:41
|- - Turbo_enot   Цитата(d7d1cd @ Aug 2 2013, 16:41) Я може...   Aug 5 2013, 05:49
- - MrYuran   Вообще-то, на один вход АЦП можно повесить все ваш...   Aug 5 2013, 07:33
|- - Turbo_enot   Цитата(MrYuran @ Aug 5 2013, 10:33) Вообщ...   Aug 5 2013, 09:44
|- - MrYuran   Цитата(Turbo_enot @ Aug 5 2013, 12:44) Та...   Aug 5 2013, 10:20
|- - Turbo_enot   Цитата(MrYuran @ Aug 5 2013, 13:20) Компа...   Aug 5 2013, 10:32
- - Turbo_enot   В принципе, проблему мне удалось решить. Все диоды...   Aug 5 2013, 12:30
- - MrYuran   КодADC10CTL1 = ADC10SSEL_1 + CONSEQ_0; // Буду бла...   Aug 5 2013, 13:25
|- - Turbo_enot   Цитата(MrYuran @ Aug 5 2013, 16:25) КодAD...   Aug 6 2013, 06:11
|- - MrYuran   Цитата(Turbo_enot @ Aug 6 2013, 09:11) А ...   Aug 6 2013, 08:03
|- - Turbo_enot   Цитата(MrYuran @ Aug 6 2013, 11:03) Означ...   Aug 6 2013, 11:56
|- - Turbo_enot   Цитата(MrYuran @ Aug 13 2013, 08:29) Засе...   Aug 13 2013, 08:04
|- - Turbo_enot   Да, кстати, вот ещё что. Создал я небольшой пример...   Aug 13 2013, 11:43
- - MrYuran   Все не так Таймер (физический) настраивается о...   Aug 13 2013, 13:09
|- - Turbo_enot   Цитата(MrYuran @ Aug 13 2013, 16:09) Все ...   Aug 13 2013, 14:20
- - Turbo_enot   Всё довольно грустно. Даже загадочно. Вот код: CO...   Aug 14 2013, 09:19
- - Turbo_enot   Ещё такой вопрос: как долго счётчик uiRealTime буд...   Aug 14 2013, 10:52
- - Turbo_enot   Буду очень благодарен, если кто-нибудь объяснит, к...   Aug 15 2013, 11:03
- - thodnev   В общем посмотрите примеры на обучающем вики от те...   Aug 16 2013, 08:02
- - Turbo_enot   Спасибо за советы, подразобрался   Aug 21 2013, 14:10


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

 


RSS Текстовая версия Сейчас: 3rd August 2025 - 16:30
Рейтинг@Mail.ru


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