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 am new to TI microcontrollers in general. I am using MSP430F5438.
I am trying to generate a PWM signal on my port 2.2 with a variable duty cycle. Which i am able to do but I need to sweep the PWM signal from a duty cycle 0-100% automated. Right now I am manually changing the
duty cycle value.
I was thinking of a Ramp or some sort of looping which I have tried but doesnt seem to work.
My working code for the PWM with manual change of duty cycle is as follows:
static void pwm_main(void)
{
WDTCTL = WDTPW+WDTHOLD; // Stop watchdog timer
// Set up XT1
P7SEL |= 0x13; // Analog function for XT1 Pins and
// setting P7.4 as ADC for DIM_VOUT
//UCSCTL6 &= ~XT1DRIVE_3; // Lowest drive strength
//UCSCTL6 |= XCAP_0 ; // Internal load cap
P2SEL |= 0x04; // P2 option select
P2DIR |= 0x04; // P2 outputs
//TA1R=0;
TA1CCR0 = 512-0; // PWM Period
TA1CCTL1 = OUTMOD_7; // CCR1 reset/set
TA1CCR1 = 128; // CCR1 PWM Duty Cycle
// | P2.2/TA2|--> CCR1 - 383-->75% PWM
// | P2.2/TA2|--> CCR1 - 128-->25% PWM
// | P2.2/TA2|--> CCR1 - 64-->12.5% PWM
// | P2.2/TA2|--> CCR1 - 32--> 6.26% PWM
// | P2.2/TA2|--> CCR1 - 16--> 3.13% PWM
// | P2.2/TA2|--> CCR1 - 8--> 1.56% PWM
TA1CTL = TASSEL_2 + MC_1 +TA1R ; // SMCLK, upmode, clear TA1R
//__bis_SR_register(GIE); // Enter LPM0, enable interrupts
}
A manual sweep of the TA1CCR1 appears to be the only way to sweep through duty cycle values. I would assume that you are performing the updates of the TA1CCR1 in an interrupt service routine triggered from the compare.
The interrupt service routine can then sweep through values to plug into the TA1CCR1.
The MSP430F5438 does not map the TA1CCR1 CCIFG to the DMA engine. This would have been another "automatic" way to sweep through values. For reference, the MSP430F5438 has TA1CCR0 and TA1CCR2 are mapped to DMA
event triggers.
Hi Brandon,
I have tried to use the while loop in which i generate a ramp for the values of TA1CCR1.
So the PWM seems to be sweeping from 0 to 100 % duty cycle. I have introduced a delay function to slow down the ramp. Which seems to be working...Also I am not enabling interrupts. If I do enable the interrrupt my other modules of the code don't seems
to be working properly.
Please give me more suggestions to improve it.
My code is as follows:
static void pwm_main(void)
{
WDTCTL = WDTPW+WDTHOLD; // Stop watchdog timer
// Set up XT1
P7SEL |= 0x13; // Analog function for XT1 Pins and
// setting P7.4 as ADC for DIM_VOUT
//UCSCTL6 &= ~XT1DRIVE_3; // Lowest drive strength
//UCSCTL6 |= XCAP_0 ; // Internal load cap
P2SEL |= 0x04; // P2 option select
P2DIR |= 0x04; // P2 outputs
//TA1R=0;
// PWM Period
while(1)
{
TA1CCR0 =512-0;
for(sweep=0; sweep <=512; sweep++)
{
TA1CCTL1 = OUTMOD_7; // CCR1 reset/set
TA1CCR1 = sweep; // CCR1 PWM Duty Cycle
delay(4500);
}
TA1CTL = TASSEL_2 + MC_1 +TA1R; // SMCLK, upmode, clear TA1R
}
// | P2.2/TA2|--> CCR1 - 383-->75% PWM
// | P2.2/TA2|--> CCR1 - 128-->25% PWM
// | P2.2/TA2|--> CCR1 - 64-->12.5% PWM
// | P2.2/TA2|--> CCR1 - 32--> 6.26% PWM
// | P2.2/TA2|--> CCR1 - 16--> 3.13% PWM
// | P2.2/TA2|--> CCR1 - 8--> 1.56% PWM
//__bis_SR_register(GIE); // Enter LPM0, enable interrupts
}
I don't know that I have any further suggestions. The code snip you provided appears to be working as you mentioned.
What are your application needs which need to be explored?
hi,
Am sorry if am silly inasking this. i tried using this code for generating pwm for my application. am not getting the pwm when i see it in the osciloscope. and i found a error in the code which says the sweep is undefined. as indicated port as the output port where do i place my osciloscope to see my pwm signal. i also wanted the pwm at 1650Hz and 1850Hz. please do help me in getting my pwm signal.
regards,
mithi
Arte you sure you're talkign about PWM?Mithilesh Jagannathan said:i also wanted the pwm at 1650Hz and 1850Hz.
PWM stands for Pulse Width Modulation. that is, you have a constant, fixed (and mostly unimportant) frequency and modulate the ratio of on/off.
What you seem to want is to have different frequency outputs. Probably with a fixed duty cycle of 50% (square wave).
How PWM works:
The timer counts with a certain frequency. With CCR0 you set the upper limit for the timer. So setting CCR0 to 99 (100-1) lets the timer count from 0 to 99 and then 0 again (100 ticks per cycle, as 0 counts too). Any other number of ticks than 100 is possible, then multiply all values with the same factor)
The PWM dfrequency is fixed to ftimerclock/100. (or whichever value you use for setting CCR0)
So CCR0 defines the PWM frequency in timer ticks.
THen you set up CCR1 to CCRx to a value between 0 and 100. When the timer counts to the value of CCRx, the CCRx unit output does the configured action (set/reset/toggle its assigned output pin). If one of the double-action modes is configured, the sewcond action takes place when the timer counts to 0.
So using reset/set mode, setting CCR1 to 100 will set the output when teh timer rolls to 0 and never reset it (as the timer never reaches 100) = 100% duty cycle. If you set it to 1, the output will be set when the timer rolls to 0, and reset when the timer counts to 1, one tick later = 1% duty cycle.
0% duty cycle isn't possible as it is undefined which action happens when set and reset happen at the same tick. But well, technically, neither 0% nor 100% DC can be considered to be any frequency at all (0Hz)
For different frequencies, you have to alter CCR0. the other CCRs are useless here, as they will all produce the same frequency, only different duty cycles.
When using CCR0 to generate different frequencies on teh CCR0 output pin, you have two choices.
1) you use the toggle mode. Then the resulting output frequency is 1/2 the PWM frequency, since the output only toggles on each timer cycle. The output will have 50% dity cycle. For 1MHz timer clock and a frequency of 1650Hz, you'll have to write 302 to CCR0.
2) you use set/reset mode. In this mode, the output will go high when the timer reaches CCR0 and low again one tick later when the timer rolls to 0. This way you get the full frequency, but the duty cycle is very small (only one timer tick). For 1650Hz, you had to write 605 to CCR0, and you'd get a duty cycle of 0.165% == a pulse of 1µs.
In any case, whether you do PWM or switch frequencies, you should be aware that you have to somehow synchronize changing ht esettigns with the current timer value. If you fail so, you'll end up with aliasing effects for a complete timer cycle. (e.g. if you lower a setting while the timer has already passed the new value, it won't trigger an output change until it raches the new value nex ttime - one complete timer cycle later)
And coming back to your code, a delay of 4500 is probably shorter than one PWM cycle (based on MCLK and timer clock speed, e.g. if MCLK is 16MHz and the timer runs on 1MHz or even less), so you won't see any predictable result.
hi jens-michael,
thanks a lot for your reply. i will try this today and get back to you for further clarifications.
regards,
mithilesh
**Attention** This is a public forum