Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Чудуса msp430f2252 Timer_A в режиме выдачи импульсов
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > MSP430
progvlad
Использовал пример. Частотата внешнего кварца 8 Мгц. Необходимо сформировать аппаратно на пине процессора 130 кГц.


Выполнил настройку таймера и источника тактовых сигналов. До частот ~40-50 кГц - нормальный меандр на выходе. Но при частотатах выше - полные чудеса: фронты расщепляются на импульсы и на других незадействованных выходах появляются импульсы от задействованного таймера.

// P1.1/TA0|--> TACCR0
// P1.2/TA1|--> TACCR1
// P1.3/TA2|--> TACCR2



// Timer A0 interrupt service routine
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A0(void)
{
TACCR0 += 200; // Add Offset to TACCR0
}

// Timer_A3 Interrupt Vector (TAIV) handler
#pragma vector=TIMERA1_VECTOR
__interrupt void Timer_A1(void)
{
switch (TAIV) // Efficient switch-implementation
{
case 2: TACCR1 += 1000; // Add Offset to TACCR1
break;
case 4: TACCR2 += 10000; // Add Offset to TACCR2
break;
case 10: P1OUT ^= 0x01; // Timer_A3 overflow
break;
}
}


Как лечить не знаю. Пришлось программно выполнить формирование 130 кГц.
rezident
Давайте полный проект. А то непонятно как систему тактирования инициализировали и в каком режиме(ах) таймер используется?
Dog Pawlowa
Цитата(progvlad @ Oct 24 2008, 17:40) *
Использовал пример. Частотата внешнего кварца 8 Мгц. Необходимо сформировать аппаратно на пине процессора 130 кГц.
Выполнил настройку таймера и источника тактовых сигналов. До частот ~40-50 кГц - нормальный меандр на выходе. Но при частотатах выше - полные чудеса: фронты расщепляются на импульсы и на других незадействованных выходах появляются импульсы от задействованного таймера.

Ну, если незадействованные сконфигурированы как входы, а смотрелось осциллографом, то ситуация всерьез не рассматривается.
А расщепление на импульсы ... Трудно поверить... Глазком бы взглянуть...
progvlad
Использовал пример с сайта www.ti.com 'msp430x22x4_ta_09.c' - MSP430F22x4 Demo - Timer_A, Toggle P1.0-3, Cont. Mode ISR, HF XTAL ACLK

При уменьшении загружаемой константы '1000' увеличиваем частоты на выходе микроконтроллера. При частоте больше 60 кГц необходимо смотреть фронты. При частоте около 100 кГц следующая картина:

Полупериод
_|-|_-|____________________|_|-|__


// Timer_A3 Interrupt Vector (TAIV) handler
#pragma vector=TIMERA1_VECTOR
__interrupt void Timer_A1(void)
{
switch (TAIV) // Efficient switch-implementation
{
case 2: TACCR1 += 1000; // Add Offset to TACCR1
break;
case 4: TACCR2 += 10000; // Add Offset to TACCR2
break;
case 10: P1OUT ^= 0x01; // Timer_A3 overflow
break;
}
}
MrYuran
Цитата(rezident @ Oct 24 2008, 17:56) *
Давайте полный проект. А то непонятно как систему тактирования инициализировали и в каком режиме(ах) таймер используется?
progvlad
#include "msp430x22x4.h"

void main(void)
{
volatile unsigned int i;
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
BCSCTL1 |= XTS; // ACLK= LFXT1= HF XTAL
BCSCTL3 |= LFXT1S1; // LFXT1S1 = 3-16Mhz

do
{
IFG1 &= ~OFIFG; // Clear OSCFault flag
for (i = 0xFF; i > 0; i--); // Time for flag to set
}
while (IFG1 & OFIFG); // OSCFault flag still set?
BCSCTL2 |= SELM_3; // MCLK = LFXT1 (safe)

P1SEL |= 0x0E; // P1.1 - P1.3 option select
P1DIR |= 0x0F; // P1.0 - P1.3 outputs
TACCTL0 = OUTMOD_4 + CCIE; // TACCR0 toggle, interrupt enabled
TACCTL1 = OUTMOD_4 + CCIE; // TACCR1 toggle, interrupt enabled
TACCTL2 = OUTMOD_4 + CCIE; // TACCR2 toggle, interrupt enabled
TACCR0 = 200;
TACCR1 = 1000;
TACCR2 = 10000;
TACTL = TASSEL_1 + MC_2 + TAIE; // ACLK, contmode, interrupt enabled

__bis_SR_register(LPM3_bits + GIE); // Enter LPM3 w/ interrupts
}

// Timer A0 interrupt service routine
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A0 (void)
{
TACCR0 += 200; // Add Offset to TACCR0
}

// Timer_A3 Interrupt Vector (TAIV) handler
#pragma vector=TIMERA1_VECTOR
__interrupt void Timer_A1(void)
{
switch (TAIV) // Efficient switch-implementation
{
case 2: TACCR1 += 1000; // Add Offset to TACCR1
break;
case 4: TACCR2 += 10000; // Add Offset to TACCR2
break;
case 10: P1OUT ^= 0x01; // Timer_A3 overflow
break;
}
}
rezident
Попробуйте тактировать ядро (MCLK) от DCO, настроенного на 8МГц-12МГц, а не от кварца (как в вашем примере). У вас не обозначен вектор NMI в котором должна происходить обработка ошибки работы кварцевого генератора. При первом же сбое он (MCLK) перейдет на тактирование от DCO, частота которого у вас по умолчанию около 1МГц. Естественно, что при этом прерывания с частотой 100кГц просто не будут успевать обрабатываться.
И еще замечание. При первой инициализации регистров НЕ пользуйтесь битовыми масками, а инициализируйте их (регистры) явными значениями.
progvlad
Цитата(rezident @ Oct 27 2008, 13:25) *
Попробуйте тактировать ядро (MCLK) от DCO, настроенного на 8МГц-12МГц, а не от кварца (как в вашем примере).


Этот пример от TI. Мне важно было точно получить стабильную выходную частоту 130 кГц. Поэтому именно внешний точный кварц использовал. эффект проявляется при частоте > 60-90 кГц на выходе микроконтроллера, когда используется переключение сигнала на выходе 'P1.1/TA0/A1'. Пришлось выполнять программно формирование частоты.
rezident
Цитата(progvlad @ Oct 27 2008, 17:31) *
Этот пример от TI.
Вот именно что пример, а не конечная программа в которой предусмотрены все нюансы, в т.ч. особенности вашей топологии трассировки кварцевого генератора, например.
Цитата(progvlad @ Oct 27 2008, 17:31) *
Мне важно было точно получить стабильную выходную частоту 130 кГц. Поэтому именно внешний точный кварц использовал. эффект проявляется при частоте > 60-90 кГц на выходе микроконтроллера, когда используется переключение сигнала на выходе 'P1.1/TA0/A1'. Пришлось выполнять программно формирование частоты.
Ядро, исполняющее программу, и периферийные модули могут тактироваться от разных источников. Ядро имеет смысл тактировать от DCO, т.к. это внутренний генератор, наименее склонный к воздействию внешних помех. Периферию при этом вы можете спокойно тактировать от кварцевого генератора. При кварце 8МГц вы можете получить частоту 130кГц с основной относительной погрешностью менее 0,8%. Причем не программно, а чисто аппаратно.
MrYuran
Сегодня наблюдал подобный эффект. Короче, суть в следующем.
Если защёлка таймера совпадает раньше, чем заканчивается текущее прерывание, то следующее прерывание возникает через круг таймера, то есть 0xffff * T, где Т - период тактовой частоты таймера.

Попробовал 100кГц, тоже не тянет. И вот почему:
Код
2418:    0f 12           push    r15;
     241a:    0e 12           [b]push    r14    [/b];
     241c:    0d 12        [b]push    r13    [/b];
     241e:    0c 12           [b]push    r12    [/b];
     2420:    b0 12 82 13     [b]call    #4994[/b];#0x1382
     2424:    3c 41           [b]pop    r12    [/b];
     2426:    3d 41           [b]pop    r13    [/b];
     2428:    3e 41           [b]pop    r14    [/b];
     242a:    3f 41           pop    r15;
     242c:    00 13           reti            

1382:    1f 42 92 01     mov    &0x0192,r15;0x0192
    1386:    3f 50 14 00     add    #20,    r15;#0x0014
    138a:    82 4f 96 01     mov    r15,    &0x0196;
    138e:    b2 50 28 00     add    #40,    &0x0192;#0x0028
    1392:    92 01
    1394:    1f 42 96 01     mov    &0x0196,r15;0x0196
    1398:    2f 52           add    #4,    r15;r2 As==10
    139a:    82 4f 94 01     mov    r15,    &0x0194;
    139e:    30 41           ret


Вот сколько бесполезных действий (выделено жирным).
Чёрт! Не выделилось!
MrYuran
Вобщем, соптимизировал слегка.
Код
interrupt (TIMERB0_VECTOR) Timerb_ccr0(void)
{
    //PulseRecharge();
    TBCCR2 = TBCCR0 + 20u;//HalfPeriod;                // Обозначили следующий фронт Gen
    TBCCR0 = TBCCR2 + 20u;//HalfPeriod;            // Будущий спад сигналов Gen и F
    TBCCR1 = TBCCR2 + 4u;//FDelay;                // Фронт F
}

По TBCCR2 встаёт 1-й фронт, по TBCCR1 с небольшой задержкой - 2й.
По TBCCR0 оба падают. Использую OUTMODE_3 (Установка/сброс).
Листинг:
Код
    23fa:    0f 12           push    r15    ;
    23fc:    1f 42 92 01     mov    &0x0192,r15;0x0192
    2400:    3f 50 14 00     add    #20,    r15;#0x0014
    2404:    82 4f 96 01     mov    r15,    &0x0196;
    2408:    1f 42 96 01     mov    &0x0196,r15;0x0196
    240c:    3f 50 14 00     add    #20,    r15;#0x0014
    2410:    82 4f 92 01     mov    r15,    &0x0192;
    2414:    1f 42 96 01     mov    &0x0196,r15;0x0196
    2418:    2f 52           add    #4,    r15;r2 As==10
    241a:    82 4f 94 01     mov    r15,    &0x0194;
    241e:    3f 41           pop    r15    ;
    2420:    00 13           reti

Эффект ещё забавнее.
1 круг таймера (15мс) идёт частота 100кГц, дальше ещё круг - тишина.
На другом выходе (который с задержкой) идут одиночные импульсы 4мкс через 15мс.

В общем, чудеса.


В общем, в данной ситуации вижу только один выход.
Сажать скоростной выход на отдельный таймер (А) без всяких прерываний.
А остальные, менее скоростные - на таймер В в непрерывном режиме с прерываниями.
rezident
Цитата(MrYuran @ Oct 28 2008, 15:43) *
В общем, в данной ситуации вижу только один выход.
Сажать скоростной выход на отдельный таймер (А) без всяких прерываний.
А остальные, менее скоростные - на таймер В в непрерывном режиме с прерываниями.
Выход гораздо прозаичнее. Нужно разделить запись нового значения регистра сравнения и вычисление следующего значения (полу)периода. Сначала запись, затем вычисление.
Код
#pragma vector=TIMERA0_VECTOR
#pragma type_attribute=__interrupt
void TimerA0_ISR(void)
{ static unsigned short newReg=HALFPERIOD*2;
  TACCR0=newReg;
  newReg+=HALFPERIOD;
}
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.