I have a code that generates a PWM. Can someone tell me how to add code to the existing to generate a PWM and give it a delay to certain amount and get that out through one of the ports?
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.
I have a code that generates a PWM. Can someone tell me how to add code to the existing to generate a PWM and give it a delay to certain amount and get that out through one of the ports?
Hi Yashaswy!
Here is some code for you that does the following: The first PWM is on P1.4 (TB0.1) and has a duty-cycle of 16ms. The second PWM on P1.3 (TA1.2) starts 12ms later and also has a duty-cycle of 16ms. Both have a period of 50ms.
Connect your probes here:
#include <msp430fr5969.h> #define PERIOD 50000 // 50ms @ SMCLK = 1MHz #define DUTY_CYCLE 16000 // 16ms @ SMCLK = 1MHz #define DELAY 12000 // 12ms @ SMCLK = 1MHz void main( void ) { WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer P1SEL0 = 0x08 | 0x10; // Enable timer function for P1.3 (TA1.2) and P1.4 (TB0.1) P1DIR = 0x08 | 0x10; // Set P1.3 (TA1.2) and P1.4 (TB0.1) to output direction PM5CTL0 &= ~LOCKLPM5; // Disable GPIO power-on default high-impedance mode CSCTL0_H = CSKEY >> 8; // Unlock CS registers CSCTL1 = DCOFSEL_6; // Set DCO = 8MHz CSCTL2 = SELA__VLOCLK | SELS__DCOCLK | SELM__DCOCLK; // Set ACLK = VLOCLK, SMCLK = MCLK = DCOCLK CSCTL3 = DIVS__8 | DIVM__8; // Set SMCLK and MCLK divider to 8 -> 1MHz CSCTL0_H = 0; // Lock CS registers TB0CCR0 = PERIOD - 1; // Period for 1st PWM TB0CCR1 = DUTY_CYCLE; // Duty cycle for 1st PWM TB0CCR2 = DELAY; // Delay to start 2nd PWM TB0CCTL1 = OUTMOD_7; // TB0.1 reset/set mode (P1.4) TB0CCTL2 = CCIE; // Compare interrupt for 12ms delay TA1CCR0 = PERIOD - 1; // Period for 2nd PWM TA1CCR2 = DUTY_CYCLE; // Duty cycle for 2nd PWM TA1CCTL2 = OUTMOD_7; // TA1.2 reset/set mode (P1.3) TB0CTL = TBSSEL_2 | ID_0 | MC_1 | TBCLR; // 1st PWM: SMCLK, divider 1, up-mode, clear __bis_SR_register( GIE ); // Enable interrupts while( 1 ); // Endless loop } #pragma vector = TIMER0_B1_VECTOR __interrupt void TIMER0_B1_ISR( void ) { TA1CTL = TASSEL_2 | ID_0 | MC_1 | TACLR; // 2nd PWM: SMCLK, divider 1, up-mode, clear TB0CCTL2 = 0x00; // Clear compare interrupt - executed only once }
P1.4 (TB0.1) is the purple line, P1.3 (TA1.2) is the blue one:
Have fun!
Dennis
OCY,
As I mentioned I added other two pulses from Timer_0_B that are expected to start and end at same time. The oscilloscope has 4 probes, so 4 pulses with 2 starting at same time and other 2 with an offset to each other. Also when I'm checking the probes, P1.4 and P1.5 are giving correct output but P1.2 and P1.0 are not able to. This is the modified code. Please find out what I'm missing here. Thank you :)
#include <msp430.h>
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // Stop WDT
// Cofigure GPIO
P1DIR = BIT2 | BIT0;
P1SEL0 = BIT2 | BIT0;
P1DIR = BIT4 | BIT5;
P1SEL0 = BIT4 | BIT5;
PM5CTL0 &= ~LOCKLPM5;
CSCTL0_H = CSKEY >> 8; // Unlock CS registers
CSCTL1 = DCOFSEL_6; // Set DCO = 8MHz
CSCTL2 = SELA__VLOCLK | SELS__DCOCLK | SELM__DCOCLK;// Set ACLK=VLO SMCLK=DCO
CSCTL3 = DIVA__8 | DIVS__8 | DIVM__8; // Set all dividers
CSCTL0_H = 0; // Lock CS registers
TA0CCR0 = 16000-1;
TA0CCR1 = 20;
TA0CCR2 = 12000-1;
TA0CCTL1 = OUTMOD_7;
TA0CCTL2 = CCIE;
TA0CTL = TASSEL_2 | ID_0 | MC_1 | TACLR;
TA1CCR0 = 16000-1;
TA1CCR1 = 20;
TA1CCTL1 = OUTMOD_7;
TA1CTL = TASSEL__SMCLK | MC__UP | TACLR; // SMCLK, up mode, clear TAR
TB0CCR0 = 4000-1;
TB0CCTL1 = OUTMOD_7; // CCR1 reset/set
TB0CCR1= 20;
TB0CCTL2 = OUTMOD_7; // CCR1 reset/set
TB0CCR2 = 20; // CCR2 PWM duty cycle
TB0CTL = TBSSEL__SMCLK | MC__UP | TBCLR; // SMCLK, up mode, clear TBR
__bis_SR_register(GIE); // Enter LPM0
__no_operation(); // For debugger
while (1);
}
#pragma vector = TIMER0_A1_VECTOR
__interrupt void TIMER0_A1_ISR( void )
{
TA1CTL = TASSEL_2 | ID_0 | MC_1 | TACLR;
TA0CCTL2 = 0x00;
}
Yashaswy, again one can only guess what you want to do...:-\
At the moment your PWMs seem to be the following:
// Timer A0 TA0CCR0 = 16000 - 1; // Period of 16ms TA0CCR1 = 20; // Duty cycle for TA0.1 of 20µs TA0CCTL1 = OUTMOD_7; // Reset/set TA0CCR1 TA0CTL = TASSEL_2 | ID_0 | MC_1 | TACLR; // TA0: SMCLK, divider 1, up mode, clear // Timer A1 TA1CCR0 = 16000 - 1; // Period of 16ms TA1CCR1 = 20; // Duty cycle for TA1.1 of 20µs TA1CCTL1 = OUTMOD_7; // Reset/set TA1CCR1 TA1CTL = TASSEL__SMCLK | MC__UP | TACLR; // TA1: SMCLK, divider 1, up mode, clear // Timer B0 TB0CCR0 = 4000 - 1; // Period of 4ms TB0CCR1 = 20; // Duty cycle for TB0.1 of 20µs TB0CCR2 = 20; // Duty cycle for TB0.2 of 20µs TB0CCTL1 = OUTMOD_7; // Reset/set TB0CCR1 TB0CCTL2 = OUTMOD_7; // Reset/set TB0CCR2 TB0CTL = TBSSEL__SMCLK | MC__UP | TBCLR; // TB0: SMCLK, divider 1, up mode, clear
Are these the desired times for your PWMs?
Dennis
Yeah exactly the same Dennis.. The pulse from Timer A0 and A1 are both have time period of 16ms with a duty cycle of 20us and the pulses from Timer B 0 have a period of 4ms with 20us as the duty cycle.
Regards,
Yashaswy
Yashaswy Akella said:. Also when I'm checking the probes, P1.4 and P1.5 are giving correct output but P1.2 and P1.0 are not able to. This is the modified code. Please find out what I'm missing here. Thank you :)
If you remove your modification, P1.0 and P1.2 will work.
It is your modifications that killed P1.0 and P1.2
Yashaswy Akella said:Please help me this one last time :)
Do you mean you are not going to attempt writing program any more for the rest of your life? If so, I will write this one for you. Otherwise you really need to learn how to write and debug program yourself.
OCY,
I love coding. It's just that I'm not able to and the deadline is approaching. This controller was specified and I need help. I agree writing that 'one last time' was my fault. I'm sorry for that. Please help.
Regards,
Yashaswy
Have a look at this part of your code - the error is located in here:
// Cofigure GPIO P1DIR = BIT2 | BIT0; P1SEL0 = BIT2 | BIT0; P1DIR = BIT4 | BIT5; P1SEL0 = BIT4 | BIT5;
I wouldn't call it "define", but yes, you are overriding your previous made settings for P1SEL0 and P1DIR.
This would have been another option with the existing code:
// Cofigure GPIO P1DIR = BIT2 | BIT0; P1SEL0 = BIT2 | BIT0; P1DIR |= BIT4 | BIT5; P1SEL0 |= BIT4 | BIT5;
Dennis
Thank you so much Dennis, this is working and I'm getting the respective pulses.
Another thing struck me. The pulse from P1.4 (yellow) and the pulse from P1.2 (green) are not starting at the same time - I mean, both of them have the same Duty cycle but have a phase shift. Is there a way to correct that and get the pulses start at the same time?
Regards,
Yashaswy
You can get rid of the shift by using the same timebase for the different PWMs, means one timer module. Timer B0 has 0.1, 0.2, 0.3, 0.4 and 0.5 routed out on the LaunchPad. You can use them instead of all the different timers you are using now. Of course not for the one that has the delay and only if the different PWM timings can all be serviced by one timebase.
Yashaswy Akella said:TB0CCTL3 = OUTMOD_7; // CCR1 reset/set
TB0CCR3 = 20; // CCR2 PWM duty cycle
Both comments do not match the code lines you have written.
Yashaswy Akella said:Can we get the output out of some other port like P1.3 by defining a statement like 'Output from P1.0 must go to P1.3 '
No. Not when using hardware PWM. You can change the output to pins that support the same timer function. For example TB0.1 is available at P2.6 and P1.4, same for other timer outputs. But you cannot choose completely free where to output the signal.
But if you would do it like mentiod here...
Dennis Eichmann said:Use TB0.0 as timebase and TB0.1, 0.2 and 0.3 as duty-cycle for three PWMs with OUTMOD_7. Then use TB0.4 with CCIE and set the CCR register to the delay time you want. Inside the ISR disable the CCIE for TB0.4 and start another timer like TA1 with TA1.0 as timebase and TA1.1 as PWM with OUTMOD_7.
...then all outputs are easy accessible:
**Attention** This is a public forum