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.

MSP432P401R: MSP432P401R

Part Number: MSP432P401R

So I have code to create 2 PWM outputs for motors, then I have code for 3 (will be 7) ADC pins that I am using with sonars sensors. I have the ADCs set up with comparators for the interrupts. When I test these alone they work find...the PWM can change with button interrupts just fine and run the motors. The ADC pins display values and interrupt accordingly with the ISR to light up LEDs. Now I am trying to combine the two, I would like for my ADC ISR to be able to change the PWM duty cycle and output the new values, however when I test the code the ADC ISR has no affect at all on the PWM, it changes the duty cycle values I can see through "expressions" on my CCS interface, but the physical output does not change, I would like to know why and what i need to do. Here is my code: 

/* DriverLib Includes */
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>

/* Standard Includes */
#include <stdint.h>
#include <stdbool.h>

 /* For usleep() */
//#include <unistd.h>
//#include <stddef.h>

/* TI-RTOS Header files */
#include <ti/drivers/GPIO.h>
//#include <ti/display/Display.h>

/* Board Header file */
//#include "Board.h"

/* Statics */
uint16_t resultsBuffer[3];//Buffer to hold ADC readings of each Sonar Sensor

/* DLUG section: 2.6.2.25 | Registers an interrupt handler for the ADC interrupt.  */
void ADC14_registerInterrupt(void (*ADC14_IRQHandler)(void));

void PWMConfigure(void);//set up PWM
void ADCConfigure(void);//set up ADC
void InitDCO(void);//Change operation frequency of DCO
void SonarOne(void);
void SonarTwo(void);
void SonarThree(void);
void SonarFour(void);
void SonarFive(void);
void SonarSix(void);
void SonarSeven(void);
void EmergencyStop(void);

volatile uint32_t ii;

/**********************Timer_A PWM Configuration Parameter for Right motor*********************
    *hold command and click Timer_A_PWMConfig to see that pwmConfigR is a typedef struct _Timer_A_PWMConfig
    *S1 is for right motor */
    Timer_A_PWMConfig pwmConfigR =
    {
    TIMER_A_CLOCKSOURCE_SMCLK,//clock source for PWM operation
    TIMER_A_CLOCKSOURCE_DIVIDER_1,//divider of clocksource SMCLK
    4800,//period
    TIMER_A_CAPTURECOMPARE_REGISTER_3,
    TIMER_A_OUTPUTMODE_RESET_SET,
    4200//start at 50% duty cycle of 5[V] (2.5[V]) so motors not moving.
    };

/**********************Timer_A PWM Configuration Parameter for Left motor*********************
    *S2 is for left motor*/
    Timer_A_PWMConfig pwmConfigL =
    {
    TIMER_A_CLOCKSOURCE_SMCLK,
    TIMER_A_CLOCKSOURCE_DIVIDER_1,
    4800,
    TIMER_A_CAPTURECOMPARE_REGISTER_4,//makes P2.7 work because TA0.4
    TIMER_A_OUTPUTMODE_RESET_SET,
    4200
    };

/*********************************END TIMER_A_PWMConfig FOR BOTH MOTORS *********************************
 * The motors work with direction and speed as one input. 51-100% duty cycle is forward speed (5[V] max,
 * higher duty cycle is faster forward speed), 0-49% duty cycle is backward speed (0[V] max, lower duty
 * cycle is faster backward speed) and 50% is no movement(2.5[V]).
 *
 * We want to use about half of each directions duty cycle since we do not want to go fast. Each direction
 * has 2,400 levels of speed. Half of each is 1,200 levels of speed. Forward can have a duty cycle of
 * 2,401-4,800 and backwards can have a duty cycle of 0 - 2,399. We will be using Forward: 2,401-3,600 &
 * Backward: 1,200 - 2,399   */

/*********************************START MAIN**********************************/
int main(void)
{
    /* Halting WDT  */
    MAP_WDT_A_holdTimer();

    PWMConfigure();//set up PWM
    ADCConfigure();//set up ADC
    MAP_Interrupt_enableSleepOnIsrExit();

    /* Going to sleep */
    while (1)
    {
        //SonarThree();//right green light on when objects between 1-2 feet.
        MAP_PCM_gotoLPM0();//sleep while no interrupts are happening.
    }
}//END MAIN
/*********************************END MAIN**********************************/

/*********************************START SONARS**********************************/
void SonarOne(void){//P5.2 & resultsBuffer[0]
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P1, GPIO_PIN0);//LED1 (left) RED
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN1);
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0);

    pwmConfigL.dutyCycle = 0;
    pwmConfigR.dutyCycle = 0;

}
void SonarTwo(void){//P5.1 & resultsBuffer[1]
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN0);//LED2 (right) RED
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0);
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN1);
    pwmConfigL.dutyCycle = 4800;
    pwmConfigR.dutyCycle = 4800;

}
void SonarThree(void){//P5.0 & resultsBuffer[2]
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN1);//LED2 (right) GREEN
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0);
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0);
//    pwmConfigL.dutyCycle = 4800;
//    pwmConfigR.dutyCycle = 4800;
//    MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfigL);
//    MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfigR);
}
void SonarFour(void){//P4.7 & resultsBuffer[3]
}
void SonarFive(void){//P4.0 & resultsBuffer[4]
}
void SonarSix(void){//P6.1 & resultsBuffer[5]
}
void SonarSeven(void){//P6.0 & resultsBuffer[6]
}
/*********************************END SONARS**********************************/

/*********************************START ADC HANDLER**********************************/
/* This interrupt is fired whenever a Sonar Reading is whatever the comparator says and the MAP_ADC14_enableInterrupt(X) says. */
void ADC14_IRQHandler(void)
{
    uint64_t status;

    status = MAP_ADC14_getEnabledInterruptStatus();//gets interrupt status for comparison
    MAP_ADC14_clearInterruptFlag(status);//clears interrupt flag for next interrupt check

    resultsBuffer[0] = MAP_ADC14_getResult(ADC_MEM0);//P5.0
    resultsBuffer[1] = MAP_ADC14_getResult(ADC_MEM1);//P5.1
    resultsBuffer[2] = MAP_ADC14_getResult(ADC_MEM2);//P4.7

    if ((resultsBuffer[0] < 1000)){//LED 1 ON WHEN OBJECTS ARE CLOSE (RED)
            SonarOne();//left red light on when objects closer than 1 foot.
        }
    else if((resultsBuffer[1] < 1000)){
            SonarTwo();//right red light on when object farther than 2 feet.
    }
    else{
            SonarThree();//right green light on when objects between 1-2 feet.
    }

    MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfigL);
    MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfigR);
}//END ADC14_IRQHandler
/*********************************END ADC HANDLER**********************************/

/*********************************START PORT 1 HANDLER**********************************/
    /* Port1 ISR - This ISR will progressively step up the duty cycle of the PWM
     * on a button press */
void PORT1_IRQHandler(void)
{
    uint32_t status = MAP_GPIO_getEnabledInterruptStatus(GPIO_PORT_P1);//P1.1 (S1)
    MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, status);

    /* Imagine status gets all of Port 1 interrupt status so if pin 1 had an interrupt then
     * status would read 00000010, for pin 4 it would read 00010000 so if we & status with
     * pin 1 or pin 4, if those interrupt bits are high then it will be true and the if
     * statement will run.*/

    if (status & GPIO_PIN1)//P1.1 (S1)
    {//moves motor duty cycle forward (increases it)
        if(pwmConfigL.dutyCycle == 4800 && pwmConfigR.dutyCycle == 4800){
            pwmConfigL.dutyCycle = 4800;
            pwmConfigR.dutyCycle = 4800;}
        else{
            pwmConfigL.dutyCycle += 300;
            pwmConfigR.dutyCycle += 300;}

        MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfigL);
        MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfigR);
    }
    else //(status & GPIO_PIN4)//P1.4 (S2)
    {//moves motor duty cycle backwards (decreases it)
        if(pwmConfigL.dutyCycle == 2400 && pwmConfigR.dutyCycle == 2400){
            pwmConfigL.dutyCycle = 2400;
            pwmConfigR.dutyCycle = 2400;}
        else{
            pwmConfigL.dutyCycle -= 300;
            pwmConfigR.dutyCycle -= 300;}

        MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfigL);
        MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfigR);
        }
}//END PORT1_IRQHandler
/*********************************END PORT 1 HANDLER**********************************/

/*********************************START PWM CONFIGURE**********************************/
void PWMConfigure(){

    InitDCO();//Change clock frequency to 48[MHz]

    /* DLUG section: 6.6.2.18 | Initialize SMCLK to DCOCLK frequency divided by 1*/
    MAP_CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);

    /* Configuring GPIO2.7 as peripheral output for PWM for right motor and
    * Configuring GPIO2.6 as peripheral output for PWM for left motor and P1.1 for button interrupt */
    MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);//P2.7 (right motor)
    MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN6, GPIO_PRIMARY_MODULE_FUNCTION);//P2.6 (left motor)
    MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P1, GPIO_PIN1);//set Pin 1 on Port 1
    MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P1, GPIO_PIN4);//set Pin 4 on Port 1
    MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, GPIO_PIN1);
    MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, GPIO_PIN4);
    MAP_GPIO_enableInterrupt(GPIO_PORT_P1, GPIO_PIN1);
    MAP_GPIO_enableInterrupt(GPIO_PORT_P1, GPIO_PIN4);

    Interrupt_setPriority(INT_PORT1,0);

    /* DLUG section: 12.4.2.4 | Enabling interrupts on port 1 for button */
    MAP_Interrupt_enableInterrupt(INT_PORT1);

    /* DLUG section: 24.4.2.11 | Generate a PWM with timer running in up mode. Clock is set at 48[MHz],
     * which is 0.0208333[us] [Microseconds] (2.08s*10^-8). Each Timer is set up with a period of 4,800
     * ticks so period is 0.0001[s] which is a frequency of 1/.0001 = 10[kHz] */
    MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfigR);
    MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfigL);
}//END PWMConfigure
/*********************************END PWM CONFIGURE**********************************/

/*********************************START ADC CONFIGURE**********************************/
void ADCConfigure(){

    /* Setting up clocks
     * MCLK = MCLK = 3MHz
     * ACLK = REFO = 32Khz */
    MAP_CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1);

    /* Initializing ADC (MCLK/1/1) */
    MAP_ADC14_enableModule();
    MAP_ADC14_initModule(ADC_CLOCKSOURCE_MCLK, ADC_PREDIVIDER_1, ADC_DIVIDER_1, 0);

    /* Configuring GPIOs for Tertiary Function and inputs on Port 4 Pins 0 & 7,
     * Port 5 Pins 0,1 & 2 and Port 6 Pins 0 & 1 */
    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN0 | GPIO_PIN1 , GPIO_TERTIARY_MODULE_FUNCTION);
    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P4, GPIO_PIN7 , GPIO_TERTIARY_MODULE_FUNCTION);

    /* Setting LED1 and LED2 on board as outputs and initializing them as low */
    MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0);//LED1(left and red)
    MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN1);
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN1);//LED2(right and green)
    MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN0);
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0);//LED2(right and blue)
    MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN2);
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN2);//LED2(right and red)

    /* DLUG section: 2.6.2.3 | Configuring ADC Memory (ADC_MEM0 - ADC_MEM6 (A6 - A12)  with no repeat)
     * with internal 3.3[V] reference */
    MAP_ADC14_configureMultiSequenceMode(ADC_MEM0,ADC_MEM2, true);

    /* DLUG section: 2.6.2.2 | Configures individual memory locations for each ADC module.
     *  (memory locations, type of voltage reference, which channel is being used for
     *  ADC sampling, false for non-differential inputs) */
    //ADC_VREFPOS_INTBUF_VREFNEG_VSS (does 2.5[V] reference voltage)
    MAP_ADC14_configureConversionMemory(ADC_MEM0,
        ADC_VREFPOS_AVCC_VREFNEG_VSS, ADC_INPUT_A5, false);//ADC5 = P5.0 = MEM0
    MAP_ADC14_configureConversionMemory(ADC_MEM1,
        ADC_VREFPOS_AVCC_VREFNEG_VSS, ADC_INPUT_A4, false);//ADC4 = P5.1 = MEM1
    MAP_ADC14_configureConversionMemory(ADC_MEM2,
        ADC_VREFPOS_AVCC_VREFNEG_VSS, ADC_INPUT_A6, false);//ADC6 = P4.7 = MEM2

    /* DLUG section: 2.6.2.16 | Setting up the sample timer to automatically step through the sequence convert
     * After one sample/convert is finished, the ADC module will automatically continue on to the next sample.*/
    MAP_ADC14_enableSampleTimer(ADC_AUTOMATIC_ITERATION);


    /*DLUG section: 2.6.2.11 | Enables the specified mask of memory channels to use the specified comparator window. The
    ADCC module has two different comparator windows that can be set with this function.*/
    ADC14_enableComparatorWindow(ADC_MEM0 | ADC_MEM2,
        ADC_COMP_WINDOW0);
    ADC14_enableComparatorWindow(ADC_MEM1,
            ADC_COMP_WINDOW1);

    /* DLUG section: 2.6.2.26 | Sets the lower and upper limits of the specified window comparator.
     * (window 0 or 1, lower limit, upper limit) */
    ADC14_setComparatorWindowValue(ADC_COMP_WINDOW0,600, 2000);

    /* DLUG section: 2.6.2.13 | Enabling the interrupt when a channel drops below threshold of comparator,
     * if use ADC_HI_INT enables interrupt when channel goes above threshold of comparator or
     * ADC_IN_INT enables interrupt channel when channel is whithin threshold */
    MAP_ADC14_enableInterrupt(ADC_LO_INT);

    ADC14_setComparatorWindowValue(ADC_COMP_WINDOW1,1500, 2000);

    MAP_ADC14_enableInterrupt(ADC_LO_INT);

    /* DLUG section: 12.4.2.4 - 12.4.2.5 | Enabling Interrupts */
    MAP_Interrupt_enableInterrupt(INT_ADC14);
    Interrupt_setPriority(INT_ADC14,1);
    MAP_Interrupt_enableMaster();

    /* DLUG section: 2.6.2.12 & 2.6.2.32 | Enables conversion of ADC data. Triggering the start of the sample.
     * Toggles the trigger for conversion of the ADC module by toggling the trigger software bit.*/
    MAP_ADC14_enableConversion();
    MAP_ADC14_toggleConversionTrigger();
}//END ADCConfigure
/*********************************END ADC CONFIGURE**********************************/

/*********************************START DCO INIT**********************************/
void InitDCO() {
    /* DLUG section: 9.3.2.4 | Enables the floating-point unit. */
    FPU_enableModule();

    /* DLUG section: 14.7.2.16 | Sets the core voltage level (Vcore). The function will
     * take care of all power state transitions needed to shift between core voltage levels.
     * Before we start we have to change VCORE to 1 to support the 48MHz frequency */
    PCM_setCoreVoltageLevel(PCM_AM_LDO_VCORE1);

    /* DLUG section: 8.4.2.22 | Changes the number of wait states that are used by the flash
     * controller for read operations. When changing frequency ranges of the clock, this
     * functions must be used in order to allow for readable flash memory.*/
    FlashCtl_setWaitState(FLASH_BANK0, 1);
    FlashCtl_setWaitState(FLASH_BANK1, 1);

    /* DLUG section: 6.6.2.21 | Sets the centered frequency of DCO operation to [32MHz to 64MHz]. */
    MAP_CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_48);

    /* DLUG section: 9.3.2.1 | Disables the floating-point unit. */
    FPU_disableModule();
}//END InitDCO
/*********************************END DCO INIT**********************************/

  • Brandon,

    and you're sure ADC ISR is executed and the following functions are executed

    MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfigL);
    MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfigR);
  • Brandon,
    In the code that you provided the ADC ISR does nothing to update the PWM configuration before calling the API to apply the configuration. Please compare the port ISR with the ADC ISR.

    Also, in the InitDCO you are setting the device to 48Mhz and then also using the MCLK to source the ADC. This is not a valid combination. Please refer to the device datasheet and technical reference manual.

    Regards,
    Chris
  • Chris, 

    Thanks for that. I had that commented out, I guess I uncommented it for some reason. So right now what happens is the sensors will trigger the interrupt and change the duty cycle accordingly, but the physical PWM does not change until after it stops sensing something. For example if I put my hand in front of the first ADC it will interrupt and change the duty cycle, but the physical output will not change. Once I remove my hand from in front of the sensor it will then change the physical PWM output. Does this have to do with the frequency also or is there something specific I am supposed to do to make sure the PWM is reconfigured inside the interrupt?

    Thanks

  • > MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfigL);
    This function is most suited to starting the PWM generation at the beginning. After that, you should use something like Timer_A_setCompareValue to just set the CCR.

    To the point: It clears the counter (TACLR), so if you call it (repeatedly) fast enough the timer will have no time to run. In your test case, the LO_INT is triggering very fast until you pull your hand away, then it doesn't trigger and the timer can run.
  • Hi Brandon,

    were you able to resolve your situation, if yes pls mark thread as answered if not pls let us know.
    In case of no further activity I will close this thread within the next 3 days.
  • Thank you once again, Bruce!

    I was able to find an example that went over using CaptureCompare to generate 2 PWMs and I was able to just insert the Timer_A_setCompareValue inside my ADC interrupt and it would change the duty cycle as the sensors readings changed!

    Example Program: timer_a_updown_compare_multiple_pwm.c

    I have one last question and then you can mark this resolved!

    So before I was doing my PWM at a 4800 tick period and so the higher the number, the longer my PWM was on the high part of the duty cycle.

    Using this setCompareValue it seems the higher my number is, the longer my PWM is on the low part of the duty cycle.

    For instance if i do: MAP_Timer_A_setCompareValue(TIMER_A0_BASE, TIMER_A_CAPTURECOMPARE_REGISTER_3, 4800);

    my PWM output is 0[V] and if i do 0 instead of 4800, then I receive my max PWM output (around 2.9[V]).

    Is there a way I can reverse the way these work, just to help simplify how I think about my code.

    /* DriverLib Includes */
    #include <ti/devices/msp432p4xx/driverlib/driverlib.h>
    
    void InitDCO(void);//Change operation frequency of DCO
    
    /* Application Defines */
    #define TIMER_PERIOD 4800
    #define DUTY_CYCLE1 4200
    #define DUTY_CYCLE2 4200
    
    /* Timer_A UpDown Configuration Parameter */
    const Timer_A_UpDownModeConfig upDownConfig =
    {
            TIMER_A_CLOCKSOURCE_SMCLK,              // SMCLK Clock SOurce
            TIMER_A_CLOCKSOURCE_DIVIDER_1,          // 
            TIMER_PERIOD,                           // 
            TIMER_A_TAIE_INTERRUPT_DISABLE,         // Disable Timer interrupt
            TIMER_A_CCIE_CCR0_INTERRUPT_DISABLE,    // Disable CCR0 interrupt
            TIMER_A_DO_CLEAR                        // Clear value
    
    };
    
    /* Timer_A Compare Configuration Parameter  (PWM1) */
    const Timer_A_CompareModeConfig compareConfig_PWM1 =
    {
            TIMER_A_CAPTURECOMPARE_REGISTER_3,          // Use CCR1
            TIMER_A_CAPTURECOMPARE_INTERRUPT_DISABLE,   // Disable CCR interrupt
            TIMER_A_OUTPUTMODE_TOGGLE_SET,              // Toggle output but
            DUTY_CYCLE1                                 //
    };
    
    /* Timer_A Compare Configuration Parameter (PWM2) */
    const Timer_A_CompareModeConfig compareConfig_PWM2 =
    {
            TIMER_A_CAPTURECOMPARE_REGISTER_4,          // Use CCR2
            TIMER_A_CAPTURECOMPARE_INTERRUPT_DISABLE,   // Disable CCR interrupt
            TIMER_A_OUTPUTMODE_TOGGLE_SET,              // Toggle output but
            DUTY_CYCLE2                                 //
    };
    
    int main(void)
    {
        /* Stop WDT  */
        MAP_WDT_A_holdTimer();
    
        InitDCO();//Change clock frequency to 48[MHz]
    
        /* DLUG section: 6.6.2.18 | Initialize SMCLK to DCOCLK frequency divided by 1*/
        MAP_CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);
    
        /* Configuring GPIO2.7 as peripheral output for PWM for right motor and
        * Configuring GPIO2.6 as peripheral output for PWM for left motor and P1.1 for button interrupt */
        MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);//P2.7 (right motor)
        MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN6, GPIO_PRIMARY_MODULE_FUNCTION);//P2.6 (left motor)
    
        /* Configuring Timer_A1 for UpDown Mode and starting */
        MAP_Timer_A_configureUpDownMode(TIMER_A0_BASE, &upDownConfig);
        MAP_Timer_A_startCounter(TIMER_A0_BASE, TIMER_A_UPDOWN_MODE);
    
        /* Initialize compare registers to generate PWM1 */
        MAP_Timer_A_initCompare(TIMER_A0_BASE, &compareConfig_PWM1);
    
        /* Initialize compare registers to generate PWM2 */
        MAP_Timer_A_initCompare(TIMER_A0_BASE, &compareConfig_PWM2);
    
        /* Sleeping when not in use */
        while (1)
        {
            MAP_Timer_A_setCompareValue(TIMER_A0_BASE, TIMER_A_CAPTURECOMPARE_REGISTER_3, 4800);//2.6 (S1)
            MAP_PCM_gotoLPM0();
        }
    }
    
    /*********************************START DCO INIT**********************************/
    void InitDCO() {
        /* DLUG section: 9.3.2.4 | Enables the floating-point unit. */
        FPU_enableModule();
    
        /* DLUG section: 14.7.2.16 | Sets the core voltage level (Vcore). The function will
         * take care of all power state transitions needed to shift between core voltage levels.
         * Before we start we have to change VCORE to 1 to support the 48MHz frequency */
        PCM_setCoreVoltageLevel(PCM_AM_LDO_VCORE1);
    
        /* DLUG section: 8.4.2.22 | Changes the number of wait states that are used by the flash
         * controller for read operations. When changing frequency ranges of the clock, this
         * functions must be used in order to allow for readable flash memory.*/
        FlashCtl_setWaitState(FLASH_BANK0, 1);
        FlashCtl_setWaitState(FLASH_BANK1, 1);
    
        /* DLUG section: 6.6.2.21 | Sets the centered frequency of DCO operation to [32MHz to 64MHz]. */
        MAP_CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_48);
    
        /* DLUG section: 9.3.2.1 | Disables the floating-point unit. */
        FPU_disableModule();
    }//END InitDCO
    /*********************************END DCO INIT**********************************/
    

  • > TIMER_A_OUTPUTMODE_TOGGLE_SET, // Toggle output but
    What you describe sounds like active high (non-inverted) PWM. I recommend:
    > TIMER_A_OUTPUTMODE_RESET_SET, // OUTMOD=7: 0 in the middle, 1 at the beginning
    so you don't get funny results when you use 0% or 100%.
  • Hmm, seems using that method still resulted in the "backwards" duty cycle and also reduced my output by half (my max output was 1.4[V] instead of 2.8[V]). I explored the other options and found that

    > TIMER_A_OUTPUTMODE_TOGGLE_RESET,

    seems to give the correct duty cycle and amplitude. There is one thing I have noticed that is sort of confusing with this capture compare PWM. I am using a clock source of 48[MHz] and using a 4,800 tick period, which I would assume to be a 10[kHz] period as it was before, but instead each of my PWMs are running at 5[kHz]. When i do a 2,400 tick period, then they both run at 10[kHz]. Is this supposed to happen because I am running them both off of the same Timer_A_UpDownModeConfig? Am I supposed to be running them each through their own Timer set up?

    Thank you for your quick responses!

  • I didn't notice that you had switched to Up/Down mode. In that mode, the period is 2*CCR0, as you can see in TRM (SLAU356H) Figure 19-14. Comparing to Figure 19-12, you can also see that some of the modes act a bit differently from Up mode.

    You should go through those waveforms and choose the one you want. Also consider what happens (not shown) when duty is 0% or 100%.
  • Ah, yes! I am going back and forth with PWM and ADC trying to figure out how to get them working with the Timer and Capture Compare! I changed it to the UpModeConfig and everything works fine including 0 and 100%, both operating at 10[kHz]. I think I can work with the PWM this way to do everything I need!

    Thank you!

**Attention** This is a public forum