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'm having a issues with the ISR function being called. I'm using examples based from this document slaa513.pdf.
I put the timer into continous mode (MC_2) and enable the interrupt (TAIE) and trying to use SMCLK (TASSEL_2)
The problem is it freezes, sometimes it goes into the the interrupt routine other times it does not.
if I use TASSEL_1 it will work for a while and then freeze. I have tried setting up the SMCLK it a couple ways but it doesn't see to help. And if I create a PWM using MC_1 on TA1.1 to create a PWM it works fine using SMCLK.
Is there something simple I'm missing here?
Code pasted below.. Note how I'm trying to vary the duty cycle using the servo1_value var in a simple loop.
#include <msp430f5528.h>
// SERVO 1 connected to P1.7/TA1.0
#define PWM_SERVO1_BIT BIT7 //P1.7
#define PWM_SERVO1_DIR P1DIR // Each Servo uses the different DIR,SEL,OUT
#define PWM_SERVO1_OUT P1OUT
#define PWM_SERVO1_SEL P1SEL
#define PWM_SERVO1_TxCCR TA1CCR0 //Timer A1 TA1.0
#define PWM_SERVO1_TxCCTL TA1CCTL0
#define PWM_SERVO_TIMER_CONTROL TA1CTL
#define PWM_SERVO_PWM_PERIOD TA1CCR0
#define PWM_SERVO_MIN 250 // old values
#define PWM_SERVO_MAX 500
#define PWM_SERVO_PERIOD 500
// LED defines for bits and outputs.
#define LED_RED_BIT BIT7
#define LED_BLUE_BIT BIT6
#define LEDS_DIR P6DIR
#define LEDS_OUT P6OUT
// LED ON/OFF Commands.
#define LED_RED_OFF LEDS_OUT &= ~LED_RED_BIT
#define LED_BLUE_OFF LEDS_OUT &= ~LED_BLUE_BIT
#define LED_RED_ON LEDS_OUT |= LED_RED_BIT
#define LED_BLUE_ON LEDS_OUT |= LED_BLUE_BIT
#define LED_RED_CYCLE LEDS_OUT ^= LED_RED_BIT
#define LED_BLUE_CYCLE LEDS_OUT ^= LED_BLUE_BIT
unsigned int servo1_value = PWM_SERVO_MIN;
void main(void) {
WDTCTL = WDTPW+WDTHOLD; // Stop that silly watchdog timer
// init the ports for setting up the LEDS
LEDS_DIR |= LED_RED_BIT + LED_BLUE_BIT ; // Set LEDS to output direction
LED_RED_OFF; // start with LEDS OFF
LED_BLUE_OFF; // start with LEDS OFF
PWM_SERVO1_DIR |= PWM_SERVO1_BIT; // setup output direction
PWM_SERVO1_SEL |= PWM_SERVO1_BIT; // set timer to update this output
PWM_SERVO1_TxCCTL = OUTMOD_4 + CCIE; // enable interrupt
PWM_SERVO_TIMER_CONTROL = TASSEL_2 + MC_2 + TAIE; // set SMCLK, continous mode, and interrupt enable.
__bis_SR_register(GIE); // enable interrupts
int pos = 0;
int i = 0;
while(1) {
pos = 240;
for(i=0;i<=25;i++) {
pos = pos + 10; // increment for testing purposes
servo1_value = pos; // update the duty cycle for the ISR function below
__delay_cycles(100000); // delay between PWM duty cycle changes.
LED_BLUE_CYCLE;
}
}
}
#pragma vector=TIMER1_A0_VECTOR
__interrupt void TIMER1_A0_VECTOR_ISR(void) {
LED_RED_CYCLE;
if(TA1CCTL0 & CCI) // If output currently high
{
TA1CCR0 += servo1_value; // PWM high ( this value plus the "else" value needs to equal pwm period.
} else {
TA1CCR0 += PWM_SERVO_PERIOD - servo1_value; // PWM low
}
}
Hi,
if I have understood correctly, you want to generate a PWM signal with TA1.0.
I do not have worked with this device in particular, I work with F5438A, both devices share family, I am going to try to give you some advices:
- TIMER1_A0_VECTOR_ISR shares the interrupt routine for the compare register reached by the timer (TA0R = TA0CCR0) and for the timer overflowing. So you only have to enable CCIE of CCR0 register, but not the TAIE. If both are enabled, the code will enter in the ISR for two conditions, and I think that you only want to enter when the timer reaches CCR0.
- I do not know the pinout of that uC, but maybe, the output can be sourced to different pins. Check in the datasheet, if TA1.0 work as second function in more than one pin. If it happens, you have to select the pin you want to use as output, for this, in the compare register control register (TA0CTL0) you have to configure the CCIS bits.
With this advices I get generate a PWM by easy way. Some name register can be wrong, so check them to ensure.
I hope it helps you
Regarding not using TAIE. In the example in the pdf linked in my first post, they show the following.
TACCTL0 = OUTMOD_4 + CCIE;
TACCTL1 = OUTMOD_4 + CCIE;
TACCTL2 = OUTMOD_4 + CCIE;
TACTL = TASSEL_2 + MC_2 + TAIE;
Does this mean the g2452 handles this differently? Or is the ISR called twice and somehow can handle this without a issue? Just curious. I'll have to test this later on a lauchpad when able.
c_builder said:#define PWM_SERVO1_TxCCR TA1CCR0 //Timer A1 TA1.0
The whole thing will fail if either the high or the low part of the PWM output is below a certain threshold (depends on timer speed and CPU speed). Imagine what happens if servo1_value is 0? Right, you're adding 0 to TA1CCR0. This means, the next interrupt will be triggered after a full timer cycle of 65536 ticks. You won't be able to change the DC for that amount of time. This will happen for any step size that is smaller than the timer ticks that pass while executing the ISR.
Maybe this is not critical in your current application, but maybe it is.
The missing ISR for the timer overflow (TAIE) or superfluous TAIE bit has already been discussed.
**Attention** This is a public forum