MSP430 Генерация пачки импульсов при помощи таймера А

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Аватара пользователя
Ser60
Друг Кота
Сообщения: 3784
Зарегистрирован: Ср дек 24, 2008 09:58:58

Re: MSP430 Генерация пачки импульсов при помощи таймера А

Сообщение Ser60 »

Цикл while, в данном конкретном случае, не нужен, если только МК не будет делать еще что-то.
Следовало-бы проиниацилизировать переменные pauseCnt и pulseCnt их соответствующими значениями из дефайном в начале кода в функции настройки таймера.
Реклама
Terminator_2017
Первый раз сказал Мяу!
Сообщения: 25
Зарегистрирован: Чт апр 06, 2017 16:59:44

Re: MSP430 Генерация пачки импульсов при помощи таймера А

Сообщение Terminator_2017 »

Вот полностью весь код:

#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?
Реклама
Аватара пользователя
Ser60
Друг Кота
Сообщения: 3784
Зарегистрирован: Ср дек 24, 2008 09:58:58

Re: MSP430 Генерация пачки импульсов при помощи таймера А

Сообщение Ser60 »

Не понял зачем его вообще включать для данного приложения? В коде прерывание происходит каждый раз по достижении счетчиком таймера его максимального значения. Вопрос первоначально был как обойтись одним таймером. Чего хотите добиться сейчас, задействовав второй таймер?
Terminator_2017
Первый раз сказал Мяу!
Сообщения: 25
Зарегистрирован: Чт апр 06, 2017 16:59:44

Re: MSP430 Генерация пачки импульсов при помощи таймера А

Сообщение Terminator_2017 »

Вообще задача в том, чтобы отправлять с таймера А пачку импульсов и принимать пришедший сигнал на таймер В.

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

Есть еще вопрос почему код по захвату у меня не заходит в прерывание:
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();
}

Да и почему-то записывает не в те регистры флаг прерывания.
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
Ser60
Друг Кота
Сообщения: 3784
Зарегистрирован: Ср дек 24, 2008 09:58:58

Re: MSP430 Генерация пачки импульсов при помощи таймера А

Сообщение Ser60 »

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

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

Напишите нормально что надо сделать, я не телепат. Если это студенческая методичка, лучше выложите её сюда полностью. Кроме того, какие имеете средства отладки (FET debugger? Лог. анализатор? Среда разработки?). Если у Вас демо-плата с MSP430, что за плата.
Реклама
Terminator_2017
Первый раз сказал Мяу!
Сообщения: 25
Зарегистрирован: Чт апр 06, 2017 16:59:44

Re: MSP430 Генерация пачки импульсов при помощи таймера А

Сообщение Terminator_2017 »

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

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

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

Среда разработки - code composer studio.
Демо платы нет, есть схема с микроконтроллером msp430f149. Средство отладки - FET debugger.
Реклама
Аватара пользователя
Ser60
Друг Кота
Сообщения: 3784
Зарегистрирован: Ср дек 24, 2008 09:58:58

Re: MSP430 Генерация пачки импульсов при помощи таймера А

Сообщение Ser60 »

В прошлый раз я был не прав с советами. Теперь задачу понял. Вот рабочий код использования Таймера для захвата. Он измеряет длительность нажатия кнопки, подсоединённой между 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
}	
Terminator_2017
Первый раз сказал Мяу!
Сообщения: 25
Зарегистрирован: Чт апр 06, 2017 16:59:44

Re: MSP430 Генерация пачки импульсов при помощи таймера А

Сообщение Terminator_2017 »

Большое спасибо за листинг!

В данном примере
#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)?
Аватара пользователя
Ser60
Друг Кота
Сообщения: 3784
Зарегистрирован: Ср дек 24, 2008 09:58:58

Re: MSP430 Генерация пачки импульсов при помощи таймера А

Сообщение Ser60 »

Не нужно там никакого условия. Вход в обработчик прерывания произойдёт как только совершится захват.
Кстати, я вспомнил, что у меня есть 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, стабилизированным часовым кристаллом. Код проверен в железе и работоспособность его гарантируется.
Terminator_2017
Первый раз сказал Мяу!
Сообщения: 25
Зарегистрирован: Чт апр 06, 2017 16:59:44

Re: MSP430 Генерация пачки импульсов при помощи таймера А

Сообщение Terminator_2017 »

А не могли бы Вы объяснить, почему при выполнении кода пошагово, все застревает в прерывании Таймера А? Что-то я забыла добавить?

#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
}
Аватара пользователя
Ser60
Друг Кота
Сообщения: 3784
Зарегистрирован: Ср дек 24, 2008 09:58:58

Re: MSP430 Генерация пачки импульсов при помощи таймера А

Сообщение Ser60 »

Нужно раскомментить строку где сбрасывается флаг прерывания ТаймераА в его обработчике, если синтакс позволяет. Как написано сделано неправильно. Попробуйте так: TACTL &= ~TAIFG;
Terminator_2017
Первый раз сказал Мяу!
Сообщения: 25
Зарегистрирован: Чт апр 06, 2017 16:59:44

Re: MSP430 Генерация пачки импульсов при помощи таймера А

Сообщение Terminator_2017 »

Исправила, но все равно зациклился в обработчике(
Аватара пользователя
Ser60
Друг Кота
Сообщения: 3784
Зарегистрирован: Ср дек 24, 2008 09:58:58

Re: MSP430 Генерация пачки импульсов при помощи таймера А

Сообщение Ser60 »

Я не пишу под 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
}	
Terminator_2017
Первый раз сказал Мяу!
Сообщения: 25
Зарегистрирован: Чт апр 06, 2017 16:59:44

Re: MSP430 Генерация пачки импульсов при помощи таймера А

Сообщение Terminator_2017 »

Большое спасибо за вашу помощь!!)

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

Насчет таймера В, в ccs нельзя написать TB0CCTL0_bit.CCIFG = 0; поэтому пишу TBCCTL0 &= ~CCIFG;. Пока разбираюсь что в схеме не так и почему не происходит захвата и зажигания светодиода в этом случае.
Аватара пользователя
Ser60
Друг Кота
Сообщения: 3784
Зарегистрирован: Ср дек 24, 2008 09:58:58

Re: MSP430 Генерация пачки импульсов при помощи таймера А

Сообщение Ser60 »

Насколько я понимаю, на вход Таймера А поступает частота 720 кгц, так что если он досчитает до 18, то это будет соответствовать периоду ультразвука 40 кгц. Этот таймер 16-битный, и максимальное значение туда можно отправить PAUSE_CNT=65535, что будет соответствовать задержке в 65535/720 = 91 миллисек. Если нужна большая задержка, то можно задействовать 32-битный счётчик прерываний в программе обработчика Таймера А или прескейлер 1:8 на входе таймера. Однако, он у Вас может быть уже задействован для получения частоты в 720 кгц на счетном входе. Поэтому я и спрашивал выше как Вы получили частоту 720 кгц на этом входе. Напишите в деталях систему и настройки тактирования МК и таймера.

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

Re: MSP430 Генерация пачки импульсов при помощи таймера А

Сообщение Terminator_2017 »

Скорее всего это частота осциллятора DCO, так как я в коде не подключаю внешний кварц.
Да, вы правы, это схема локатора, который должен измерять расстояние до 3-х метров.
3 метра это около 0,018 сек. Сейчас я могу добиться только измерения расстояния до 0.5 метров.
Так как используется диффузионный режим работы ультразвукового датчика, то лучше иметь большую паузу таймера а, для того, чтобы пластины в датчике могли успокоиться и без проблем переключиться на нужный режим.
Аватара пользователя
Ser60
Друг Кота
Сообщения: 3784
Зарегистрирован: Ср дек 24, 2008 09:58:58

Re: MSP430 Генерация пачки импульсов при помощи таймера А

Сообщение Ser60 »

Хорошо, пусть будет 1 сек. А с чем связано ограничение в 0.5м сейчас? Я не увидел новых вопросов в последнем сообщении. Полагаю, проблемы с программированием таймеров решены (?)

Кстати, что в проекте фиксировано кроме устройства дальномера? Я имею в виду МК и датчик. Этот уж слишком древний. А насчёт датчика - если устроит дальность до 2м с погрешностью около 3%, посмотрите на датчики другого типа VL6180X.
Terminator_2017
Первый раз сказал Мяу!
Сообщения: 25
Зарегистрирован: Чт апр 06, 2017 16:59:44

Re: MSP430 Генерация пачки импульсов при помощи таймера А

Сообщение Terminator_2017 »

0,5 метров не связано ни с чем. Просто максимальное время паузы можно сделать - 7 мсек, а это как раз 0,5 м.
Пыталась с помощью delay(); попробовать сделать задержку, но не выходит сделать больше паузу чем 7 мсек. Вопрос мой тот же, как реализовать паузу в 1 сек? Что такое прескейлер, а также что такое 32-битный счётчик прерывания и есть ли у вас пример его использования?
Аватара пользователя
Ser60
Друг Кота
Сообщения: 3784
Зарегистрирован: Ср дек 24, 2008 09:58:58

Re: MSP430 Генерация пачки импульсов при помощи таймера А

Сообщение Ser60 »

Я всё-таки не понял какие проблемы с получением задержки в 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мсек.
Terminator_2017
Первый раз сказал Мяу!
Сообщения: 25
Зарегистрирован: Чт апр 06, 2017 16:59:44

Re: MSP430 Генерация пачки импульсов при помощи таймера А

Сообщение Terminator_2017 »

Большущее спасибо Вам, 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 В, то есть по логике он должен переходить в прерывание.
Ответить

Вернуться в «Разные вопросы по МК»