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.

MSP430FR4133: P1.7 Timer A0 works but not P8.3 Timer A1 w/ exact settings

Part Number: MSP430FR4133

Hi, I've got very simple code which is sampling from the ADC module of a potentiometer on P8.1 A9 to control a servo motor PWM which in turn rotates the SG90 servo motor.

The following code works fine for P1.7 output for PWM signal and using timer TA0 module

// Main c file 

/********************************
main.c
Default Template file for testing purposes
Aaron Shek, @ 2023 University of Strathclyde
*********************************/

#include <msp430.h>
#include <driverlib.h>
#include <stdio.h>

unsigned int rate_ = 0;
uint32_t TimerA0_period = 20000; // PWM Period
unsigned int i;

// ADC interrupt service routine
#pragma vector=ADC_VECTOR           
__interrupt void ADC_ISR(void)
{
  switch(__even_in_range(ADCIV,ADCIV_ADCIFG))
  {
    case ADCIV_ADCIFG:              
    rate_ = (int)(600 + (2.05*ADCMEM0)); // Max value of 2695, min 600
    //printf("%d\n",rate_);
    __bic_SR_register_on_exit(LPM0_bits); // Clear CPUOFF bit from LMP0 to prevent MCU sleeping
    //ADC_clearInterrupt(ADC_BASE,ADC_COMPLETED_INTERRUPT);
    break;
  }
}

void main(void)
{
    WDTCTL = WDTPW | WDTHOLD; // Stop WDT
    
    P1DIR |= 0x80; // P1.7 output
    P1SEL0 |= 0x80; // P1.7 options select
    
    P4DIR |= 0x01; // Indicator LED
    P4OUT |= 0x01; 
    
    // Configure Pin for ADC
    GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P8,GPIO_PIN1,GPIO_PRIMARY_MODULE_FUNCTION);
    
    // Disable the GPIO power-on default high-impedance mode to activate
    // previously configured port settings
    PM5CTL0 &= ~LOCKLPM5; PMM_unlockLPM5();
    
    // Timer TA0 setup
    TA0CCR0 = TimerA0_period; // PWM Period
    TA0CCTL1 = OUTMOD_7; // CCR1 reset/set                      
    TA0CTL = TASSEL_2 | MC_1; // SMCLK, up mode
    
    // ADC setup
    // Configure the Pin
    SYSCFG2 |= ADCPCTL9; // Turn on analogue pin A9 (so it is not a GPIO).
    // Configure CLock source, operation mode
    ADCCTL0 |= ADCSHT_2 | ADCON;  // 16 ADCCLK cycles, turn on ADC.
    ADCCTL1 |= ADCSHP; // ADDCLK = MODOSC; sampling timer
    ADCCTL2 |= ADCRES; // 10 bit conversion results
    // Configure ADC mux and +ve & -ve references
    ADCMCTL0 |= ADCINCH_9; // A9 ADC input select; Vref = AVCC   
    ADCIFG &= ~0x01;  //Clear interrupt flag  
    ADCIE |= ADCIE0;  //Enable ADC conversion complete interrupt
 
    __enable_interrupt();
      
    while(1) {  
      ADCCTL0 |= 0x03;          // Sampling and conversion start
      while(ADCCTL0 & ADCBUSY) {
      int memval = rate_;
      TA0CCR1 = memval;     
      __delay_cycles(10000);
      }
    }  
    // __bis_SR_register(LPM0_bits); // Enter LPM0
    
}

However, when I want to use P8.3 instead alongside  timer TA1 module instead using the exact same configuration it does not work: 

// Main c file 

/********************************
main.c
Default Template file for testing purposes
Aaron Shek, @ 2023 University of Strathclyde
*********************************/

#include <msp430.h>
#include <driverlib.h>
#include <stdio.h>

unsigned int rate_ = 0;
uint32_t TimerA1_period = 20000; // PWM Period
unsigned int i;

// ADC interrupt service routine
#pragma vector=ADC_VECTOR           
__interrupt void ADC_ISR(void)
{
  switch(__even_in_range(ADCIV,ADCIV_ADCIFG))
  {
    case ADCIV_ADCIFG:              
    rate_ = (int)(600 + (2.05*ADCMEM0)); // Max value of 2695, min 600
    //printf("%d\n",rate_);
    __bic_SR_register_on_exit(LPM0_bits); // Clear CPUOFF bit from LMP0 to prevent MCU sleeping
    //ADC_clearInterrupt(ADC_BASE,ADC_COMPLETED_INTERRUPT);
    break;
  }
}

void main(void)
{
    WDTCTL = WDTPW | WDTHOLD; // Stop WDT
    
    P8DIR |= 0x03; // P8.3 output
    P8SEL0 |= 0x03; // P8.3 options select
    
    P4DIR |= 0x01; // Indicator LED
    P4OUT |= 0x01; 
    
    // Configure Pin for ADC
    GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P8,GPIO_PIN1,GPIO_PRIMARY_MODULE_FUNCTION);
    
    // Disable the GPIO power-on default high-impedance mode to activate
    // previously configured port settings
    PM5CTL0 &= ~LOCKLPM5; PMM_unlockLPM5();
    
    // Timer TA0 setup
    TA1CCR0 = TimerA1_period; // PWM Period
    TA1CCTL1 = OUTMOD_7; // CCR1 reset/set                      
    TA1CTL = TASSEL_2 | MC_1; // SMCLK, up mode
    
    // ADC setup
    // Configure the Pin
    SYSCFG2 |= ADCPCTL9; // Turn on analogue pin A9 (so it is not a GPIO).
    // Configure CLock source, operation mode
    ADCCTL0 |= ADCSHT_2 | ADCON;  // 16 ADCCLK cycles, turn on ADC.
    ADCCTL1 |= ADCSHP; // ADDCLK = MODOSC; sampling timer
    ADCCTL2 |= ADCRES; // 10 bit conversion results
    // Configure ADC mux and +ve & -ve references
    ADCMCTL0 |= ADCINCH_9; // A9 ADC input select; Vref = AVCC   
    ADCIFG &= ~0x01;  //Clear interrupt flag  
    ADCIE |= ADCIE0;  //Enable ADC conversion complete interrupt
 
    __enable_interrupt();
      
    while(1) {  
      ADCCTL0 |= 0x03;          // Sampling and conversion start
      while(ADCCTL0 & ADCBUSY) {
      int memval = rate_;
      TA1CCR1 = memval;     
      __delay_cycles(10000);
      }
    }  
    // __bis_SR_register(LPM0_bits); // Enter LPM0
}

I'm very lost and I've consulted the user guide and datasheet but I cannot see where I went wrong. 

Your help is much appreciated.

Aaron

  •     P8DIR |= 0x03; // P8.3 output
        P8SEL0 |= 0x03; // P8.3 options select
     

    Those bits are for P8.0 and P8.1. What you want is the handy symbol BIT3 (0x08) provided in the device header file.

  • Hi David,

    Thanks for responding. Unfortunately it did not seem to fix it when I changed from 0x03 to BIT3. 

  • It is something as simple as the fact you changed from using CCR1 to CCR2? The first iteration you were using P1.7/TA0.1 which is Timer A0, CCR1. You changed to P8.3/TA1.2 which is Timer A1, CCR2. In your code, you correctly changed from the TA0 to TA1, but never changed from CCTL1 to CCTL2 or CCR1 to CCR2.

    EDIT: You still need to include the changes David mentioned.

  • Thanks for responding back, that seemed promising first but still no luck, I've attached the code..

    // Main c file 
    
    /********************************
    main.c
    Default Template file for testing purposes
    Aaron Shek, @ 2023 University of Strathclyde
    *********************************/
    
    #include <msp430.h>
    #include <driverlib.h>
    #include <stdio.h>
    
    unsigned int rate_ = 0;
    uint32_t TimerA1_period = 20000; // PWM Period
    unsigned int i;
    
    // ADC interrupt service routine
    #pragma vector=ADC_VECTOR           
    __interrupt void ADC_ISR(void)
    {
      switch(__even_in_range(ADCIV,ADCIV_ADCIFG))
      {
        case ADCIV_ADCIFG:              
        rate_ = (int)(600 + (2.05*ADCMEM0)); // Max value of 2695, min 600
        //printf("%d\n",rate_);
        __bic_SR_register_on_exit(LPM0_bits); // Clear CPUOFF bit from LMP0 to prevent MCU sleeping
        //ADC_clearInterrupt(ADC_BASE,ADC_COMPLETED_INTERRUPT);
        break;
      }
    }
    
    void main(void)
    {
        WDTCTL = WDTPW | WDTHOLD; // Stop WDT
        
        P8DIR |= BIT3; // P8.3 output
        P8SEL0 |= BIT3; // P8.3 options select
        
        P4DIR |= 0x01; // Indicator LED
        P4OUT |= 0x01; 
        
        // Configure Pin for ADC
        GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P8,GPIO_PIN1,GPIO_PRIMARY_MODULE_FUNCTION);
        
        // Disable the GPIO power-on default high-impedance mode to activate
        // previously configured port settings
        PM5CTL0 &= ~LOCKLPM5; PMM_unlockLPM5();
        
        // Timer TA1 setup
        TA1CCR1 = TimerA1_period; // PWM Period
        TA1CCTL2 = OUTMOD_7; // CCR1 reset/set                      
        TA1CTL = TASSEL_2 | MC_1; // SMCLK, up mode
        
        // ADC setup
        // Configure the Pin
        SYSCFG2 |= ADCPCTL9; // Turn on analogue pin A9 (so it is not a GPIO).
        // Configure CLock source, operation mode
        ADCCTL0 |= ADCSHT_2 | ADCON;  // 16 ADCCLK cycles, turn on ADC.
        ADCCTL1 |= ADCSHP; // ADDCLK = MODOSC; sampling timer
        ADCCTL2 |= ADCRES; // 10 bit conversion results
        // Configure ADC mux and +ve & -ve references
        ADCMCTL0 |= ADCINCH_9; // A9 ADC input select; Vref = AVCC   
        ADCIFG &= ~0x01;  //Clear interrupt flag  
        ADCIE |= ADCIE0;  //Enable ADC conversion complete interrupt
     
        __enable_interrupt();
          
        while(1) {  
          ADCCTL0 |= 0x03;          // Sampling and conversion start
          while(ADCCTL0 & ADCBUSY) {
          int memval = rate_;
          TA1CCR2 = memval;     
          __delay_cycles(10000);
          }
        }  
        // __bis_SR_register(LPM0_bits); // Enter LPM0
    }

    If you look at the registers, timer0 and timer1 are identical so logically speaking should work the same? 

    Much appreciated. 

    Aaron

  • Aaron,

    Debug your project and check your GPIO settings for port 8 when you are in your while loop. More than likely, the driverlib function you are utilizing to setup the ADC is overwriting what you've done above it for setting up Timer output, since they are the same port. 

    Also, your PWM period should change to an uint16_t variable as the timers are not 32 bit. This will change the underlying container size and reduce CPU overhead. 

  • Adding on to Jace's comments, the revised code is not setting the value for the CCR0 register. On line 50 of the newest code snippet, you are setting CCR1 with TimerA1_period, not CCR0, which is required. Keep in mind, from the User Guide, "The timer repeatedly counts up to the value of compare register TAxCCR0, which defines the period".

  • Thanks, this resolved my issue. Also thanks Jace for the advice on the variable type.

**Attention** This is a public forum