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

 
 
> Кнопки, таймеры, АЦП, взрыв мозга, Помогите новичку
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 14 2013, 09:19
Сообщение #2


Участник
*

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



Всё довольно грустно. Даже загадочно. Вот код:

CODE
void delay_ms(uint16_t ms);
void InitSystem(void);

#pragma vector = TIMER0_A0_VECTOR
__interrupt void T0_A0(void)
{
uiRealTime += 1;
if (uiRealTime < uiTimer1)
{
P1OUT ^= SPKR;
}
}
// Задержка в мииллисекундах
void delay_ms(uint16_t ms)
{
static uint16_t delay_timer;

delay_timer = uiRealTime + ms;

while(uiRealTime < delay_timer);

}

// Инициализация системы
void InitSystem(void)
{
WDTCTL = WDTPW + WDTHOLD; // Останавливаем собаку

// Инициализируем ACLK
BCSCTL3 = LFXT1S_2;

// Устанавливаем источник частоты для таймера Timer_A
TACCR0 = 11; // (12 kHz / TACCR + 1) = 1 kHz, T = 1 мc
TA0CCTL0 = CCIE; // Разрешаем прерывание таймера по достижении CCR0
TA0CTL |= TASSEL_1 + MC_1 + TACLR; // (ACLK) = 12 kHz
}

//***********************Главная функция*************************

void main(void)
{
InitSystem();
P1DIR &= ~BUTTON3;
P1IES = BUTTON3;
P1IE = BUTTON3;
P1DIR |= SPKR;
P1REN |= SPKR;
P1OUT &= ~SPKR;
__bis_SR_register(GIE);
while (1)
{

}
}

#pragma vector = PORT1_VECTOR
__interrupt void P1_isr(void)
{
P1IFG &= ~BUTTON3;
uiTimer1 = uiRealTime + 1000;
//delay_ms(1000); // от дребезга
}


Под SPKR понимается выход на динамик, с которого я осциллографом снимаю импульсы. Я исправил код, но результат очень странный: если проверяю на подключённой по JTAG плате, то при нажатии кнопки как надо инициируется секундный писк. ОДНАКО, после некоторого времени тишины, писк неожиданно самопроизвольно включается вновь, но уже на БОЛЕЕ длительное время, и так же внезапно отключается. Если плата отключена, то писк срабатывает только при первом нажатии, а затем уходит в глухую оборону... Думаю факт подключения здесь особую роль не играет, а просто я опять где-то накосячил и чего-то не понял. А функция delay_ms, вроде как уходит в бесконечный цикл, после строчки while(uiRealTime < delay_timer); И если я её (функцию delay_ms) добавляю в конце своего кода, то, соответственно, ничего не происходит. help.gif

Прошу прощения, ступил. Никто за меня переменную uiTimer1 не обнулил, вот полтергейст и возникал. biggrin.gif
CODE
#pragma vector = TIMER0_A0_VECTOR
__interrupt void T0_A0(void)
{
uiRealTime += 1;
if (uiRealTime < uiTimer1)
{
P1OUT ^= SPKR;
}
else
uiTimer1 = 0; // Вот, обнулил её здесь, теперь ничего без моего нажатия не гудит
}


Хотя не совсем понимаю, как она могла влезать в неравенство if (uiRealTime < uiTimer1)

А вот вопрос с delay_ms остаётся открытым. Там наверняка тоже всё на поверхности лежит, только я не догнал ещё.

Раньше я делал так:

Был у меня таймер

CODE
TA1CCR0 = 6; // Частота писка = (12000/TA1CCR0+1)
TA1CTL = TASSEL_1 + MC_1 + TACLR; // ACLK, Прямой счёт, обнуление таймера


И, был следующий код:

CODE
if (m >= 0) //Если выполняется условие
{
TA1CCTL0 = CCIE; // Разрешаем прерывание таймера
__delay_cycles(50000);
flash3 = SPKR;
}


Возникало прерывание:

CODE
#pragma vector = TIMER1_A0_VECTOR // Прерывания таймера на динамик
__interrupt void T1_A0(void)
{
if (l == 200) // Если моргнули 200 раз
{
TA1CCTL0 &= ~CCIE; // Запрещаем прерывания (писк)
flash3 = 0; // Говорим, что flash3 уже не спикер
P1OUT &= ~SPKR; // Спикер отключаем
l = 0; // Обнуляем кол-во морганий сигналами
}
if (flash3 == SPKR) // если flash3 == SPKR,
{
P1OUT ^= flash3; // мигаем сигналом

l++; // Говорим, что моргнули сигналом очередной раз
}
LPM3_EXIT;
}


Сейчас разбираюсь с системными тиками, и мне всё больше кажется, что они так не смогут, ведь тогда мне нужны часы - 1 таймер, определённая частота гудения - второй таймер, а ведь у меня в проге ещё и светодиоды разной частотой мигают. Если только при помощи этих системных таймеров возможно будет этими светодиодами управлять (менять их частоту мигания). Я уже как-то совсем запутался sad.gif wacko.gif Может у меня всё хорошо было для моего случая
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   Ребят, ещё такой вопрос: Как сделать короткий ШИМ ...   Aug 9 2013, 09:44
|- - VasyaT   Цитата(Turbo_enot @ Aug 9 2013, 13:44) Ре...   Aug 9 2013, 20:43
|- - Turbo_enot   Цитата(VasyaT @ Aug 9 2013, 23:43) 1. Вкл...   Aug 12 2013, 06:46
|- - MrYuran   Цитата(Turbo_enot @ Aug 12 2013, 09:46) Д...   Aug 12 2013, 07:21
|- - Turbo_enot   Цитата(MrYuran @ Aug 12 2013, 10:21) К не...   Aug 12 2013, 10:44
|- - MrYuran   Цитата(Turbo_enot @ Aug 12 2013, 13:44) Р...   Aug 12 2013, 11:36
|- - Turbo_enot   Цитата(MrYuran @ Aug 12 2013, 14:36) Ну в...   Aug 12 2013, 12:03
|- - MrYuran   Цитата(Turbo_enot @ Aug 12 2013, 15:03) Н...   Aug 13 2013, 05:29
|- - 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   Ещё такой вопрос: как долго счётчик 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 Текстовая версия Сейчас: 6th August 2025 - 18:43
Рейтинг@Mail.ru


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