Например TDA7294

Форум РадиоКот • Просмотр темы - MSP430 Генерация пачки импульсов при помощи таймера А
Форум РадиоКот
Здесь можно немножко помяукать :)





Текущее время: Пт апр 19, 2024 02:57:21

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 41 ]    , 2,  
Автор Сообщение
Не в сети
 Заголовок сообщения: Re: MSP430 Генерация пачки импульсов при помощи таймера А
СообщениеДобавлено: Вт май 16, 2017 19:58:14 
Друг Кота
Аватар пользователя

Карма: 74
Рейтинг сообщений: 607
Зарегистрирован: Ср дек 24, 2008 09:58:58
Сообщений: 3715
Рейтинг сообщения: 0
Медали: 3
Мявтор 1-й степени (1) Мявтор 2-й степени (1) Мявтор 3-й степени (1)
Цикл while, в данном конкретном случае, не нужен, если только МК не будет делать еще что-то.
Следовало-бы проиниацилизировать переменные pauseCnt и pulseCnt их соответствующими значениями из дефайном в начале кода в функции настройки таймера.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: MSP430 Генерация пачки импульсов при помощи таймера А
СообщениеДобавлено: Вт май 16, 2017 20:03:47 
Первый раз сказал Мяу!

Зарегистрирован: Чт апр 06, 2017 16:59:44
Сообщений: 25
Рейтинг сообщения: 0
Вот полностью весь код:

#include "msp430f149.h"

#define PULSE_CNT 5 // # of pulses in a burst
#define PAUSE_CNT 10 // pause duration

void Ports_config();
void TimerA_config();
char timerMode; // 0: burst, 1:pause
char pulseCnt, pauseCnt;

void wait( volatile int i ){
while ( i-- > 0 );
}

void Ports_config()
{
P1SEL = BIT6; // assign P1.2 to TimerA
P1DIR = BIT6;
P1DIR |= BIT0;
P1SEL|=BIT0;
P1DIR &= ~BIT0;
}
void flash() {
P1OUT = 0x01;
wait((int)5000);
P1OUT &= ~0x01;
wait((int)10000);
}
void TimerA_config()
{
TA0CCR0 = 18;
TA0CCR1 = 10;
TA0CCTL1 = OUTMOD_7;
TA0CTL = TASSEL_2 + MC_1 + TACLR + TAIE;
timerMode = 0;
}

#pragma vector=TIMER0_A1_VECTOR // TimerA handler
__interrupt void TimerA_ISR(void)
{

(TACTL & TAIFG)==0;
// TA0CTL_bit.TAIFG = 0; // clear TimerA interrupt
if (timerMode)
{

if (!(--pauseCnt)) // pause is over is complete
{

pauseCnt = PAUSE_CNT; // restore pause counter
timerMode = 0; // switch to the other mode
TACCTL1 = OUTMOD_7; // toggle mode
}
}
else
{
if (!(--pulseCnt)) // burst is complete
{

pulseCnt = PULSE_CNT; // restore pulse counter
timerMode = 1; // switch to the other mode
TACCTL1 = OUTMOD_5; // reset mode
}
}
}
int main()
{
WDTCTL = WDTPW + WDTHOLD; // stop watchdog timer
//Clock_config(); // set 8 MHz MSCK, 2 MHz SMCLK
Ports_config(); // set up ports for GPIO
TimerA_config(); // configure TimerA module for 40 KHz

__enable_interrupt(); // enable interrupts globally
__low_power_mode_0(); // wait for char receive

while(1)
{
__no_operation();
}
}

А если во время паузы необходимо включать таймер B в режиме захвата, необходимо в прерывании добавить или в main?


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: MSP430 Генерация пачки импульсов при помощи таймера А
СообщениеДобавлено: Вт май 16, 2017 20:25:42 
Друг Кота
Аватар пользователя

Карма: 74
Рейтинг сообщений: 607
Зарегистрирован: Ср дек 24, 2008 09:58:58
Сообщений: 3715
Рейтинг сообщения: 0
Медали: 3
Мявтор 1-й степени (1) Мявтор 2-й степени (1) Мявтор 3-й степени (1)
Не понял зачем его вообще включать для данного приложения? В коде прерывание происходит каждый раз по достижении счетчиком таймера его максимального значения. Вопрос первоначально был как обойтись одним таймером. Чего хотите добиться сейчас, задействовав второй таймер?


Вернуться наверх
 
PCBWay - всего $5 за 10 печатных плат, первый заказ для новых клиентов БЕСПЛАТЕН

Сборка печатных плат от $30 + БЕСПЛАТНАЯ доставка по всему миру + трафарет

Онлайн просмотровщик Gerber-файлов от PCBWay + Услуги 3D печати
Не в сети
 Заголовок сообщения: Re: MSP430 Генерация пачки импульсов при помощи таймера А
СообщениеДобавлено: Вт май 16, 2017 21:06:00 
Первый раз сказал Мяу!

Зарегистрирован: Чт апр 06, 2017 16:59:44
Сообщений: 25
Рейтинг сообщения: 0
Вообще задача в том, чтобы отправлять с таймера А пачку импульсов и принимать пришедший сигнал на таймер В.

Решила постепенно разбираться.
Сейчас мне не понятно, почему в прерывании не выполняются условия.
Также есть вопрос, как добавить в данный код работу таймера В.

Есть еще вопрос почему код по захвату у меня не заходит в прерывание:
void main(void)
{
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer

P4DIR &= ~BIT0;
P4SEL |= BIT0;

timerB_init();
__bis_SR_register(LPM0_bits + GIE); // LPM0 + Enable global ints
}

void timerB_init()
{
TBCCTL0=CM_1+SCS+CCIS_1+CAP+CCIE;
TBCTL=MC_2+TBSSEL_2;
}

#pragma vector = TIMERB0_VECTOR
__interrupt void TIMERB0_VECTOR_ISR (void)
{
__no_operation();
}

Да и почему-то записывает не в те регистры флаг прерывания.


Вернуться наверх
 
Выбираем схему BMS для заряда литий-железофосфатных (LiFePO4) аккумуляторов

Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.

Подробнее>>
Не в сети
 Заголовок сообщения: Re: MSP430 Генерация пачки импульсов при помощи таймера А
СообщениеДобавлено: Ср май 17, 2017 02:54:59 
Друг Кота
Аватар пользователя

Карма: 74
Рейтинг сообщений: 607
Зарегистрирован: Ср дек 24, 2008 09:58:58
Сообщений: 3715
Рейтинг сообщения: 0
Медали: 3
Мявтор 1-й степени (1) Мявтор 2-й степени (1) Мявтор 3-й степени (1)
Цитата:
почему код по захвату у меня не заходит в прерывание

Потому что таймер стоит и не считает. Запишите значение МС_1 в TBCTL. Кроме того, TBCL0=0 дефолтно и для запуска таймера там должно быть ненулевое значение. Ну и ещё этот таймер, согласно конфигурации тактируется от ACLK. Чему равна эта частота (из кода определить это невозможно)?

Остальные вопросы я не понял. Что значит "принимать пришедший сигнал на таймер В"? И какие условия должны выполняться в прерывании (сейчас там никаких условий не проверяется)?

Напишите нормально что надо сделать, я не телепат. Если это студенческая методичка, лучше выложите её сюда полностью. Кроме того, какие имеете средства отладки (FET debugger? Лог. анализатор? Среда разработки?). Если у Вас демо-плата с MSP430, что за плата.


Вернуться наверх
 
Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.

Подробнее>>
Не в сети
 Заголовок сообщения: Re: MSP430 Генерация пачки импульсов при помощи таймера А
СообщениеДобавлено: Ср май 17, 2017 08:59:42 
Первый раз сказал Мяу!

Зарегистрирован: Чт апр 06, 2017 16:59:44
Сообщений: 25
Рейтинг сообщения: 0
Задача в том, чтобы отправлять пачку импульсов с таймера А на ультразвуковой датчик, излучать, а затем принимать усиленный отраженный сигнал на вход таймера В.

Прерывания таймера В должны происходить тогда, когда на вход его поступает отраженный сигнал. Нужно выводить время с начала запуска таймера В и захвата сигнала. Также останавливать таймер и запускать заново после расчета времени.

Вообще я тактирую от SMCLK (TBSELL_2) ибо когда пыталась от ACLK таймер В не считал.

Среда разработки - code composer studio.
Демо платы нет, есть схема с микроконтроллером msp430f149. Средство отладки - FET debugger.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: MSP430 Генерация пачки импульсов при помощи таймера А
СообщениеДобавлено: Ср май 17, 2017 19:11:32 
Друг Кота
Аватар пользователя

Карма: 74
Рейтинг сообщений: 607
Зарегистрирован: Ср дек 24, 2008 09:58:58
Сообщений: 3715
Рейтинг сообщения: 0
Медали: 3
Мявтор 1-й степени (1) Мявтор 2-й степени (1) Мявтор 3-й степени (1)
В прошлый раз я был не прав с советами. Теперь задачу понял. Вот рабочий код использования Таймера для захвата. Он измеряет длительность нажатия кнопки, подсоединённой между P1.1 и землёй. Для этого в P1.1 задействован внутренний подтягивающий резистор. Только что протестил его на макетке при тактировании таймера от ACLK. Код работает с Таймером А, т.к. в моём МК G2553 нет Таймера B, однако работа с последним полностью аналогична. В принципе, код работы с таймером у Вас был правильный. Следует только сбрасывать флаг прерывания в ISR.
Спойлер
Код:
#include "io430.h"

void Clock_config();            // function prototypes
void Ports_config();
void TimerA_config();
unsigned int lastCapture;
unsigned int duration;             // button press duration

int main()
{
     WDTCTL = WDTPW + WDTHOLD;      // stop watchdog timer
   Clock_config();            // set 8 MHz MSCK, 2 MHz SMCLK
   Ports_config();            // set up ports for GPIO
   TimerA_config();            // configure TimerA module capture
     __enable_interrupt();         // enable interrupts globally
   
   while(1)
   {
      __low_power_mode_0();      // wait for capture
        __no_operation();           
      __no_operation();           // set breakpoint here to examine duration
   }
}

void Clock_config()            // configure basic clock module
{
   DCOCTL = CALDCO_8MHZ;         // set 8 MHz MCLK
   BCSCTL1 = CALBC1_8MHZ;
   BCSCTL2 = DIVS_1;
   BCSCTL3 = LFXT1S1;         // select VLO as ACLK 
}

void Ports_config()
{
     P1SEL = P1;               // assign P1.1 to TimerA input
   P1DIR &= ~P1;            // and configure it for capture
   P1REN = P1;               // enable pull-up resistor
   P1OUT = P1;
}

void TimerA_config()
{
   TA0CCTL0 = CM_3 | SCS | CAP | CCIE;
   TA0CTL = TASSEL_1 + MC_2 + TACLR;
}

#pragma vector=TIMER0_A0_VECTOR      // TimerA handler
__interrupt void TimerA_ISR(void)
{
     if (P1IN & P1)            // button is released
   {
      duration = TACCR0 - lastCapture;
      __low_power_mode_off_on_exit();
   }   
   lastCapture = TACCR0;
   TA0CCTL0_bit.CCIFG = 0;         // clear TimerA capture
}   


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: MSP430 Генерация пачки импульсов при помощи таймера А
СообщениеДобавлено: Ср май 17, 2017 22:27:23 
Первый раз сказал Мяу!

Зарегистрирован: Чт апр 06, 2017 16:59:44
Сообщений: 25
Рейтинг сообщения: 0
Большое спасибо за листинг!

В данном примере
#pragma vector=TIMER0_A0_VECTOR // TimerA handler
__interrupt void TimerA_ISR(void)
{
if (P1IN & P1) // button is released
{
duration = TACCR0 - lastCapture;
__low_power_mode_off_on_exit();
}
lastCapture = TACCR0;
TA0CCTL0_bit.CCIFG = 0; // clear TimerA capture
}
есть условие if (P1IN & P1) , а если не использовать кнопку, то условие должно быть: что если CAP ==1? или просто if(CCIFG)?


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: MSP430 Генерация пачки импульсов при помощи таймера А
СообщениеДобавлено: Чт май 18, 2017 00:19:30 
Друг Кота
Аватар пользователя

Карма: 74
Рейтинг сообщений: 607
Зарегистрирован: Ср дек 24, 2008 09:58:58
Сообщений: 3715
Рейтинг сообщения: 0
Медали: 3
Мявтор 1-й степени (1) Мявтор 2-й степени (1) Мявтор 3-й степени (1)
Не нужно там никакого условия. Вход в обработчик прерывания произойдёт как только совершится захват.
Кстати, я вспомнил, что у меня есть MSP430FR5730 с Таймером B и адаптировал код для IAR под него.
Спойлер
Код:
#include "io430.h"

void Clock_config();            // function prototypes
void Ports_config();
void TimerB_config();
unsigned int lastCapture;
unsigned int duration;             // button press duration

int main()
{
     WDTCTL = WDTPW + WDTHOLD;      // stop watchdog timer
   REFCTL0_L |= REFTCOFF;         // disable temp sensor
   Ports_config();               // set up ports for GPIO
   Clock_config();               // set 8 MHz MSCK, 1 MHz SMCLK
   TimerB_config();            // configure TimerB module capture
     __enable_interrupt();         // enable interrupts globally
   
   while(1)
   {
      __low_power_mode_0();      // wait for capture
        __no_operation();           
      __no_operation();           // set breakpoint here to examine duration
   }
}

void Clock_config()               // configure clock system
{
     CSCTL0_H = CSKEY_H;            // unlock the clock interface
     CSCTL4_L = XT1DRIVE1;         // crystal drive level
    while (SFRIFG1_L & OFIFG)      // wait for 32KHz oscillator to start
   {
        CSCTL5_L &= ~XT1OFFG;      // clear XT1 fault flag
      SFRIFG1_L &= ~OFIFG;      // clear oscillator fault flag 
   }
   CSCTL3 = DIVS_3;                    // set 8 MHz MCLK, SMCLK
}

void Ports_config()
{
     P2DIR_bit.P2DIR1 = 0;         // assign P2.1 to TimerB input
   P2REN_bit.P2REN1 = 1;         // enable pull-up resistor on P2.1
   P2OUT_bit.P2OUT1 = 1;
   P2IES_bit.P2IES1 = 1;         // enable button falling edge interrupt
   P2IE_bit.P2IE1 = 1;            // enable button interrupt
   P2IFG_bit.P2IFG1 = 0;         // clear interrupt flag
   PJSEL0_L = PJSEL0_4 | PJSEL0_5;   // config Xtal pins for X1OSC
}

void TimerB_config()
{
   TB0CCTL0 = CM_1 | SCS | CAP | CCIE;
}

#pragma vector=PORT2_VECTOR         // PORT2 handler
__interrupt void PORT2_ISR(void)
{
     if (P2IFG & PAIFG1)            // button interrupt?
   {
        TB0CTL = TASSEL_1 + MC_2 + TBCLR; // start capture
      lastCapture = 0;
        P2IE_bit.P2IE1 = 0;         // disable button interrupt
      P2SEL1_bit.P2SEL1_1 = 1;   // reassign button for TimerB   
      P2SEL0_bit.P2SEL0_1 = 1;    
        P2IFG_bit.P2IFG1 = 0;      // clear interrupt flag
   }   


#pragma vector=TIMER0_B0_VECTOR      // TimerB handler
__interrupt void TimerB_ISR(void)
{
     P2SEL1_bit.P2SEL1_1 = 0;      // reassign button to GPIO   
   P2SEL0_bit.P2SEL0_1 = 0;
   P2IE_bit.P2IE1 = 1;            // enable button interrupt
   P2IFG_bit.P2IFG1 = 0;         // clear button interrupt flag
   
   TB0CTL = 0;                  // stop capture   
     duration = TB0CCR0 - lastCapture;
   lastCapture = TB0CCR0;
   TB0CCTL0_bit.CCIFG = 0;         // clear TimerB capture flag
   __low_power_mode_off_on_exit(); // wake up CPU on exit
}   

В схеме помимо МК есть кнопка между выводом P2.1 и землёй. Таймер Б изначально остановлен и программа ожидает прерывания по спаду уровня на P2.1, которое происходит по нажатии на кнопку. Как произойдёт нажатие, пин P2.1 переконфигурируется на работу с модулем захвата канала 0 Таймера Б и сам таймер запускается в режим захвата по нарастающему уровню сигнала на P2.1, который образуется по отпускании кнопки. Как только захват произойдёт, таймер останавливается, кнопка переконфигугируется на GPIO и весь процесс повторяется. В этом примере Таймер Б тактируется от кварцевого генератора XT1 на порте J, стабилизированным часовым кристаллом. Код проверен в железе и работоспособность его гарантируется.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: MSP430 Генерация пачки импульсов при помощи таймера А
СообщениеДобавлено: Чт май 18, 2017 21:53:18 
Первый раз сказал Мяу!

Зарегистрирован: Чт апр 06, 2017 16:59:44
Сообщений: 25
Рейтинг сообщения: 0
А не могли бы Вы объяснить, почему при выполнении кода пошагово, все застревает в прерывании Таймера А? Что-то я забыла добавить?

#include "msp430f149.h"

#define PULSE_CNT 5 // # of pulses in a burst
#define PAUSE_CNT 10 // pause duration

void Ports_config();
void TimerA_config();
char timerMode; // 0: burst, 1:pause
char pulseCnt, pauseCnt;
unsigned int lastCapture;
unsigned int duration;

void Ports_config()
{
P1SEL = BIT6; // assign P1.2 to TimerA
P1DIR = BIT6;
P4SEL = BIT0; //timer B
P4DIR &= ~BIT0;
P1DIR |= BIT0;
P1SEL|=BIT0;
P1DIR &= ~BIT0;
}

void TimerA_config()
{
TA0CCR0 = 18;
TA0CCR1 = 7;
TA0CCTL1 = OUTMOD_7;
TA0CTL = TASSEL_2 + MC_1 + TACLR + TAIE;
timerMode = 0;
}
void TimerB_config()
{
TB0CCTL0 = CM_3 | SCS | CAP | CCIE;
TB0CTL = TBSSEL_1 + MC_2 + TBCLR;
}
//————————Timer A interrupt——————
#pragma vector=TIMER0_A1_VECTOR // TimerA handler
__interrupt void TimerA_ISR(void)
{
(TACTL & TAIFG) == 0;
// TA0CTL_bit.TAIFG = 0; // clear TimerA interrupt
if (timerMode)
{
if (!(--pauseCnt)) // pause is over is complete
{
pauseCnt = PAUSE_CNT; // restore pause counter
timerMode = 0; // switch to the other mode
TACCTL1 = OUTMOD_7; // toggle mode
}
}
else
{
if (!(--pulseCnt)) // burst is complete
{
pulseCnt = PULSE_CNT; // restore pulse counter
timerMode = 1; // switch to the other mode
TACCTL1 = OUTMOD_5; // reset mode
}
}
}
//————————Timer B interrupt——————
#pragma vector=TIMERB0_VECTOR // TimerB handler
__interrupt void TimerB_ISR(void)
{
if(TBR < 300)
P1OUT &= ~BIT0;
lastCapture = 0;
TB0CTL = 0; // stop capture
duration = TB0CCR0 - lastCapture;
lastCapture = TB0CCR0;

__low_power_mode_off_on_exit(); // wake up CPU on exit
}
int main()
{
WDTCTL = WDTPW + WDTHOLD; // stop watchdog timer
Ports_config(); // set up ports for GPIO
TimerA_config(); // configure TimerA module for 40 KHz
TimerB_config();
__enable_interrupt(); // enable interrupts globally
__low_power_mode_0(); // wait for char receive
}


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: MSP430 Генерация пачки импульсов при помощи таймера А
СообщениеДобавлено: Чт май 18, 2017 22:06:10 
Друг Кота
Аватар пользователя

Карма: 74
Рейтинг сообщений: 607
Зарегистрирован: Ср дек 24, 2008 09:58:58
Сообщений: 3715
Рейтинг сообщения: 0
Медали: 3
Мявтор 1-й степени (1) Мявтор 2-й степени (1) Мявтор 3-й степени (1)
Нужно раскомментить строку где сбрасывается флаг прерывания ТаймераА в его обработчике, если синтакс позволяет. Как написано сделано неправильно. Попробуйте так: TACTL &= ~TAIFG;


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: MSP430 Генерация пачки импульсов при помощи таймера А
СообщениеДобавлено: Чт май 18, 2017 22:25:02 
Первый раз сказал Мяу!

Зарегистрирован: Чт апр 06, 2017 16:59:44
Сообщений: 25
Рейтинг сообщения: 0
Исправила, но все равно зациклился в обработчике(


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: MSP430 Генерация пачки импульсов при помощи таймера А
СообщениеДобавлено: Чт май 18, 2017 22:38:52 
Друг Кота
Аватар пользователя

Карма: 74
Рейтинг сообщений: 607
Зарегистрирован: Ср дек 24, 2008 09:58:58
Сообщений: 3715
Рейтинг сообщения: 0
Медали: 3
Мявтор 1-й степени (1) Мявтор 2-й степени (1) Мявтор 3-й степени (1)
Я не пишу под CCS и не знаю его синтаксиса. Нужно добиться сброса флага прерывания в отладчике. При пошаговой отладке в пока находитесь в прерывании после сброса флага может сгенерироваться новое и тогда отладка зациклится. Лучше отладчиком пошагово в прерывание не заходить. Вообще, зачем пошагово отлаживаете? Убирайте здесь длинные листинги под спойлер и пользуйтесь тагом "код". Там хоть какое-то форматирование текста есть.

Добавлено позже:
Для гарантированного сброса флага таймера А, независимо от того как в CCS определена константа TAIFG, напишите:
TACTL &= 0xFFFE;
Причина невыхода из прерывания Таймера А ещё и в том, что при выходе из прерывания состояние процессора восстанавливается таким, которым оно было до входа. А поскольку в main() процессор помещается в сон, то и пробуждаться по выходу из обработчика он не будет.

Посмотрев Ваш код подробнее не обнаружил там сброса флага Таймера Б - тогда код и там циклится будет, принимая во внимание, что приоритет таймера Б выше, чем А. В моём коде выше для этого была строчка:
TB0CCTL0_bit.CCIFG = 0;
Кроме того, если в конце обработчика таймера Б стоит
__low_power_mode_off_on_exit();
то куда будет выход по пробуждении, если в main() нет цикла?

Я модифицировал свой код, следуя Вашему. У меня он выходит в main() там где указано установить breakpoint. Для этого я подсоединил выход PWM (у меня Р1.0) к входу захвата Таймера Б (Р2.1). Только смысла я в нём не вижу. Захват будет& происходить по первому фронту импульса PWM и переменная duration будет всегда принимать разные значения, что и подтверждается на практике.

Спойлер
Код:
#include "io430.h"
#define PULSE_CNT 5               // # of pulses in a burst
#define PAUSE_CNT 10            // pause duration

void Clock_config();            // function prototypes
void Ports_config();
void TimerA_config();
void TimerB_config();
unsigned int lastCapture;
unsigned int duration;             // button press duration
char timerMode;                  // 0: burst, 1:pause
char pulseCnt, pauseCnt;

int main()
{
     WDTCTL = WDTPW + WDTHOLD;      // stop watchdog timer
   REFCTL0_L |= REFTCOFF;         // disable temp sensor
   Ports_config();               // set up ports for GPIO
   Clock_config();               // set 8 MHz MSCK, 1 MHz SMCLK
   TimerA_config();            // configure TimerA module for PWM
   TimerB_config();            // configure TimerB module capture
   
   while(1)
   {
      __low_power_mode_0();      // wait for capture
        __no_operation();           
      __no_operation();           // set breakpoint here to examine duration
   }
}

void Clock_config()               // configure clock system
{
     CSCTL0_H = CSKEY_H;            // unlock the clock interface
     CSCTL4_L = XT1DRIVE1;         // crystal drive level
    while (SFRIFG1_L & OFIFG)      // wait for 32KHz oscillator to start
   {
        CSCTL5_L &= ~XT1OFFG;      // clear XT1 fault flag
      SFRIFG1_L &= ~OFIFG;      // clear oscillator fault flag 
   }
   CSCTL3 = DIVS_3;                // set 8 MHz MCLK/1MHz SMCLK
}

void Ports_config()
{
 
    P1SEL1_bit.P1SEL1_0 = 0;      // assign P1.0 to TimerA0.1
   P1SEL0_bit.P1SEL0_0 = 1;
   P1DIR_bit.P1DIR0 = 1;
   P2SEL1_bit.P2SEL1_1 = 1;      // assign button for TimerB   input
   P2SEL0_bit.P2SEL0_1 = 1;    
//    P2DIR_bit.P2DIR1 = 0;         // assign P2.1 to GPIO
//   P2REN_bit.P2REN1 = 1;         // enable pull-up resistor on P2.1
//   P2OUT_bit.P2OUT1 = 1;
//   P2IES_bit.P2IES1 = 1;         // enable button falling edge interrupt
//   P2IE_bit.P2IE1 = 1;            // enable button interrupt
//   P2IFG_bit.P2IFG1 = 0;         // clear interrupt flag
   PJSEL0_L = PJSEL0_4 | PJSEL0_5;   // config Xtal pins for X1OSC
}

void TimerA_config()
{
   TA0CCR0 = 18;               // timer period
   TA0CCR1 = 10;               // PWM duty
   TA0CCTL1 = OUTMOD_7;         // toggle output
   TA0CTL = TASSEL_2 + MC_1 + TACLR + TAIE; // start timer
   timerMode = 0;
   pauseCnt = PAUSE_CNT;
   pulseCnt = PULSE_CNT;
}

void TimerB_config()
{
   TB0CCTL0 = CM_1 | SCS | CAP | CCIE;
   TB0CTL = TASSEL_1 + MC_2 + TBCLR; // start capture
   lastCapture = 0;   
}

#pragma vector=PORT2_VECTOR         // PORT2 handler
__interrupt void PORT2_ISR(void)
{
     if (P2IFG & PAIFG1)            // button interrupt?
   {
        TB0CTL = TASSEL_1 + MC_2 + TBCLR; // start capture
      lastCapture = 0;
        P2IE_bit.P2IE1 = 0;         // disable button interrupt
      P2SEL1_bit.P2SEL1_1 = 1;   // reassign button for TimerB   
      P2SEL0_bit.P2SEL0_1 = 1;    
        P2IFG_bit.P2IFG1 = 0;      // clear interrupt flag
   }   


#pragma vector=TIMER0_A1_VECTOR      // TimerA handler
__interrupt void TimerA_ISR(void)
{
     TA0CTL_bit.TAIFG = 0;         // clear TimerA interrupt
     if (timerMode)
   {
        if (!(--pauseCnt))         // pause is over is complete
      {
           pauseCnt = PAUSE_CNT;   // restore pause counter
         timerMode = 0;         // switch to the other mode
            TA0CCTL1 = OUTMOD_7;   // toggle mode
      }
   }
   else
   { 
       if (!(--pulseCnt))         // burst is complete
      {
           pulseCnt = PULSE_CNT;   // restore pulse counter
         timerMode = 1;         // switch to the other mode
           TA0CCTL1 = OUTMOD_5;   // reset mode
      }
   }
}   

#pragma vector=TIMER0_B0_VECTOR      // TimerB handler
__interrupt void TimerB_ISR(void)
{
//     P2SEL1_bit.P2SEL1_1 = 0;      // reassign button to GPIO   
//   P2SEL0_bit.P2SEL0_1 = 0;
//   P2IE_bit.P2IE1 = 1;            // enable button interrupt
//   P2IFG_bit.P2IFG1 = 0;         // clear button interrupt flag
   
//   TB0CTL = 0;                  // stop capture   
     duration = TB0CCR0 - lastCapture;
   lastCapture = TB0CCR0;
   TB0CCTL0_bit.CCIFG = 0;         // clear TimerB capture flag
   __low_power_mode_off_on_exit(); // wake up CPU on exit
}   


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: MSP430 Генерация пачки импульсов при помощи таймера А
СообщениеДобавлено: Пт май 19, 2017 21:25:12 
Первый раз сказал Мяу!

Зарегистрирован: Чт апр 06, 2017 16:59:44
Сообщений: 25
Рейтинг сообщения: 0
Большое спасибо за вашу помощь!!)

Сегодня я смогла добраться до осциллографа и посмотреть что происходит.
Пачки излучаются, но нужна все-таки больше пауза. Я пыталась поменять в #define PAUSE_CNT 10 // pause duration значение на 2000, но мах задержка 7.5 мсек. Как можно увеличить до секунды?

Насчет таймера В, в ccs нельзя написать TB0CCTL0_bit.CCIFG = 0; поэтому пишу TBCCTL0 &= ~CCIFG;. Пока разбираюсь что в схеме не так и почему не происходит захвата и зажигания светодиода в этом случае.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: MSP430 Генерация пачки импульсов при помощи таймера А
СообщениеДобавлено: Пт май 19, 2017 22:22:54 
Друг Кота
Аватар пользователя

Карма: 74
Рейтинг сообщений: 607
Зарегистрирован: Ср дек 24, 2008 09:58:58
Сообщений: 3715
Рейтинг сообщения: 0
Медали: 3
Мявтор 1-й степени (1) Мявтор 2-й степени (1) Мявтор 3-й степени (1)
Насколько я понимаю, на вход Таймера А поступает частота 720 кгц, так что если он досчитает до 18, то это будет соответствовать периоду ультразвука 40 кгц. Этот таймер 16-битный, и максимальное значение туда можно отправить PAUSE_CNT=65535, что будет соответствовать задержке в 65535/720 = 91 миллисек. Если нужна большая задержка, то можно задействовать 32-битный счётчик прерываний в программе обработчика Таймера А или прескейлер 1:8 на входе таймера. Однако, он у Вас может быть уже задействован для получения частоты в 720 кгц на счетном входе. Поэтому я и спрашивал выше как Вы получили частоту 720 кгц на этом входе. Напишите в деталях систему и настройки тактирования МК и таймера.

А нужна-ли Вам такая большая задержка в 1 сек? Я полагаю целью проекта является построение ультразвукового локатора. Если принять скорость звука в воздухе 333 м/с (если правильно со школы помню), то максимальная дальность Вашего устройства с секундной паузой будет около 150м. Однако, мне не представляется реальным получить радиус действия более где-то 10м. Или причина в секундной задержке - экономия токопотребления? Проясните этот момент. Может заодно схемкой устройства поделитесь, можно через ЛС.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: MSP430 Генерация пачки импульсов при помощи таймера А
СообщениеДобавлено: Вс май 21, 2017 20:04:07 
Первый раз сказал Мяу!

Зарегистрирован: Чт апр 06, 2017 16:59:44
Сообщений: 25
Рейтинг сообщения: 0
Скорее всего это частота осциллятора DCO, так как я в коде не подключаю внешний кварц.
Да, вы правы, это схема локатора, который должен измерять расстояние до 3-х метров.
3 метра это около 0,018 сек. Сейчас я могу добиться только измерения расстояния до 0.5 метров.
Так как используется диффузионный режим работы ультразвукового датчика, то лучше иметь большую паузу таймера а, для того, чтобы пластины в датчике могли успокоиться и без проблем переключиться на нужный режим.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: MSP430 Генерация пачки импульсов при помощи таймера А
СообщениеДобавлено: Вс май 21, 2017 20:33:15 
Друг Кота
Аватар пользователя

Карма: 74
Рейтинг сообщений: 607
Зарегистрирован: Ср дек 24, 2008 09:58:58
Сообщений: 3715
Рейтинг сообщения: 0
Медали: 3
Мявтор 1-й степени (1) Мявтор 2-й степени (1) Мявтор 3-й степени (1)
Хорошо, пусть будет 1 сек. А с чем связано ограничение в 0.5м сейчас? Я не увидел новых вопросов в последнем сообщении. Полагаю, проблемы с программированием таймеров решены (?)

Кстати, что в проекте фиксировано кроме устройства дальномера? Я имею в виду МК и датчик. Этот уж слишком древний. А насчёт датчика - если устроит дальность до 2м с погрешностью около 3%, посмотрите на датчики другого типа VL6180X.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: MSP430 Генерация пачки импульсов при помощи таймера А
СообщениеДобавлено: Вс май 21, 2017 21:14:24 
Первый раз сказал Мяу!

Зарегистрирован: Чт апр 06, 2017 16:59:44
Сообщений: 25
Рейтинг сообщения: 0
0,5 метров не связано ни с чем. Просто максимальное время паузы можно сделать - 7 мсек, а это как раз 0,5 м.
Пыталась с помощью delay(); попробовать сделать задержку, но не выходит сделать больше паузу чем 7 мсек. Вопрос мой тот же, как реализовать паузу в 1 сек? Что такое прескейлер, а также что такое 32-битный счётчик прерывания и есть ли у вас пример его использования?


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: MSP430 Генерация пачки импульсов при помощи таймера А
СообщениеДобавлено: Вс май 21, 2017 21:53:55 
Друг Кота
Аватар пользователя

Карма: 74
Рейтинг сообщений: 607
Зарегистрирован: Ср дек 24, 2008 09:58:58
Сообщений: 3715
Рейтинг сообщения: 0
Медали: 3
Мявтор 1-й степени (1) Мявтор 2-й степени (1) Мявтор 3-й степени (1)
Я всё-таки не понял какие проблемы с получением задержки в 1 сек между пачками. Вы писали что использовали PAUSE_CNT = 2000. Почему не 40000? Период обнуления таймера для генерации частоты ШИМ 40 кгц - 1/40 мсек. Т.е. для получения 1 сек нужно сосчитать 40000 прерываний в обработчике. Попробуйте это сначала, только объявите переменную pauseCnt как unsigned int. У меня всё работает. Это брутальное решение, т.к. процессор будет часто пробуждаться лишь для увеличения счётчика, но зато быстро реализуемое.

Правильнее было-бы уменьшить частоту на входе счётчика таймера, задействовав его прескайлер, т.е. делитель входной частоты в максимальным делением 1:8 на время паузы. Тогда можно будет считать лишь до 5000. А если ещё увеличить период обнуления до 50000 в режиме подсчёта паузы, то можно будет считать до 11. А применив прескайлер 1:8 и установив период таймера 45000, можно будет считать лишь до 2. Короче, вариантов масса. Прочитать про прескайлер (input divider) можно в ДШ. Он управляется битами IDx в регистре TACTL.

Кстати о птичках: когда Вы писали про 2000, я полагаю, что не изменили тип переменной pauseCnt с char на unsigned int. При этом в переменную типа char нельзя будет записать что-то более 255, и если записываете туда 2000 (0х790 hex), то компилятор обрубит её до младшего байта (0х90). При этом максимальная зaдержка пачек действительно будет 256/40 = 6.4мсек.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: MSP430 Генерация пачки импульсов при помощи таймера А
СообщениеДобавлено: Вт май 23, 2017 12:10:11 
Первый раз сказал Мяу!

Зарегистрирован: Чт апр 06, 2017 16:59:44
Сообщений: 25
Рейтинг сообщения: 0
Большущее спасибо Вам, Ser60!

Я поменяла тип и получилось сделать паузу в 250 мсек.

Но скорее всего не работает режим захвата.
Пытаюсь проверить что происходит заход в прерывание таймера Б - пытаюсь зажечь диод.
Но безуспешно:
#include "msp430f149.h"

#define PULSE_CNT 4 // # of pulses in a burst
#define PAUSE_CNT 10000 // pause duration

void Ports_config();
void TimerA_config();
char timerMode; // 0: burst, 1:pause
unsigned int pulseCnt, pauseCnt;
unsigned int lastCapture;
unsigned int duration;


void Ports_config()
{
P1SEL = BIT6; // assign P1.6 to TimerA
P1DIR = BIT6;
P4SEL = BIT0; // timer B
P4DIR &= ~BIT0;
P1DIR |= BIT0;
P1SEL|=BIT0;
P1OUT = 0x01;
//P1SEL &= ~BIT0;
}

void TimerA_config()
{
TA0CCR0 = 18;
TA0CCR1 = 10;
TA0CCTL1 = OUTMOD_7;
TA0CTL = TASSEL_2 + MC_1 + TACLR + TAIE;
timerMode = 0;
pauseCnt = PAUSE_CNT;
pulseCnt = PULSE_CNT;
}
void TimerB_config()
{
TB0CCTL0 = CM_3 | SCS | CAP | CCIE;
TB0CTL = TBSSEL_1 + MC_2 + TBCLR;
lastCapture = 0;
}
//————————Timer B interrupt——————
#pragma vector=TIMERB0_VECTOR // TimerB handler
__interrupt void TimerB_ISR(void)
{

//if(TB0CCR0 < 0x12C)
P1OUT ^= BIT1;
lastCapture = 0;
TB0CTL = 0; // stop capture
duration = TB0CCR0 - lastCapture;
lastCapture = TB0CCR0;
//TBCTL &= ~ TBIFG;
TB0CCTL0 &= ~CCIFG;
//CCIFG = 0; // clear TimerB capture flag
__low_power_mode_off_on_exit(); // wake up CPU on exit
}
int main()
{
WDTCTL = WDTPW + WDTHOLD; // stop watchdog timer
Ports_config(); // set up ports for GPIO
TimerA_config(); // configure TimerA module for 40 KHz
TimerB_config();
while(1)
{
__low_power_mode_0(); // wait for capture
__no_operation();
__no_operation(); // set breakpoint here to examine duration
}
}

В чем может быть проблема? На вход таймера В приходит уровень - 3 В, то есть по логике он должен переходить в прерывание.


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 41 ]    , 2,  

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 27


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y