MSP430 Генерация пачки импульсов при помощи таймера А
-
Terminator_2017
- Первый раз сказал Мяу!
- Сообщения: 25
- Зарегистрирован: Чт апр 06, 2017 16:59:44
MSP430 Генерация пачки импульсов при помощи таймера А
Дорогие мои друзья, коллеги, товарищи!
Нужна Ваша помощь!
Необходимо генерировать пачку импульсов (частота 40 кГц) с выхода Timer A на MSP430f149 с определенным интервалом.
Данная задача необходима для ультразвукового детектора.
К сожалению, сейчас получается лишь подавать импульсы с частотой 40 кГц без остановки.
Пример листинга:
void timerA_PWM()
{
//задаем частоту ШИМ
TACCR0=18;
//устанавливаем длительность импульса
TACCR1=10;
//устанавливаем режим вывода «Сброс/Установка» (111)
TACCTL1=OUTMOD_7;
//выбираем SMCLK в качестве источника тактирования
//режим «Вверх»
TACTL=TASSEL_2 +MC_1;
}
void timerA_pause()
{
//задаем интервал времени между измерениями
TACCR0 = 12000-1;
//разрешаем прерывания от таймера
TACCTL0 = CCIE;
//режим «Вверх»;
//коэффициент деления для входной тактовой частоты = 8
//выбираем ACLK в качестве источника тактирования таймера
//устанавливаем бит очистки таймера A
TACTL = MC_1|ID_3|TASSEL_1|TACLR;
}
//Обработчик прерывания таймера A
#pragma vector = TIMERA0_VECTOR
__interrupt void TIMERA0_VECTOR_ISR(void)
{
//Перевод таймера А в режим формирования ШИМ
timerA_PWM();
//Пауза для формирования пачки импульсов и захвата
_delay_cycles(1000);
//Перевод таймера А в режим ожидания
timerA_pause();
}
Помогите милой даме разобраться, пожалуйста!))))))
Нужна Ваша помощь!
Необходимо генерировать пачку импульсов (частота 40 кГц) с выхода Timer A на MSP430f149 с определенным интервалом.
Данная задача необходима для ультразвукового детектора.
К сожалению, сейчас получается лишь подавать импульсы с частотой 40 кГц без остановки.
Пример листинга:
void timerA_PWM()
{
//задаем частоту ШИМ
TACCR0=18;
//устанавливаем длительность импульса
TACCR1=10;
//устанавливаем режим вывода «Сброс/Установка» (111)
TACCTL1=OUTMOD_7;
//выбираем SMCLK в качестве источника тактирования
//режим «Вверх»
TACTL=TASSEL_2 +MC_1;
}
void timerA_pause()
{
//задаем интервал времени между измерениями
TACCR0 = 12000-1;
//разрешаем прерывания от таймера
TACCTL0 = CCIE;
//режим «Вверх»;
//коэффициент деления для входной тактовой частоты = 8
//выбираем ACLK в качестве источника тактирования таймера
//устанавливаем бит очистки таймера A
TACTL = MC_1|ID_3|TASSEL_1|TACLR;
}
//Обработчик прерывания таймера A
#pragma vector = TIMERA0_VECTOR
__interrupt void TIMERA0_VECTOR_ISR(void)
{
//Перевод таймера А в режим формирования ШИМ
timerA_PWM();
//Пауза для формирования пачки импульсов и захвата
_delay_cycles(1000);
//Перевод таймера А в режим ожидания
timerA_pause();
}
Помогите милой даме разобраться, пожалуйста!))))))
- Реклама
- oleg110592
- Друг Кота
- Сообщения: 3832
- Зарегистрирован: Сб сен 10, 2011 17:46:25
Re: MSP430 Генерация пачки импульсов при помощи таймера А
подзабыл MSP430, по настройкам таймера не подскажу, но тут попробую покритиковать:
критика:
1) паузы в прерываниях обычно не делают
2) _delay_cycles(1000); сильно мало
3) после перевода таймера А в режим ожидания имхо пауза тоже нужна
в ИАРе MSP430, как и в AVR можно сделать функции задержки так:
попробовать применить можно так, желательно перенести в main:
Код: Выделить всё
//Обработчик прерывания таймера A
#pragma vector = TIMERA0_VECTOR
__interrupt void TIMERA0_VECTOR_ISR(void)
{
//Перевод таймера А в режим формирования ШИМ
timerA_PWM();
//Пауза для формирования пачки импульсов и захвата
_delay_cycles(1000);
//Перевод таймера А в режим ожидания
timerA_pause();
}1) паузы в прерываниях обычно не делают
2) _delay_cycles(1000); сильно мало
3) после перевода таймера А в режим ожидания имхо пауза тоже нужна
в ИАРе MSP430, как и в AVR можно сделать функции задержки так:
Код: Выделить всё
#define XTALL 16.0
#define delay_us(us) __delay_cycles (XTALL * us);
#define delay_ms(ms) delay_us (1000 * ms)Код: Выделить всё
//Перевод таймера А в режим формирования ШИМ
timerA_PWM();
//Пауза для формирования пачки импульсов и захвата
delay_ms(100); // задержка в mS
//Перевод таймера А в режим ожидания
timerA_pause();
delay_ms(100);
-
Terminator_2017
- Первый раз сказал Мяу!
- Сообщения: 25
- Зарегистрирован: Чт апр 06, 2017 16:59:44
Re: MSP430 Генерация пачки импульсов при помощи таймера А
попробовать применить можно так, желательно перенести в main:
[/quote]
Т.е. ничего не записывать в прерывание?
Код: Выделить всё
//Перевод таймера А в режим формирования ШИМ
timerA_PWM();
//Пауза для формирования пачки импульсов и захвата
delay_ms(100); // задержка в mS
//Перевод таймера А в режим ожидания
timerA_pause();
delay_ms(100);
Т.е. ничего не записывать в прерывание?
- oleg110592
- Друг Кота
- Сообщения: 3832
- Зарегистрирован: Сб сен 10, 2011 17:46:25
Re: MSP430 Генерация пачки импульсов при помощи таймера А
имхо не нужно прерывание:Terminator_2017 писал(а):Т.е. ничего не записывать в прерывание?
1) включили шим
2) выдержали паузу
3) выключили шим
4) выдержали паузу
5) переход в пункт 1)
||||||||||||||||||______________||||||||||||||||||______________||||||||||||||||||______________
-
Terminator_2017
- Первый раз сказал Мяу!
- Сообщения: 25
- Зарегистрирован: Чт апр 06, 2017 16:59:44
Re: MSP430 Генерация пачки импульсов при помощи таймера А
Спасибо большое, oleg110592, за то что Вы так быстро мне ответили.
Я уже пробовала в main, без прерывания сделать, но к сожалению, ничего не получается. Либо просто высокий уровень, либо импульсы без остановки.
Может быть есть какой-то еще способ отправлять пачку импульсов?
Я уже пробовала в main, без прерывания сделать, но к сожалению, ничего не получается. Либо просто высокий уровень, либо импульсы без остановки.
Может быть есть какой-то еще способ отправлять пачку импульсов?
- Реклама
- oleg110592
- Друг Кота
- Сообщения: 3832
- Зарегистрирован: Сб сен 10, 2011 17:46:25
Re: MSP430 Генерация пачки импульсов при помощи таймера А
так бы попробовал:
Код: Выделить всё
#define XTALL 16.0
#define delay_us(us) __delay_cycles (XTALL * us);
#define delay_ms(ms) delay_us (1000 * ms)
void timerA_PWM()
{
//задаем частоту ШИМ
TACCR0=18;
//устанавливаем длительность импульса
TACCR1=10;
//устанавливаем режим вывода «Сброс/Установка» (111)
TACCTL1=OUTMOD_7;
//выбираем SMCLK в качестве источника тактирования
//режим «Вверх»
TACTL |= TASSEL_2
}
void main()
{
...............
...............
timerA_PWM();
while(1)
{
TACTL |= MC_1; // Timer ON
delay_ms(100);
TACTL &= ~MC_1; // Timer OFF
delay_ms(100);
}
}- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: MSP430 Генерация пачки импульсов при помощи таймера А
Terminator_2017, можно ещё оперировать не включением/отключением таймера, а направлением выхода. Т.е. ШИМ постоянно молотит, а в определённые времена настраиваем его вывод на вход или выход.
-
Terminator_2017
- Первый раз сказал Мяу!
- Сообщения: 25
- Зарегистрирован: Чт апр 06, 2017 16:59:44
Re: MSP430 Генерация пачки импульсов при помощи таймера А
Большое спасибо!oleg110592 писал(а):так бы попробовал:Код: Выделить всё
#define XTALL 16.0 #define delay_us(us) __delay_cycles (XTALL * us); #define delay_ms(ms) delay_us (1000 * ms) void timerA_PWM() { //задаем частоту ШИМ TACCR0=18; //устанавливаем длительность импульса TACCR1=10; //устанавливаем режим вывода «Сброс/Установка» (111) TACCTL1=OUTMOD_7; //выбираем SMCLK в качестве источника тактирования //режим «Вверх» TACTL |= TASSEL_2 } void main() { ............... ............... timerA_PWM(); while(1) { TACTL |= MC_1; // Timer ON delay_ms(100); TACTL &= ~MC_1; // Timer OFF delay_ms(100); } }
Я поменяла выход на 1.6/ТА1 и данный код заработал. Но не понимаю почему первые два раза, когда таймер останавливается, сигнал низкого уровня, а следующие две остановки сигнал с выхода остается на высоком уровне.
- oleg110592
- Друг Кота
- Сообщения: 3832
- Зарегистрирован: Сб сен 10, 2011 17:46:25
Re: MSP430 Генерация пачки импульсов при помощи таймера А
Таймер выключаем в неопределенный момент - какое состояние пина было когда шим работал, такое и осталось. Тут поcле выключения таймера можно принудительно пин установить в "0" так: P1OUT &= ~(1<<6);Terminator_2017 писал(а):Но не понимаю почему первые два раза, когда таймер останавливается, сигнал низкого уровня, а следующие две остановки сигнал с выхода остается на высоком уровне.
-
Terminator_2017
- Первый раз сказал Мяу!
- Сообщения: 25
- Зарегистрирован: Чт апр 06, 2017 16:59:44
Re: MSP430 Генерация пачки импульсов при помощи таймера А
Не получается все равно сделать так, чтобы после подачи импульсов был низкий уровень.
Пробовала так:
WDTCTL=WDTPW+WDTHOLD;
timerA_PWM();
while(1)
{
TACTL |= MC_1; // Timer ON
delay_us(125);
TACTL &= ~MC_1; // Timer OFF
P1OUT &= ~(1<<7);
delay_ms(100);
}
Что я делаю не так?
Пробовала так:
WDTCTL=WDTPW+WDTHOLD;
timerA_PWM();
while(1)
{
TACTL |= MC_1; // Timer ON
delay_us(125);
TACTL &= ~MC_1; // Timer OFF
P1OUT &= ~(1<<7);
delay_ms(100);
}
Что я делаю не так?
- oleg110592
- Друг Кота
- Сообщения: 3832
- Зарегистрирован: Сб сен 10, 2011 17:46:25
Re: MSP430 Генерация пачки импульсов при помощи таймера А
Terminator_2017 писал(а):
P1OUT &= ~(1<<7);
Что я делаю не так?
не оно?Terminator_2017 писал(а): Я поменяла выход на 1.6/ТА1
-
Terminator_2017
- Первый раз сказал Мяу!
- Сообщения: 25
- Зарегистрирован: Чт апр 06, 2017 16:59:44
Re: MSP430 Генерация пачки импульсов при помощи таймера А
Пробовала и P1OUT &= ~(1<<6);, но все равно чередуется, то задержка на низком, то на высоком уровне
- oleg110592
- Друг Кота
- Сообщения: 3832
- Зарегистрирован: Сб сен 10, 2011 17:46:25
Re: MSP430 Генерация пачки импульсов при помощи таймера А
глянул док. - подзабыл о P1SEL
Код: Выделить всё
while(1)
{
P1SEL |= (1<<6);
TACTL |= MC_1; // Timer ON
delay_us(125);
TACTL &= ~MC_1; // Timer OFF
P1SEL &= ~(1<<6);
P1OUT &= ~(1<<6);
delay_ms(100);
}-
Terminator_2017
- Первый раз сказал Мяу!
- Сообщения: 25
- Зарегистрирован: Чт апр 06, 2017 16:59:44
Re: MSP430 Генерация пачки импульсов при помощи таймера А
Товарищи,
А как можно реализовать все-таки через прерывания
К сожалению способ выше заставляет первый и последний импульс в пачке дрожать + нужно в паузу реализовать включение таймера А в режиме захвата
А как можно реализовать все-таки через прерывания
К сожалению способ выше заставляет первый и последний импульс в пачке дрожать + нужно в паузу реализовать включение таймера А в режиме захвата
- Starichok51
- Модератор
- Сообщения: 19054
- Зарегистрирован: Сб авг 14, 2010 15:05:51
- Откуда: г. Озерск, Челябинская обл.
Re: MSP430 Генерация пачки импульсов при помощи таймера А
использовать еще один таймер.
первый таймер - собственно генерация требуемых импульсов в пачке.
второй таймер - формирует "окно" требуемой длительности для пачки.
в прерывании второго таймера (например, переполнение - это "сигнал" окончания "окна") делаем следующее:
- выключаем первый таймер (конец пачки),
- выключаем второй таймер,
- переводим первый таймер в режим захвата, и включаем его,
- формируем "сигнал" для начала отсчета паузы между пачками.
а еще лучше применить третий таймер для задания периода следования пачек, а не применять программную задержку.
именно программная задержка может быть причиной дрожания времени начала пачки, так как начало отсчета задержки будет зависеть от выполнения разных условий в программном цикле.
этот третий таймер
- включает первый таймер в режиме ШИМ,
- включает второй таймер для отсчета "окна".
ну, а взаимодействия первого и второго таймеров между собой я уже описал.
первый таймер - собственно генерация требуемых импульсов в пачке.
второй таймер - формирует "окно" требуемой длительности для пачки.
в прерывании второго таймера (например, переполнение - это "сигнал" окончания "окна") делаем следующее:
- выключаем первый таймер (конец пачки),
- выключаем второй таймер,
- переводим первый таймер в режим захвата, и включаем его,
- формируем "сигнал" для начала отсчета паузы между пачками.
а еще лучше применить третий таймер для задания периода следования пачек, а не применять программную задержку.
именно программная задержка может быть причиной дрожания времени начала пачки, так как начало отсчета задержки будет зависеть от выполнения разных условий в программном цикле.
этот третий таймер
- включает первый таймер в режиме ШИМ,
- включает второй таймер для отсчета "окна".
ну, а взаимодействия первого и второго таймеров между собой я уже описал.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
-
Terminator_2017
- Первый раз сказал Мяу!
- Сообщения: 25
- Зарегистрирован: Чт апр 06, 2017 16:59:44
Re: MSP430 Генерация пачки импульсов при помощи таймера А
Добрый день,
Не поняла про три таймера.
Возможно можно как-то использовать лишь ССR0 и прерывание?
На одном из форумов мне предложили следующий алгоритм:"Use the CCR0 interrupt to count the number of periods, after counting to five then turn off the output accordingly and readjust the value of CCR0 to the desired delay, then on the next interrupt change CCR0 back to the pulse period and re-start the output."
Но я не понимаю как это реализовать. Возможно кто-то решал такую задачу?
Не поняла про три таймера.
Возможно можно как-то использовать лишь ССR0 и прерывание?
На одном из форумов мне предложили следующий алгоритм:"Use the CCR0 interrupt to count the number of periods, after counting to five then turn off the output accordingly and readjust the value of CCR0 to the desired delay, then on the next interrupt change CCR0 back to the pulse period and re-start the output."
Но я не понимаю как это реализовать. Возможно кто-то решал такую задачу?
Re: MSP430 Генерация пачки импульсов при помощи таймера А
Я помогу реализовать этот подход в коде, напишите какие должны быть длительности пачки и паузы.
-
Terminator_2017
- Первый раз сказал Мяу!
- Сообщения: 25
- Зарегистрирован: Чт апр 06, 2017 16:59:44
Re: MSP430 Генерация пачки импульсов при помощи таймера А
Добрый день, Ser60
Период одного импульса 25 мкс (9 сек длительность импульса) Я тактирую от внутреннего генератора (720 кГц), поэтому вот такие значения соответствуют: TACCR0= 18; и TACCR1=7;
Пачка состоит из 5 импульсов = 125 мкс длительность одной пачки
Пауза между пачками должна быть около 200 - 300 мс.
Период одного импульса 25 мкс (9 сек длительность импульса) Я тактирую от внутреннего генератора (720 кГц), поэтому вот такие значения соответствуют: TACCR0= 18; и TACCR1=7;
Пачка состоит из 5 импульсов = 125 мкс длительность одной пачки
Пауза между пачками должна быть около 200 - 300 мс.
Re: MSP430 Генерация пачки импульсов при помощи таймера А
Вот Вам рабочий код. У меня нет MSP430F149, поэтому я его протестил на MSP430G2553.
Не знаю как Вы сгенерировали частоту 720 кгц, я установил её на скорою руку приблизительно в функции Clock_config(), при этом частота импульсов в пачке получилась около 37 кгц. Переменная timerMode в программе отвечает за работу таймера в режиме генерации импульсов (timerMode=0) или паузы (timerMode=1). Число импульсов в пачке и длительность паузы устанавливаются константами PULSE_CNT и PAUSE_CNT в начале файла и отсчитывается переменными pulseCn и pauseCnt в обработчике прерывания таймера. Во время генерации импульсов выходной режим пина таймера установлен в OUTMODE_7, как в Вашей программе, а на время генерации паузы он меняется на OUTMOD_5 (reset) также в обработчике прерывания. Будут вопросы по коду - отвечу. Вот снятая осциллограмма работы.
Спойлер
Код: Выделить всё
#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();
char timerMode; // 0: burst, 1:pause
char pulseCnt, pauseCnt;
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();
}
}
void Clock_config() // configure basic clock module
{
DCOCTL = DCO1; //set ~40 KHz pulse frequency
BCSCTL1 = RSEL3 + XT2OFF;
BCSCTL2 = DIVS_1;
BCSCTL3 = LFXT1S1; // select VLO as ACLK
}
void Ports_config()
{
P1SEL = P2; // assign P1.2 to TimerA
P1DIR = P2;
}
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)
{
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
}
}
} -
Terminator_2017
- Первый раз сказал Мяу!
- Сообщения: 25
- Зарегистрирован: Чт апр 06, 2017 16:59:44
Re: MSP430 Генерация пачки импульсов при помощи таймера А
Спасибо большое за пример кода!
Подскажите, а для чего цикл while?
А также я немного переделала под свой мсп и код прерывания получился такой:
#pragma vector=TIMER0_A1_VECTOR // TimerA handler
__interrupt void TimerA_ISR(void)
{
//(TACTL & TAIFG)=0;
// TA0CTL_bit.TAIFG = 0; // clear TimerA interrupt
1 -------------------- (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
{
2 ---------------------if (!(--pulseCnt)) // burst is complete
{
pulseCnt = PULSE_CNT; // restore pulse counter
timerMode = 1; // switch to the other mode
TACCTL1 = OUTMOD_5; // reset mode
}
}
}
В прерывание входит, но ходит только по двум строчкам (указала в коде)
К сожалению не смогла посмотреть что на осциллографе. Поэтому пыталась зажигать светодиод, чтобы понять как долго он горит во время паузы, но ничего.
Подскажите, а для чего цикл while?
А также я немного переделала под свой мсп и код прерывания получился такой:
#pragma vector=TIMER0_A1_VECTOR // TimerA handler
__interrupt void TimerA_ISR(void)
{
//(TACTL & TAIFG)=0;
// TA0CTL_bit.TAIFG = 0; // clear TimerA interrupt
1 -------------------- (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
{
2 ---------------------if (!(--pulseCnt)) // burst is complete
{
pulseCnt = PULSE_CNT; // restore pulse counter
timerMode = 1; // switch to the other mode
TACCTL1 = OUTMOD_5; // reset mode
}
}
}
В прерывание входит, но ходит только по двум строчкам (указала в коде)
К сожалению не смогла посмотреть что на осциллографе. Поэтому пыталась зажигать светодиод, чтобы понять как долго он горит во время паузы, но ничего.


