Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Вт май 16, 2017 19:58:14
Цикл while, в данном конкретном случае, не нужен, если только МК не будет делать еще что-то.
Следовало-бы проиниацилизировать переменные pauseCnt и pulseCnt их соответствующими значениями из дефайном в начале кода в функции настройки таймера.
Вт май 16, 2017 20:03:47
Вот полностью весь код:
#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?
Вт май 16, 2017 20:25:42
Не понял зачем его вообще включать для данного приложения? В коде прерывание происходит каждый раз по достижении счетчиком таймера его максимального значения. Вопрос первоначально был как обойтись одним таймером. Чего хотите добиться сейчас, задействовав второй таймер?
Вт май 16, 2017 21:06:00
Вообще задача в том, чтобы отправлять с таймера А пачку импульсов и принимать пришедший сигнал на таймер В.
Решила постепенно разбираться.
Сейчас мне не понятно, почему в прерывании не выполняются условия.
Также есть вопрос, как добавить в данный код работу таймера В.
Есть еще вопрос почему код по захвату у меня не заходит в прерывание:
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();
}
Да и почему-то записывает не в те регистры флаг прерывания.
Ср май 17, 2017 02:54:59
почему код по захвату у меня не заходит в прерывание
Потому что таймер стоит и не считает. Запишите значение МС_1 в TBCTL. Кроме того, TBCL0=0 дефолтно и для запуска таймера там должно быть ненулевое значение. Ну и ещё этот таймер, согласно конфигурации тактируется от ACLK. Чему равна эта частота (из кода определить это невозможно)?
Остальные вопросы я не понял. Что значит "
принимать пришедший сигнал на таймер В"? И какие условия должны выполняться в прерывании (сейчас там никаких условий не проверяется)?
Напишите нормально что надо сделать, я не телепат. Если это студенческая методичка, лучше выложите её сюда полностью. Кроме того, какие имеете средства отладки (FET debugger? Лог. анализатор? Среда разработки?). Если у Вас демо-плата с MSP430, что за плата.
Ср май 17, 2017 08:59:42
Задача в том, чтобы отправлять пачку импульсов с таймера А на ультразвуковой датчик, излучать, а затем принимать усиленный отраженный сигнал на вход таймера В.
Прерывания таймера В должны происходить тогда, когда на вход его поступает отраженный сигнал. Нужно выводить время с начала запуска таймера В и захвата сигнала. Также останавливать таймер и запускать заново после расчета времени.
Вообще я тактирую от SMCLK (TBSELL_2) ибо когда пыталась от ACLK таймер В не считал.
Среда разработки - code composer studio.
Демо платы нет, есть схема с микроконтроллером msp430f149. Средство отладки - FET debugger.
Ср май 17, 2017 19:11:32
В прошлый раз я был не прав с советами. Теперь задачу понял. Вот рабочий код использования Таймера для захвата. Он измеряет длительность нажатия кнопки, подсоединённой между 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
}
Ср май 17, 2017 22:27:23
Большое спасибо за листинг!
В данном примере
#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)?
Чт май 18, 2017 00:19:30
Не нужно там никакого условия. Вход в обработчик прерывания произойдёт как только совершится захват.
Кстати, я вспомнил, что у меня есть 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, стабилизированным часовым кристаллом. Код проверен в железе и работоспособность его гарантируется.
Чт май 18, 2017 21:53:18
А не могли бы Вы объяснить, почему при выполнении кода пошагово, все застревает в прерывании Таймера А? Что-то я забыла добавить?
#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
}
Чт май 18, 2017 22:06:10
Нужно раскомментить строку где сбрасывается флаг прерывания ТаймераА в его обработчике, если синтакс позволяет. Как написано сделано неправильно. Попробуйте так: TACTL &= ~TAIFG;
Чт май 18, 2017 22:25:02
Исправила, но все равно зациклился в обработчике(
Чт май 18, 2017 22:38:52
Я не пишу под 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
}
Пт май 19, 2017 21:25:12
Большое спасибо за вашу помощь!!)
Сегодня я смогла добраться до осциллографа и посмотреть что происходит.
Пачки излучаются, но нужна все-таки больше пауза. Я пыталась поменять в #define PAUSE_CNT 10 // pause duration значение на 2000, но мах задержка 7.5 мсек. Как можно увеличить до секунды?
Насчет таймера В, в ccs нельзя написать TB0CCTL0_bit.CCIFG = 0; поэтому пишу TBCCTL0 &= ~CCIFG;. Пока разбираюсь что в схеме не так и почему не происходит захвата и зажигания светодиода в этом случае.
Пт май 19, 2017 22:22:54
Насколько я понимаю, на вход Таймера А поступает частота 720 кгц, так что если он досчитает до 18, то это будет соответствовать периоду ультразвука 40 кгц. Этот таймер 16-битный, и максимальное значение туда можно отправить PAUSE_CNT=65535, что будет соответствовать задержке в 65535/720 = 91 миллисек. Если нужна большая задержка, то можно задействовать 32-битный счётчик прерываний в программе обработчика Таймера А или прескейлер 1:8 на входе таймера. Однако, он у Вас может быть уже задействован для получения частоты в 720 кгц на счетном входе. Поэтому я и спрашивал выше как Вы получили частоту 720 кгц на этом входе. Напишите в деталях систему и настройки тактирования МК и таймера.
А нужна-ли Вам такая большая задержка в 1 сек? Я полагаю целью проекта является построение ультразвукового локатора. Если принять скорость звука в воздухе 333 м/с (если правильно со школы помню), то максимальная дальность Вашего устройства с секундной паузой будет около 150м. Однако, мне не представляется реальным получить радиус действия более где-то 10м. Или причина в секундной задержке - экономия токопотребления? Проясните этот момент. Может заодно схемкой устройства поделитесь, можно через ЛС.
Вс май 21, 2017 20:04:07
Скорее всего это частота осциллятора DCO, так как я в коде не подключаю внешний кварц.
Да, вы правы, это схема локатора, который должен измерять расстояние до 3-х метров.
3 метра это около 0,018 сек. Сейчас я могу добиться только измерения расстояния до 0.5 метров.
Так как используется диффузионный режим работы ультразвукового датчика, то лучше иметь большую паузу таймера а, для того, чтобы пластины в датчике могли успокоиться и без проблем переключиться на нужный режим.
Вс май 21, 2017 20:33:15
Хорошо, пусть будет 1 сек. А с чем связано ограничение в 0.5м сейчас? Я не увидел новых вопросов в последнем сообщении. Полагаю, проблемы с программированием таймеров решены (?)
Кстати, что в проекте фиксировано кроме устройства дальномера? Я имею в виду МК и датчик. Этот уж слишком древний. А насчёт датчика - если устроит дальность до 2м с погрешностью около 3%, посмотрите на датчики другого типа VL6180X.
Вс май 21, 2017 21:14:24
0,5 метров не связано ни с чем. Просто максимальное время паузы можно сделать - 7 мсек, а это как раз 0,5 м.
Пыталась с помощью delay(); попробовать сделать задержку, но не выходит сделать больше паузу чем 7 мсек. Вопрос мой тот же, как реализовать паузу в 1 сек? Что такое прескейлер, а также что такое 32-битный счётчик прерывания и есть ли у вас пример его использования?
Вс май 21, 2017 21:53:55
Я всё-таки не понял какие проблемы с получением задержки в 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мсек.
Вт май 23, 2017 12:10:11
Большущее спасибо Вам, 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 В, то есть по логике он должен переходить в прерывание.
Powered by phpBB © phpBB Group.
phpBB Mobile / SEO by Artodia.