|
|
  |
Чудуса msp430f2252 Timer_A в режиме выдачи импульсов, При увеличении частоты на выходе фронт расщепляется! |
|
|
|
Oct 24 2008, 14:40
|
Группа: Новичок
Сообщений: 7
Регистрация: 24-10-08
Пользователь №: 41 156

|
Использовал пример. Частотата внешнего кварца 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 кГц.
|
|
|
|
|
Oct 27 2008, 08:30
|
Группа: Новичок
Сообщений: 7
Регистрация: 24-10-08
Пользователь №: 41 156

|
Использовал пример с сайта 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; } }
|
|
|
|
|
Oct 27 2008, 09:24
|
Группа: Новичок
Сообщений: 7
Регистрация: 24-10-08
Пользователь №: 41 156

|
#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; } }
|
|
|
|
|
Oct 27 2008, 12:31
|
Группа: Новичок
Сообщений: 7
Регистрация: 24-10-08
Пользователь №: 41 156

|
Цитата(rezident @ Oct 27 2008, 13:25)  Попробуйте тактировать ядро (MCLK) от DCO, настроенного на 8МГц-12МГц, а не от кварца (как в вашем примере). Этот пример от TI. Мне важно было точно получить стабильную выходную частоту 130 кГц. Поэтому именно внешний точный кварц использовал. эффект проявляется при частоте > 60-90 кГц на выходе микроконтроллера, когда используется переключение сигнала на выходе 'P1.1/TA0/A1'. Пришлось выполнять программно формирование частоты.
|
|
|
|
|
Oct 27 2008, 13:33
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(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%. Причем не программно, а чисто аппаратно.
|
|
|
|
|
Oct 28 2008, 08:23
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Сегодня наблюдал подобный эффект. Короче, суть в следующем. Если защёлка таймера совпадает раньше, чем заканчивается текущее прерывание, то следующее прерывание возникает через круг таймера, то есть 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 Вот сколько бесполезных действий (выделено жирным). Чёрт! Не выделилось!
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Oct 28 2008, 10:43
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Вобщем, соптимизировал слегка. Код 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мс. В общем, чудеса. В общем, в данной ситуации вижу только один выход. Сажать скоростной выход на отдельный таймер (А) без всяких прерываний. А остальные, менее скоростные - на таймер В в непрерывном режиме с прерываниями.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Oct 28 2008, 14:41
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(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; }
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|