This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi,
I'm seeing some odd behavior with the high resolution Timer D generating 2 center aligned PWM signals with varying dead time.
The PWM frequency is 132kHz, and the min and max duty are such that it does not enter the "not recommended" minimum on time.
I have an interrupt that increases the CCR register by one count every second. This is latched at TDR=0, so the PWM updates without glitching.
Observation 1: Instead of seeing the duty cycle increase by the expected ~16ns per second, it increases by 125ns every eight seconds.
Observation 2: When I look at both signals at once, for the 7 second intervals where the duty cycle remains unchanged, one PWM signal marches forward by ~16ns, only to reset to its starting position with the now increased by 125ns duty cycle on the 8th second.
Question: Is this possibly something I've configured wrong or is there a hidden/undocumented feature here that I've stumbled upon?
I've included the pwm setup routine and duty cycle update routine:
Edward
I'm running off a 32k768Hz crystal, using the DCO/FLL to generate a 16MHz SMCLK, which is used as the source for TimerD0 hi freq generator which is locked on at 8x to make 128MHz timer clock.
void configure_pwm(void)
{
//reset timer counts and direction:
TD0CTL0 = TDCLR;
TD0HCTL0 = 0; // kill the clock if it is still running
TD0HINT &= ~TDHLKIFG; // clear FLL lock Flag
//setup TimerD0 High speed clock
TD0HCTL1 = TDHCLKCR; // input is greater than 15Mhz
TD0CTL0 = TDSSEL_2; // set the input clock for the FLL to sync to.
TD0HCTL0 = //TDHFW | // Fast Wakeup?
TDHD_0 | // divider _0: /1 _1: /2 _2: /4 _3: /8
TDHM_0 | // multiplier _0: x8 _1: x16
TDHRON | // force High-res timer on - needs to be turned off at some point
// TDHEAEN | // enhanced accuracy?! This seems to add jitter
TDHREGEN | // sync to input clock - Closed loop running mode
TDHEN; // enable high speed clock
//set up timer for 132kHz
//TIMERD0:
TD0CTL1 = TDIDEX_0 | // _0: /1 _1: /2 _2: /3 ... _7: /8
TDCLKM_2 ; // _0: Ext Clk _1: Hires Clk _2: previous TDx Clk ### NULL for TD0 ###
TD0CTL0 = TDCLGRP_0 | // channels individual
CNTL_0 | // _0: 16Bit, _1: 12bit _2: 10bit _3: 8bit
TDSSEL_2 | // _0: TDCLK, _1: ACLK _2: SMCLK _3: inv TDCLK
ID_0 | // _0: /1 _1: /2 _2: /4 _3: /8
MC_3 | // _0: stop _1: up to TDCL0 _2: up overflow _3: up/down
TDCLR ; // Now that the clock to the timer is stopped, reset any timer start.
TD0CTL2 = 0; // channel capture mode register
TD0CCTL0 = 0; // channel 0 capture/compare settings
TD0CCTL1 = OUTMOD_2 | // PWM 0 - centred around count of zero
CLLD_1;
TD0CCTL2 = OUTMOD_6 | // PWM 180 - centred around max count
CLLD_1;
TD0CL0 = 486; // 128Mhz / 486 / 2 = 132kHz
TD0CL1 = 10; // minimum PWM_0 duty cycle
TD0CL2 = 486-10; // minimum PWM_180 duty cycle
while(!(TD0HINT | TDHLKIFG)); // wait for the PLL to lock
//Start!
TD0CTL1 = TDCLKM_1; // connect the timer to the hi res FLL
//get outputs setup to be active high, inactive low.
P1OUT &= ~BIT7;
P2OUT &= ~BIT0;
P1DIR |= BIT7;
P2DIR |= BIT0;
//set up GPIO ports for peripheral
P1SEL |= BIT7;
P2SEL |= BIT0;
}
void pwm_set_duty(unsigned int duty)
{
if( duty > PWM_Duty_Max) // ensures minimum duty cycle maintained
duty = PWM_Duty_Max;
if( duty < PWM_Duty_Min) // ensures successful update when using fast clock
duty = PWM_Duty_Min;
TD0CCR1 = duty;
duty = 486 - duty;
TD0CCR2 = duty;
}
I have no experience wiht the high-resolution timers, but I dimly remember from browsign through the description, that there was some granularity that was coarser than the possible settings would indicate. It could explain the 125 (not 128?) ms steps even though you change by 16ms.
I believe the 125ns is a function of the 16MHz clock (1/8MHz because up/down mode effectively doubles the update period)
The ~16ns I mentioned is actually one eighth of the 125ns, 15.6ns or so. Or 2 x 1/128MHz - which is the resolution I am expecting.
The FLL is set at 8 times the SMCLK of 16MHz.
I tried running directly off the 16MHz clock (and not enabling the high frequency generator) and the observed symptoms disappear.
I thought I had thoroughly looked through the msp 5/6 user manual. Would you have seen this granularity comment there or somewhere else?
Just as a follow up: Timer D does not correctly count down in High speed mode. This unfortunately limits is use as a high resolution PWM generator to the upcounting modes only.
A TI engineer has confirmed this behavior.
From my own investigation, it looks as if the high speed counting bits (3bits for x8, 4bits for x16) continue to count up, so the turn around point (up->down counting) is affected, and also any Capture/compare event that occurs on the down count.
For my application the only thing that could be done was revert to the standard speed clock, but other workarounds are possible in some applications.
I had hoped to have seen this in the device errata sheets by now. In any event, the flaw is now documented on the 'net.
It was in a forum post.Edward Cheeseman said:Would you have seen this granularity comment there or somewhere else?
Final follow up:
This behavior has been documented in the latest errata sheet (30 Oct 2013, rev H) number TD2.
http://www.ti.com/lit/er/slaz249h/slaz249h.pdf
Advice is that High Speed mode only works while set to up-counting only. No workarounds yet.
I’d say so. If it works when counting up and being reset at a variable count (CCR0), it should also work if counting up to a fixed point (65535). It’s the down direction that causes trouble.
**Attention** This is a public forum