EmbeddedRelated.com
Forums

TimerA and PWM

Started by Jeff Allan August 19, 2003
Hello All
This is my first post to the MSP430 news group, and as
you have guessed I am new to the MSP430.
I am trying to get the PWM to work on a MSP430F1232
chip, I am using the example fet120_ta_pwm01.c.
Which works fine, but I would like to use the Timer_A
in continous mode as opposed to up mode in the
example.
Because I am using Timer_A for a 1ms tick.
Can any one help!
Thanks in advance.

Jeff Allan


Beginning Microcontrollers with the MSP430

This isn't, or shouldn't be a problem. Timer A has three capture
compare 
registers. To generate PWM you typically use CCR0 to generate the period 
and CCR1 or CCR2 to generate the pulse. IIRC the example uses the up 
mode only, and resets when TAR = CCR0. This simplifies everything 
because you don't even need an ISR. If you want PWM in continuous mode 
you simply have to handle CCR0 and CCR1 or 2 in an ISR. Let's assume you 
are generating your 1ms tick with CCR2, and are using CCR1 for the PWM, 
along with CCR0. You will need an ISR for CCR2 anyway. So, having 
configured Timer A in continuous mode you will need the following 3 ISR's:-

Let's assume an 8MHz crystal
20kHz PWM
1msec heartbeat

;****	CONSTANTS

PERIOD		EQU	400		;VERY LOW, SEE GOTCHA'S LATER
HEARTBEAT	EQU	8000

TA0_ISR:
	BIC	#CCIFG,&CCTLA0		;CLEAR THE FLAG ANYWAY
	ADD	#PERIOD,&CCR0		;ADD THE PERIOD TO THE OLD VALUE
	RETI

TA1_ISR:
	BIC	#CCIFG,&CCTLA1		;CLEAR THE INT FLAG
	MOV	&CCR0,&CCR1		;GET THE NEXT PERIOD START
	ADD	&DUTY_CYCLE,&CCR1	;ADD THE PULSE LENGTH TO IT
	RETI

TA2_ISR:
	BIC	#CCIFG,&CCTLA2		;OBVIOUS BY NOW
	ADD	#HEARTBEAT,&CCR2	;ADD THE VALUE FOR 1MS TO CCR2
	BIS	#TICK,&FLAG_REGISTER	;SET A FLAG BIT TO INDICATE TICK 					;HAS 
OCCURRED
	RETI

There is a potential GOTCHA with this method. Simply that motor PWM 
should have a frewquency around 20kHz, and this equates to only 400 
clock cycles. This is why the MSP implements this generally using UP 
mode, no ISR's. Imagine what will happen when you need a 2% duty cycle, 
or a 98% duty cycle. The short time differences between the ISR 
occurences are too short. Now you can handle this in the code that 
determines the duty cycle, assuming that it isn't fixed, and you can 
arrange just for 1 ISR to handle both times, of course you must 
generally make that ISR the CCR1 ISR. In code you would adopt different 
ISR strategies based upon the duty cycles. If duty cycle is short you 
only use CCR1 to set up both of the next time periods, if duty cycle is 
very long you do the same but you must compensate the first time that 
the duty cycle exceeds your limit, whatever you determine that to be.

Of course you asked for a method of doing this using continuous mode on 
Timer A. I have given you the most direct, and hopefully understandable 
way. There are many ways to do this. If all you are concerned about is a 
heartbeat there is a simpler way of doing it. Use the code in the 
example, using CCR0 and CCR1 in up mode, I assume that CCR0 is set to 
400 for a 20kHz period, giving a convenient 4 clocks per % duty cycle as 
well. Now simply count the number of periods of the PWM, using the 
TimerA overflow ISR. Since the period is 50 usecs, you need 20 PWM 
periods per TICK. In the INIT routines enable the Timer_A overflow 
interrupt (this occurs as the Timer counts from CCR0 to 0). In the Timer 
overflow interrupt simply implement a count to 20 and set a flag when 
this occurs.

I strongly recommend you use a flag to signal the heartbeat, since you 
don't want to process the periodic events at 1msec in an ISR. The golden 
rule for ISRs is short and fast, try to avoid manipulating port pins, or 
registers. If you do remember that you must preserve the original state 
on entry to the ISR, and recover them on exit.

A typical ISR for me simply clears the interrupt flag, sets up a flag, 
or semaphore to the main program, or stuffs a task into a queue, sets up 
  the next interrupt condition if necessary and exits.

Al


Jeff Allan wrote:
> Hello All
> This is my first post to the MSP430 news group, and as
> you have guessed I am new to the MSP430.
> I am trying to get the PWM to work on a MSP430F1232
> chip, I am using the example fet120_ta_pwm01.c.
> Which works fine, but I would like to use the Timer_A
> in continous mode as opposed to up mode in the
> example.
> Because I am using Timer_A for a 1ms tick.
> Can any one help!
> Thanks in advance.
> 
> Jeff Allan
> 
> 
> 
> .
> 
>  
> 
> ">http://docs.yahoo.com/info/terms/ 
> 
> 
> 


Thankyou
For the comprehensive reply.

Jeff

--- In msp430@msp4..., onestone <onestone@b...> wrote:
> This isn't, or shouldn't be a problem.
Timer A has three capture 
compare 
> registers. To generate PWM you typically use CCR0
to generate the 
period 
> and CCR1 or CCR2 to generate the pulse. IIRC the
example uses the 
up 
> mode only, and resets when TAR = CCR0. This
simplifies everything 
> because you don't even need an ISR. If you want PWM in continuous 
mode 
> you simply have to handle CCR0 and CCR1 or 2 in an
ISR. Let's 
assume you 
> are generating your 1ms tick with CCR2, and are
using CCR1 for the 
PWM, 
> along with CCR0. You will need an ISR for CCR2
anyway. So, having 
> configured Timer A in continuous mode you will need the following 3 
ISR's:-
> 
> Let's assume an 8MHz crystal
> 20kHz PWM
> 1msec heartbeat
> 
> ;****	CONSTANTS
> 
> PERIOD		EQU	400		;VERY LOW, SEE 
GOTCHA'S LATER
> HEARTBEAT	EQU	8000
> 
> TA0_ISR:
> 	BIC	#CCIFG,&CCTLA0		;CLEAR THE FLAG ANYWAY
> 	ADD	#PERIOD,&CCR0		;ADD THE PERIOD TO THE OLD 
VALUE
> 	RETI
> 
> TA1_ISR:
> 	BIC	#CCIFG,&CCTLA1		;CLEAR THE INT FLAG
> 	MOV	&CCR0,&CCR1		;GET THE NEXT PERIOD START
> 	ADD	&DUTY_CYCLE,&CCR1	;ADD THE PULSE LENGTH TO IT
> 	RETI
> 
> TA2_ISR:
> 	BIC	#CCIFG,&CCTLA2		;OBVIOUS BY NOW
> 	ADD	#HEARTBEAT,&CCR2	;ADD THE VALUE FOR 1MS TO CCR2
> 	BIS	#TICK,&FLAG_REGISTER	;SET A FLAG BIT TO INDICATE 
TICK 					;HAS 
> OCCURRED
> 	RETI
> 
> There is a potential GOTCHA with this method. Simply that motor PWM 
> should have a frewquency around 20kHz, and this equates to only 400 
> clock cycles. This is why the MSP implements this generally using 
UP 
> mode, no ISR's. Imagine what will happen when
you need a 2% duty 
cycle, 
> or a 98% duty cycle. The short time differences
between the ISR 
> occurences are too short. Now you can handle this in the code that 
> determines the duty cycle, assuming that it isn't fixed, and you 
can 
> arrange just for 1 ISR to handle both times, of
course you must 
> generally make that ISR the CCR1 ISR. In code you would adopt 
different 
> ISR strategies based upon the duty cycles. If duty
cycle is short 
you 
> only use CCR1 to set up both of the next time
periods, if duty 
cycle is 
> very long you do the same but you must compensate
the first time 
that 
> the duty cycle exceeds your limit, whatever you
determine that to 
be.
> 
> Of course you asked for a method of doing this using continuous 
mode on 
> Timer A. I have given you the most direct, and
hopefully 
understandable 
> way. There are many ways to do this. If all you
are concerned about 
is a 
> heartbeat there is a simpler way of doing it. Use
the code in the 
> example, using CCR0 and CCR1 in up mode, I assume that CCR0 is set 
to 
> 400 for a 20kHz period, giving a convenient 4
clocks per % duty 
cycle as 
> well. Now simply count the number of periods of
the PWM, using the 
> TimerA overflow ISR. Since the period is 50 usecs, you need 20 PWM 
> periods per TICK. In the INIT routines enable the Timer_A overflow 
> interrupt (this occurs as the Timer counts from CCR0 to 0). In the 
Timer 
> overflow interrupt simply implement a count to 20
and set a flag 
when 
> this occurs.
> 
> I strongly recommend you use a flag to signal the heartbeat, since 
you 
> don't want to process the periodic events at
1msec in an ISR. The 
golden 
> rule for ISRs is short and fast, try to avoid
manipulating port 
pins, or 
> registers. If you do remember that you must
preserve the original 
state 
> on entry to the ISR, and recover them on exit.
> 
> A typical ISR for me simply clears the interrupt flag, sets up a 
flag, 
> or semaphore to the main program, or stuffs a task
into a queue, 
sets up 
>   the next interrupt condition if necessary and
exits.
> 
> Al
> 
> 
> Jeff Allan wrote:
> > Hello All
> > This is my first post to the MSP430 news group, and as
> > you have guessed I am new to the MSP430.
> > I am trying to get the PWM to work on a MSP430F1232
> > chip, I am using the example fet120_ta_pwm01.c.
> > Which works fine, but I would like to use the Timer_A
> > in continous mode as opposed to up mode in the
> > example.
> > Because I am using Timer_A for a 1ms tick.
> > Can any one help!
> > Thanks in advance.
> > 
> > Jeff Allan
> > 
> > 
> > 
> > .
> > 
> >  
> > 
> > ">http://docs.yahoo.com/info/terms/ 
> > 
> > 
> >


You're welcome.

Al

Jeff wrote:
> Thankyou
> For the comprehensive reply.
> 
> Jeff
> 
> --- In msp430@msp4..., onestone <onestone@b...> wrote:
> 
>>This isn't, or shouldn't be a problem. Timer A has three
capture 
> 
> compare 
> 
>>registers. To generate PWM you typically use CCR0 to generate the 
> 
> period 
> 
>>and CCR1 or CCR2 to generate the pulse. IIRC the example uses the 
> 
> up 
> 
>>mode only, and resets when TAR = CCR0. This simplifies everything 
>>because you don't even need an ISR. If you want PWM in continuous 
> 
> mode 
> 
>>you simply have to handle CCR0 and CCR1 or 2 in an ISR. Let's 
> 
> assume you 
> 
>>are generating your 1ms tick with CCR2, and are using CCR1 for the 
> 
> PWM, 
> 
>>along with CCR0. You will need an ISR for CCR2 anyway. So, having 
>>configured Timer A in continuous mode you will need the following 3 
> 
> ISR's:-
> 
>>Let's assume an 8MHz crystal
>>20kHz PWM
>>1msec heartbeat
>>
>>;****	CONSTANTS
>>
>>PERIOD		EQU	400		;VERY LOW, SEE 
> 
> GOTCHA'S LATER
> 
>>HEARTBEAT	EQU	8000
>>
>>TA0_ISR:
>>	BIC	#CCIFG,&CCTLA0		;CLEAR THE FLAG ANYWAY
>>	ADD	#PERIOD,&CCR0		;ADD THE PERIOD TO THE OLD 
> 
> VALUE
> 
>>	RETI
>>
>>TA1_ISR:
>>	BIC	#CCIFG,&CCTLA1		;CLEAR THE INT FLAG
>>	MOV	&CCR0,&CCR1		;GET THE NEXT PERIOD START
>>	ADD	&DUTY_CYCLE,&CCR1	;ADD THE PULSE LENGTH TO IT
>>	RETI
>>
>>TA2_ISR:
>>	BIC	#CCIFG,&CCTLA2		;OBVIOUS BY NOW
>>	ADD	#HEARTBEAT,&CCR2	;ADD THE VALUE FOR 1MS TO CCR2
>>	BIS	#TICK,&FLAG_REGISTER	;SET A FLAG BIT TO INDICATE 
> 
> TICK 					;HAS 
> 
>>OCCURRED
>>	RETI
>>
>>There is a potential GOTCHA with this method. Simply that motor PWM 
>>should have a frewquency around 20kHz, and this equates to only 400 
>>clock cycles. This is why the MSP implements this generally using 
> 
> UP 
> 
>>mode, no ISR's. Imagine what will happen when you need a 2% duty 
> 
> cycle, 
> 
>>or a 98% duty cycle. The short time differences between the ISR 
>>occurences are too short. Now you can handle this in the code that 
>>determines the duty cycle, assuming that it isn't fixed, and you 
> 
> can 
> 
>>arrange just for 1 ISR to handle both times, of course you must 
>>generally make that ISR the CCR1 ISR. In code you would adopt 
> 
> different 
> 
>>ISR strategies based upon the duty cycles. If duty cycle is short 
> 
> you 
> 
>>only use CCR1 to set up both of the next time periods, if duty 
> 
> cycle is 
> 
>>very long you do the same but you must compensate the first time 
> 
> that 
> 
>>the duty cycle exceeds your limit, whatever you determine that to 
> 
> be.
> 
>>Of course you asked for a method of doing this using continuous 
> 
> mode on 
> 
>>Timer A. I have given you the most direct, and hopefully 
> 
> understandable 
> 
>>way. There are many ways to do this. If all you are concerned about 
> 
> is a 
> 
>>heartbeat there is a simpler way of doing it. Use the code in the 
>>example, using CCR0 and CCR1 in up mode, I assume that CCR0 is set 
> 
> to 
> 
>>400 for a 20kHz period, giving a convenient 4 clocks per % duty 
> 
> cycle as 
> 
>>well. Now simply count the number of periods of the PWM, using the 
>>TimerA overflow ISR. Since the period is 50 usecs, you need 20 PWM 
>>periods per TICK. In the INIT routines enable the Timer_A overflow 
>>interrupt (this occurs as the Timer counts from CCR0 to 0). In the 
> 
> Timer 
> 
>>overflow interrupt simply implement a count to 20 and set a flag 
> 
> when 
> 
>>this occurs.
>>
>>I strongly recommend you use a flag to signal the heartbeat, since 
> 
> you 
> 
>>don't want to process the periodic events at 1msec in an ISR. The 
> 
> golden 
> 
>>rule for ISRs is short and fast, try to avoid manipulating port 
> 
> pins, or 
> 
>>registers. If you do remember that you must preserve the original 
> 
> state 
> 
>>on entry to the ISR, and recover them on exit.
>>
>>A typical ISR for me simply clears the interrupt flag, sets up a 
> 
> flag, 
> 
>>or semaphore to the main program, or stuffs a task into a queue, 
> 
> sets up 
> 
>>  the next interrupt condition if necessary and exits.
>>
>>Al
>>
>>
>>Jeff Allan wrote:
>>
>>>Hello All
>>>This is my first post to the MSP430 news group, and as
>>>you have guessed I am new to the MSP430.
>>>I am trying to get the PWM to work on a MSP430F1232
>>>chip, I am using the example fet120_ta_pwm01.c.
>>>Which works fine, but I would like to use the Timer_A
>>>in continous mode as opposed to up mode in the
>>>example.
>>>Because I am using Timer_A for a 1ms tick.
>>>Can any one help!
>>>Thanks in advance.
>>>
>>>Jeff Allan
>>>
>>>
>>>
>>>.
>>>
>>> 
>>>
>>>">http://docs.yahoo.com/info/terms/ 
> 
>>>
>>>
> 
> 
> 
> .
> 
>  
> 
> ">http://docs.yahoo.com/info/terms/ 
> 
> 
>