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**********************************/