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.

CCS/MSP432P401R: MSP432P401R serial communication issue ?. Please I need to fix it urgently

Part Number: MSP432P401R


Tool/software: Code Composer Studio

Hi I am trying to send a character through the serial communication port using the code given below. The code is used to control the speed of a stepper motor connected to Msp432P401R. I am trying to send a character "B" over to putty on pressing  button P1.1 .Upon button press the direction of the motor changes and it is indicated by the character "B". At present I am able to transmit the data but it is being received in putty as some null value or some other character. I have checked the baud rate , parity bits and stop bits. its all seems to be correct. 


#include "msp432.h"
volatile unsigned int i;
//char TXData = '1';
int main(void) {

WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD; // Stop WDT


// GPIO Setup
P4->OUT &= ~BIT6; //Direction of Motor
P4->DIR |= BIT6; //Set Direction of the motor

P1->OUT = BIT1;
P1->REN = BIT1; // Enable pull-up resistor (P1.1 output high)
P1->IFG = 0; // Clear all P1 interrupt flags
P1->IE = BIT1; // Enable interrupt for P1.1
P1->IES = BIT1; // Interrupt on high-to-low transition


P2->SEL0 |= 0x80;
P2->SEL1 &= ~0x80;//PWM
P2->DIR |= 0x80;

TIMER_A0->CCR[0] = 10000 - 1; /* PWM Period */
TIMER_A0->CCTL[4] = 0xE0; /* CCR4 reset/set mode */
TIMER_A0->CTL = 0x0214; /* use SMCLK, count up, clear TA0R register */

P5->SEL1 |= BIT4; // Configure P5.4 for ADC
P5->SEL0 |= BIT4;


//Ports for UART and LED

P1->DIR |= BIT0;
P1->OUT &= ~BIT0; // P1.0 LED

// Configure UART pins
P1->SEL0 |= BIT2 | BIT3; // set 2-UART pin as second function
//UART config
EUSCI_A0->CTLW0 |= EUSCI_A_CTLW0_SWRST; // Put eUSCI in reset
EUSCI_A0->CTLW0 = EUSCI_A_CTLW0_SWRST |EUSCI_B_CTLW0_SSEL__SMCLK; // Remain eUSCI in reset and Configure eUSCI clock source for SMCLK

// EUSCI_A0->BRW = 1; // Using baud rate calculator
// EUSCI_A0->MCTLW = (10 << EUSCI_A_MCTLW_BRF_OFS) |EUSCI_A_MCTLW_OS16;
// EUSCI_A0->CTLW0 &= ~EUSCI_A_CTLW0_SWRST;// Initialize eUSCI
// EUSCI_A0->IE |= EUSCI_A_IE_RXIE; // Enable USCI_A0 RX interrupt
EUSCI_A0->BRW = 78; // 12000000/16/9600
EUSCI_A0->MCTLW = (2 << EUSCI_A_MCTLW_BRF_OFS) |EUSCI_A_MCTLW_OS16;
EUSCI_A0->CTLW0 &= ~EUSCI_A_CTLW0_SWRST; // Initialize eUSCI
EUSCI_A0->IFG &= ~EUSCI_A_IFG_RXIFG; // Clear eUSCI RX interrupt flag
EUSCI_A0->IE |= EUSCI_A_IE_RXIE; // Enable USCI_A0 RX interrupt


// Enable global interrupt
__enable_irq(); // Enable ADC interrupt in NVIC module
NVIC->ISER[0] = 1 << ((ADC14_IRQn) & 31);

// Sampling time, S&H=16, ADC14 on
ADC14->CTL0 = ADC14_CTL0_SHT0_2 | ADC14_CTL0_SHP | ADC14_CTL0_ON;//,Pulse sample mode is selected,core is ready to power up when a valid conversion is triggered.
ADC14->CTL1 = ADC14_CTL1_RES_2; // Use sampling timer, 12-bit conversion results

ADC14->MCTL[0] |= ADC14_MCTLN_INCH_1; // A1 ADC input select; Vref=AVCC
ADC14->IER0 |= ADC14_IER0_IE0; // Enable ADC conv complete interrupt

ADC14->IER0 = ADC14_IER0_IE0; // Enable ADC14IFG.0
SCB->SCR &= ~SCB_SCR_SLEEPONEXIT_Msk; // Wake up on exit from ISR

// Ensures SLEEPONEXIT takes effect immediately
__DSB();

while (1)
{

//P1->OUT &= ~BIT0;
//printf("%d",TXData);
// for (i = 200; i > 0; i--); // Delay

//Start sampling/conversion
ADC14->CTL0 |= ADC14_CTL0_ENC | ADC14_CTL0_SC;
__sleep();

__no_operation(); // For debugger
}
}

// ADC14 interrupt service routine
void ADC14_IRQHandler(void) {
volatile uint8_t temp;
if (ADC14->MEM[0] > 0x0F & ADC14->MEM[0] <= 0x7F) {
P4->OUT = 0x0000;
TIMER_A0->CCR[0] = 0;
TIMER_A0->CCR[4] = 0;

}

if (ADC14->MEM[0] > 0x7F & ADC14->MEM[0] <= 0xFF) {
if (P1->IFG & BIT1) {
P4->OUT ^= BIT6;
}
P1->IFG &= ~BIT1;

TIMER_A0->CCR[0] = 50000 - 1;
TIMER_A0->CCR[4] = 50000 / 5;

}
else if (ADC14->MEM[0] > 0xFF & ADC14->MEM[0] <= 0x2FF) {
if (P1->IFG & BIT1) {
P4->OUT ^= BIT6;

}
P1->IFG &= ~BIT1;


TIMER_A0->CCR[0] = 40000 - 1;
TIMER_A0->CCR[4] = 40000 / 3;

}
else if (ADC14->MEM[0] > 0x2FF & ADC14->MEM[0] <= 0x7FF) {
//P1->OUT = ~BIT0;
if (P1->IFG & BIT1) {
P4->OUT ^= BIT6;
}
P1->IFG &= ~BIT1;
TIMER_A0->CCR[0] = 20000 - 1;
TIMER_A0->CCR[4] = 20000 / 2;

}

else if (ADC14->MEM[0] > 0x7FF & ADC14->MEM[0] <= 0xAFF) {
//P1->OUT = ~BIT0;
if (P1->IFG & BIT1) {
P4->OUT ^= BIT6;
}
P1->IFG &= ~BIT1;
TIMER_A0->CCR[0] = 15000 - 1;
TIMER_A0->CCR[4] = 15000 / 1.5;

}
else if (ADC14->MEM[0] > 0xAFF & ADC14->MEM[0] <= 0xCFF) {
// P1->OUT = ~BIT0;
if (P1->IFG & BIT1) {
P4->OUT ^= BIT6;
}
P1->IFG &= ~BIT1;
TIMER_A0->CCR[0] = 10000 - 1;
TIMER_A0->CCR[4] = 10000 / 1.2;

}
else if (ADC14->MEM[0] > 0xCFF & ADC14->MEM[0] <= 0xFFF) {
//P1->OUT = ~BIT0;
if (P1->IFG & BIT1) {
if(EUSCI_A0->IFG & EUSCI_A_IFG_RXIFG)
//temp = EUSCI_A0->RXBUF;
EUSCI_A0->IFG &= ~EUSCI_A_IFG_RXIFG;
P4->OUT ^= BIT6;
while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));
EUSCI_A0->TXBUF = EUSCI_A0->RXBUF;
EUSCI_A0->TXBUF = "B";

}
P1->IFG &= ~BIT1;

TIMER_A0->CCR[0] = 5000 - 1;
TIMER_A0->CCR[4] = 5000 / 1.1;

}


}

  • > EUSCI_A0->BRW = 78; // 12000000/16/9600

    Since you're not changing the clock, SMCLK is running at about 3MHz, not 12MHz, so BRW should be more like 20 here. I don't see an entry for 3MHz in TRM (SLAU356I) Table 24-5 (which seems a bit odd), but with UCOS16=0, MCTL=0, and  BRW=313 my calculator says you'll get 0.1% accuracy, which is pretty good.

  • Hi ,

    Thanks you for the reply.

    I changed the BRW value to 313. the serial port is showing is printing blank values. Do I have any other uart communication settings ?

  • > EUSCI_A0->MCTLW = (2 << EUSCI_A_MCTLW_BRF_OFS) |EUSCI_A_MCTLW_OS16;

    Did you set [UC]OS16=0? That's part of the BRW=313 setting. I suggest setting everything to 0:

    > EUSCI_A0->MCTLW = 0*EUSCI_A_MCTLW_OS16;  // UCOS16=0, no modulation

  • Hi ,

    This what I did changed..

    EUSCI_A0->BRW = 313; // 12000000/16/9600
    //EUSCI_A0->MCTLW = (2 << EUSCI_A_MCTLW_BRF_OFS) |EUSCI_A_MCTLW_OS16;
    EUSCI_A0->MCTLW = 0*EUSCI_A_MCTLW_OS16;
    EUSCI_A0->CTLW0 &= ~EUSCI_A_CTLW0_SWRST; // Initialize eUSCI
    EUSCI_A0->IFG &= ~EUSCI_A_IFG_RXIFG; // Clear eUSCI RX interrupt flag
    EUSCI_A0->IE |= EUSCI_A_IE_RXIE; // Enable USCI_A0 RX interrupt

    Now it is giving out the letter "H" instead of "B"

  • >while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));
    >EUSCI_A0->TXBUF = EUSCI_A0->RXBUF;
    >EUSCI_A0->TXBUF = "B";

    1) Write a character ('B'), not a pointer ("B") to TXBUF. I suspect this is what you're seeing.

    2) Make sure you have space in TXBUF before writing to it. This may not be your problem now, but it will be eventually.

    >while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));

    >EUSCI_A0->TXBUF = EUSCI_A0->RXBUF;

    >while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));
    >EUSCI_A0->TXBUF = 'B';

  • Hi,

    Thank you again for the response.

    I made the changes as you mentioned here.

    I started getting the results. I owe you one.

    My goal is to send a string and view it in the Serial Port. An example will be sending 'Hello world'  instead of 'B'. So for each button press I need to get

    'Hello world' 

    'Hello world' 

    'Hello world' 

    and so on

    . Can you please help me with this last part ? 

  • You might consider the uart_puts() and uart_putc() from over here:

    https://e2e.ti.com/support/microcontrollers/msp430/f/166/p/519923/1895391

    That uart_putc() uses driverlib, but it translates directly into the code sequence you have above.

    You should be wary of sending a string like this from an ISR, since it blocks the ISR from returning. Sending "Hello World" at 9600bps will take 11ms.

  • Hi Bruce,

    Thank you again.

    I will look into it and let you know.

  • #include "ti/devices/msp432p4xx/inc/msp.h"
    volatile unsigned int i;
    char *TXData []= {"Anticlockwise \r"};
    int main(void) {

    WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD; // Stop WDT


    // GPIO Setup
    P4->OUT &= ~BIT6; //Direction of Motor
    P4->DIR |= BIT6; //Set Direction of the motor

    P1->OUT = BIT1;
    P1->REN = BIT1; // Enable pull-up resistor (P1.1 output high)
    P1->IFG = 0; // Clear all P1 interrupt flags
    P1->IE = BIT1; // Enable interrupt for P1.1
    P1->IES = BIT1; // Interrupt on high-to-low transition


    P2->SEL0 |= 0x80;
    P2->SEL1 &= ~0x80;//PWM
    P2->DIR |= 0x80;

    TIMER_A0->CCR[0] = 10000 - 1; /* PWM Period */
    TIMER_A0->CCTL[4] = 0xE0; /* CCR4 reset/set mode */
    TIMER_A0->CTL = 0x0214; /* use SMCLK, count up, clear TA0R register */

    P5->SEL1 |= BIT4; // Configure P5.4 for ADC
    P5->SEL0 |= BIT4;


    //Ports for UART and LED

    P1->DIR |= BIT0;
    P1->OUT &= ~BIT0; // P1.0 LED

    // Configure UART pins
    P1->SEL0 |= BIT2 | BIT3; // set 2-UART pin as second function
    //UART config
    EUSCI_A0->CTLW0 |= EUSCI_A_CTLW0_SWRST; // Put eUSCI in reset
    EUSCI_A0->CTLW0 = EUSCI_A_CTLW0_SWRST |EUSCI_A_CTLW0_SSEL__SMCLK; // Remain eUSCI in reset and Configure eUSCI clock source for SMCLK

    EUSCI_A0->BRW = 313; // 12000000/16/9600
    //EUSCI_A0->MCTLW = (2 << EUSCI_A_MCTLW_BRF_OFS) |EUSCI_A_MCTLW_OS16;
    // EUSCI_A_MCTLW_OS16 = 0;
    EUSCI_A0->MCTLW = 0*EUSCI_A_MCTLW_OS16;
    EUSCI_A0->CTLW0 &= ~EUSCI_A_CTLW0_SWRST; // Initialize eUSCI
    EUSCI_A0->IFG &= ~EUSCI_A_IFG_RXIFG; // Clear eUSCI RX interrupt flag
    EUSCI_A0->IE |= EUSCI_A_IE_RXIE; // Enable USCI_A0 RX interrupt


    // Enable global interrupt
    __enable_irq(); // Enable ADC interrupt in NVIC module
    NVIC->ISER[0] = 1 << ((ADC14_IRQn) & 31);

    // Sampling time, S&H=16, ADC14 on
    ADC14->CTL0 = ADC14_CTL0_SHT0_2 | ADC14_CTL0_SHP | ADC14_CTL0_ON;//,Pulse sample mode is selected,core is ready to power up when a valid conversion is triggered.
    ADC14->CTL1 = ADC14_CTL1_RES_2; // Use sampling timer, 12-bit conversion results

    ADC14->MCTL[0] |= ADC14_MCTLN_INCH_1; // A1 ADC input select; Vref=AVCC
    ADC14->IER0 |= ADC14_IER0_IE0; // Enable ADC conv complete interrupt

    ADC14->IER0 = ADC14_IER0_IE0; // Enable ADC14IFG.0
    SCB->SCR &= ~SCB_SCR_SLEEPONEXIT_Msk; // Wake up on exit from ISR

    // Ensures SLEEPONEXIT takes effect immediately
    __DSB();

    while (1)
    {


    //Start sampling/conversion
    ADC14->CTL0 |= ADC14_CTL0_ENC | ADC14_CTL0_SC;
    __sleep();

    __no_operation(); // For debugger
    }
    }

    // ADC14 interrupt service routine
    void ADC14_IRQHandler(void) {
    volatile uint8_t temp;
    if (ADC14->MEM[0] > 0x0F & ADC14->MEM[0] <= 0x7F) {
    P4->OUT = 0x0000;
    TIMER_A0->CCR[0] = 0;
    TIMER_A0->CCR[4] = 0;

    }

    if (ADC14->MEM[0] > 0x7F & ADC14->MEM[0] <= 0xFF) {
    if (P1->IFG & BIT1) {
    P4->OUT ^= BIT6;
    }
    P1->IFG &= ~BIT1;

    TIMER_A0->CCR[0] = 50000 - 1;
    TIMER_A0->CCR[4] = 50000 / 5;

    }
    else if (ADC14->MEM[0] > 0xFF & ADC14->MEM[0] <= 0x2FF) {
    if (P1->IFG & BIT1) {
    P4->OUT ^= BIT6;

    }
    P1->IFG &= ~BIT1;


    TIMER_A0->CCR[0] = 40000 - 1;
    TIMER_A0->CCR[4] = 40000 / 3;

    }
    else if (ADC14->MEM[0] > 0x2FF & ADC14->MEM[0] <= 0x7FF) {
    //P1->OUT = ~BIT0;
    if (P1->IFG & BIT1) {
    if(EUSCI_A0->IFG & EUSCI_A_IFG_RXIFG)
    //temp = EUSCI_A0->RXBUF;
    EUSCI_A0->IFG &= ~EUSCI_A_IFG_RXIFG;
    P4->OUT ^= BIT6;
    while(TXData[i]){
    while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));

    EUSCI_A0->TXBUF = EUSCI_A0->RXBUF;

    while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));
    EUSCI_A0->TXBUF = TXData[i];
    i++;
    }
    i=0;
    }
    P1->IFG &= ~BIT1;
    TIMER_A0->CCR[0] = 20000 - 1;
    TIMER_A0->CCR[4] = 20000 / 2;

    }

    else if (ADC14->MEM[0] > 0x7FF & ADC14->MEM[0] <= 0xAFF) {
    //P1->OUT = ~BIT0;
    if (P1->IFG & BIT1) {
    P4->OUT ^= BIT6;
    }
    P1->IFG &= ~BIT1;
    TIMER_A0->CCR[0] = 15000 - 1;
    TIMER_A0->CCR[4] = 15000 / 1.5;

    }
    else if (ADC14->MEM[0] > 0xAFF & ADC14->MEM[0] <= 0xCFF) {
    // P1->OUT = ~BIT0;
    if (P1->IFG & BIT1) {
    P4->OUT ^= BIT6;
    }
    P1->IFG &= ~BIT1;
    TIMER_A0->CCR[0] = 10000 - 1;
    TIMER_A0->CCR[4] = 10000 / 1.2;

    }
    else if (ADC14->MEM[0] > 0xCFF & ADC14->MEM[0] <= 0xFFF) {
    //P1->OUT = ~BIT0;
    if (P1->IFG & BIT1) {
    if(EUSCI_A0->IFG & EUSCI_A_IFG_RXIFG)
    //temp = EUSCI_A0->RXBUF;
    EUSCI_A0->IFG &= ~EUSCI_A_IFG_RXIFG;
    P4->OUT ^= BIT6;
    while(TXData[i]){
    while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));

    EUSCI_A0->TXBUF = EUSCI_A0->RXBUF;

    while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));
    EUSCI_A0->TXBUF = TXData[i];
    i++;
    }
    i=0;
    }
    P1->IFG &= ~BIT1;

    TIMER_A0->CCR[0] = 5000 - 1;
    TIMER_A0->CCR[4] = 5000 / 1.1;

    }


    }

    I had another question, I modified the code a bit before trying out the library you send out. It is spitting out strings, but some random gibberish. Do you think I can modify this and get the result ?

  • > char *TXData []= {"Anticlockwise \r"};

    I think you want

    > char TXData []= {"Anticlockwise \r"};

    Warnings shouldn't be ignored.

  • Hi Bruce,

    I just got it to work. You are awesome. Don't know what to say. Can I connect with you in LinkedIn ?

  • Hi I am trying to print "Clockwise" and  "Anticlockwise" upon consecutive button presses The clockwise part is not getting printed, the "fl" flag is not getting activated.

    #include "ti/devices/msp432p4xx/inc/msp.h"
    volatile unsigned int i;
    int fl = 0;
    char TXData []= {"Clockwise "};
    int main(void) {

    WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD; // Stop WDT


    // GPIO Setup
    P4->OUT &= ~BIT6; //Direction of Motor
    P4->DIR |= BIT6; //Set Direction of the motor

    P1->OUT = BIT1;
    P1->REN = BIT1; // Enable pull-up resistor (P1.1 output high)
    P1->IFG = 0; // Clear all P1 interrupt flags
    P1->IE = BIT1; // Enable interrupt for P1.1
    P1->IES = BIT1; // Interrupt on high-to-low transition


    P2->SEL0 |= 0x80;
    P2->SEL1 &= ~0x80;//PWM
    P2->DIR |= 0x80;

    TIMER_A0->CCR[0] = 10000 - 1; /* PWM Period */
    TIMER_A0->CCTL[4] = 0xE0; /* CCR4 reset/set mode */
    TIMER_A0->CTL = 0x0214; /* use SMCLK, count up, clear TA0R register */

    P5->SEL1 |= BIT4; // Configure P5.4 for ADC
    P5->SEL0 |= BIT4;


    //Ports for UART and LED

    P1->DIR |= BIT0;
    P1->OUT &= ~BIT0; // P1.0 LED

    // Configure UART pins
    P1->SEL0 |= BIT2 | BIT3; // set 2-UART pin as second function
    //UART config
    EUSCI_A0->CTLW0 |= EUSCI_A_CTLW0_SWRST; // Put eUSCI in reset
    EUSCI_A0->CTLW0 = EUSCI_A_CTLW0_SWRST |EUSCI_A_CTLW0_SSEL__SMCLK; // Remain eUSCI in reset and Configure eUSCI clock source for SMCLK

    EUSCI_A0->BRW = 313; // 12000000/16/9600
    //EUSCI_A0->MCTLW = (2 << EUSCI_A_MCTLW_BRF_OFS) |EUSCI_A_MCTLW_OS16;
    // EUSCI_A_MCTLW_OS16 = 0;
    EUSCI_A0->MCTLW = 0*EUSCI_A_MCTLW_OS16;
    EUSCI_A0->CTLW0 &= ~EUSCI_A_CTLW0_SWRST; // Initialize eUSCI
    EUSCI_A0->IFG &= ~EUSCI_A_IFG_RXIFG; // Clear eUSCI RX interrupt flag
    EUSCI_A0->IE |= EUSCI_A_IE_RXIE; // Enable USCI_A0 RX interrupt


    // Enable global interrupt
    __enable_irq(); // Enable ADC interrupt in NVIC module
    NVIC->ISER[0] = 1 << ((ADC14_IRQn) & 31);

    // Sampling time, S&H=16, ADC14 on
    ADC14->CTL0 = ADC14_CTL0_SHT0_2 | ADC14_CTL0_SHP | ADC14_CTL0_ON;//,Pulse sample mode is selected,core is ready to power up when a valid conversion is triggered.
    ADC14->CTL1 = ADC14_CTL1_RES_2; // Use sampling timer, 12-bit conversion results

    ADC14->MCTL[0] |= ADC14_MCTLN_INCH_1; // A1 ADC input select; Vref=AVCC
    ADC14->IER0 |= ADC14_IER0_IE0; // Enable ADC conv complete interrupt

    ADC14->IER0 = ADC14_IER0_IE0; // Enable ADC14IFG.0
    SCB->SCR &= ~SCB_SCR_SLEEPONEXIT_Msk; // Wake up on exit from ISR

    // Ensures SLEEPONEXIT takes effect immediately
    __DSB();

    while (1)
    {


    //Start sampling/conversion
    ADC14->CTL0 |= ADC14_CTL0_ENC | ADC14_CTL0_SC;
    __sleep();

    __no_operation(); // For debugger
    }
    }

    // ADC14 interrupt service routine
    void ADC14_IRQHandler(void) {

    if (ADC14->MEM[0] > 0x00 & ADC14->MEM[0] <= 0xFF) {
    if (P1->IFG & BIT1) {
    if(EUSCI_A0->IFG & EUSCI_A_IFG_RXIFG)
    //temp = EUSCI_A0->RXBUF;
    EUSCI_A0->IFG &= ~EUSCI_A_IFG_RXIFG;
    P4->OUT ^= BIT6;
    fl =~fl;
    printf("%d",fl);

    if(fl == 0){
    strcpy(TXData, "Clockwise ");
    }
    else if(fl == 1){
    //printf("why");
    strcpy(TXData, "Anticlockwise ");
    }
    while(TXData[i]){
    while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));

    EUSCI_A0->TXBUF = EUSCI_A0->RXBUF;

    while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));
    EUSCI_A0->TXBUF = TXData[i];
    i++;
    }
    i=0;
    }
    P1->IFG &= ~BIT1;

    TIMER_A0->CCR[0] = 50000 - 1;
    TIMER_A0->CCR[4] = 50000 / 5;

    }
    if (ADC14->MEM[0] > 0xFF & ADC14->MEM[0] <= 0x7FF) {
    if (P1->IFG & BIT1) {
    if(EUSCI_A0->IFG & EUSCI_A_IFG_RXIFG)
    //temp = EUSCI_A0->RXBUF;
    EUSCI_A0->IFG &= ~EUSCI_A_IFG_RXIFG;
    P4->OUT ^= BIT6;
    fl &= ~fl;
    printf("%d",fl);
    if(fl == 0){
    strcpy(TXData, "ACW ");
    }
    else if(fl == 1){
    //printf("why");
    strcpy(TXData, "CW ");
    }
    while(TXData[i]){
    while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));

    EUSCI_A0->TXBUF = EUSCI_A0->RXBUF;

    while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));
    EUSCI_A0->TXBUF = TXData[i];
    i++;
    }
    i=0;
    }
    P1->IFG &= ~BIT1;

    TIMER_A0->CCR[0] = 10000 - 1;
    TIMER_A0->CCR[4] = 10000 / 3;

    }
    if (ADC14->MEM[0] > 0x7FF & ADC14->MEM[0] <= 0xFFF) {
    if (P1->IFG & BIT1) {
    if(EUSCI_A0->IFG & EUSCI_A_IFG_RXIFG)
    //temp = EUSCI_A0->RXBUF;
    EUSCI_A0->IFG &= ~EUSCI_A_IFG_RXIFG;
    P4->OUT ^= BIT6;
    fl =~fl;

    if(fl == 0){
    strcpy(TXData, "Clockwise ");
    }
    else if(fl == 1){
    //printf("why");
    strcpy(TXData, "Anticlockwise ");
    }
    while(TXData[i]){
    while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));

    EUSCI_A0->TXBUF = EUSCI_A0->RXBUF;

    while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));
    EUSCI_A0->TXBUF = TXData[i];
    i++;
    }
    i=0;
    }
    P1->IFG &= ~BIT1;

    TIMER_A0->CCR[0] = 5000 - 1;
    TIMER_A0->CCR[4] = 5000 / 2;

    }
    // else if (ADC14->MEM[0] > 0x7FF & ADC14->MEM[0] <= 0xAFF) {
    // //P1->OUT = ~BIT0;
    // if (P1->IFG & BIT1) {
    // P4->OUT ^= BIT6;
    // }
    // P1->IFG &= ~BIT1;
    // TIMER_A0->CCR[0] = 15000 - 1;
    // TIMER_A0->CCR[4] = 15000 / 1.5;
    //
    // }
    // else if (ADC14->MEM[0] > 0xAFF & ADC14->MEM[0] <= 0xCFF) {
    // // P1->OUT = ~BIT0;
    // if (P1->IFG & BIT1) {
    // P4->OUT ^= BIT6;
    // }
    // P1->IFG &= ~BIT1;
    // TIMER_A0->CCR[0] = 10000 - 1;
    // TIMER_A0->CCR[4] = 10000 / 1.2;
    //
    // }
    // else if (ADC14->MEM[0] > 0xCFF & ADC14->MEM[0] <= 0xFFF) {
    // //P1->OUT = ~BIT0;
    // if (P1->IFG & BIT1) {
    // if(EUSCI_A0->IFG & EUSCI_A_IFG_RXIFG)
    // //temp = EUSCI_A0->RXBUF;
    // EUSCI_A0->IFG &= ~EUSCI_A_IFG_RXIFG;
    // P4->OUT ^= BIT6;
    // while(TXData[i]){
    // while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));
    //
    // EUSCI_A0->TXBUF = EUSCI_A0->RXBUF;
    //
    // while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));
    // EUSCI_A0->TXBUF = TXData[i];
    // i++;
    // }
    // i=0;
    // }
    // P1->IFG &= ~BIT1;
    //
    // TIMER_A0->CCR[0] = 5000 - 1;
    // TIMER_A0->CCR[4] = 5000 / 1.1;

    // }


    }

  • > fl =~fl;

    This doesn't change 0->1 it changes 0->0xFFFF. To flip just 0->1->0 (bit 0) you could use XOR:

    > fl ^= 1;

  • Hi Bruce,

    Thanks for all your help. Can you please let me know how you calculated the BRW value because I couldn't find it in MSP432 Reference Manual Table. Why did you turn off the modulation ?

  • BRW is a divisor for (in this case) SMCLK=3MHz. I divided 3MHz / 9600bps = 312.5, rounded to 313. To check my work I divided 3MHz/313=9584.6 (actual bps) and 9600/9584.6=1.0016, or 0.16% error.

    The important part was setting UCOS16=0. If you do the above with the addition of a /16, you end up with something like 2% error.

    Since I didn't know the modulation constants for BRCLK=3MHz (still seems like a funny omission), I suggested turning off the modulation since that might make things worse. You could try computing them using TRM Sec 24.3.10, but trying to fix a 0.16% error probably isn't worth the trouble.

  • Hi Bruce,

    Thanks again. I had one more doubt I am using an ADC in this code to control the frequency of the PWM wave It seems that I am not able to access all the "if" conditions once I add the UART communication module. An example will be, I am not able to change the CCR0 value from 50,000 to 5,000 instead it is only fluctuating between 10,000 and 5,000. I am using a potentiometer at port 5.4 to control the voltage level(Ist terminal of the potentiometer is connected to 5V Vcc from MSP432, 2nd terminal to pin 5.4, and third terminal to the GND on the MSP432 board). The hardware seems to be working fine because when I remove the code related to UART I am getting the required voltage variation in ADC.

    #include "ti/devices/msp432p4xx/inc/msp.h"
    volatile unsigned int i;
    int fl = 0;
    char TXData []= {"CW "};
    int main(void) {

    WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD; // Stop WDT


    // GPIO Setup
    P4->OUT &= ~BIT6; //Direction of Motor
    P4->DIR |= BIT6; //Set Direction of the motor

    P1->OUT = BIT1;
    P1->REN = BIT1; // Enable pull-up resistor (P1.1 output high)
    P1->IFG = 0; // Clear all P1 interrupt flags
    P1->IE = BIT1; // Enable interrupt for P1.1
    P1->IES = BIT1; // Interrupt on high-to-low transition


    P2->SEL0 |= 0x80;
    P2->SEL1 &= ~0x80;//PWM
    P2->DIR |= 0x80;

    TIMER_A0->CCR[0] = 10000 - 1; /* PWM Period */
    TIMER_A0->CCTL[4] = 0xE0; /* CCR4 reset/set mode */
    TIMER_A0->CTL = 0x0214; /* use SMCLK, count up, clear TA0R register */

    P5->SEL1 |= BIT4; // Configure P5.4 for ADC
    P5->SEL0 |= BIT4;


    //Ports for UART and LED

    P1->DIR |= BIT0;
    P1->OUT &= ~BIT0; // P1.0 LED

    // Configure UART pins
    P1->SEL0 |= BIT2 | BIT3; // set 2-UART pin as second function
    //UART config
    EUSCI_A0->CTLW0 |= EUSCI_A_CTLW0_SWRST; // Put eUSCI in reset
    EUSCI_A0->CTLW0 = EUSCI_A_CTLW0_SWRST |EUSCI_A_CTLW0_SSEL__SMCLK; // Remain eUSCI in reset and Configure eUSCI clock source for SMCLK

    EUSCI_A0->BRW = 313; // 12000000/16/9600
    //EUSCI_A0->MCTLW = (2 << EUSCI_A_MCTLW_BRF_OFS) |EUSCI_A_MCTLW_OS16;
    // EUSCI_A_MCTLW_OS16 = 0;
    EUSCI_A0->MCTLW = 0*EUSCI_A_MCTLW_OS16;
    EUSCI_A0->CTLW0 &= ~EUSCI_A_CTLW0_SWRST; // Initialize eUSCI
    EUSCI_A0->IFG &= ~EUSCI_A_IFG_RXIFG; // Clear eUSCI RX interrupt flag
    EUSCI_A0->IE |= EUSCI_A_IE_RXIE; // Enable USCI_A0 RX interrupt


    // Enable global interrupt
    __enable_irq(); // Enable ADC interrupt in NVIC module
    NVIC->ISER[0] = 1 << ((ADC14_IRQn) & 31);

    // Sampling time, S&H=16, ADC14 on
    ADC14->CTL0 = ADC14_CTL0_SHT0_2 | ADC14_CTL0_SHP | ADC14_CTL0_ON;//,Pulse sample mode is selected,core is ready to power up when a valid conversion is triggered.
    ADC14->CTL1 = ADC14_CTL1_RES_2; // Use sampling timer, 12-bit conversion results

    ADC14->MCTL[0] |= ADC14_MCTLN_INCH_1; // A1 ADC input select; Vref=AVCC
    ADC14->IER0 |= ADC14_IER0_IE0; // Enable ADC conv complete interrupt

    ADC14->IER0 = ADC14_IER0_IE0; // Enable ADC14IFG.0
    SCB->SCR &= ~SCB_SCR_SLEEPONEXIT_Msk; // Wake up on exit from ISR

    // Ensures SLEEPONEXIT takes effect immediately
    __DSB();

    while (1)
    {


    //Start sampling/conversion
    ADC14->CTL0 |= ADC14_CTL0_ENC | ADC14_CTL0_SC;
    __sleep();

    __no_operation(); // For debugger
    }
    }

    // ADC14 interrupt service routine
    void ADC14_IRQHandler(void) {

    if (ADC14->MEM[0] > 0x00 & ADC14->MEM[0] <= 0xFF) {
    if (P1->IFG & BIT1) {
    if(EUSCI_A0->IFG & EUSCI_A_IFG_RXIFG)
    //temp = EUSCI_A0->RXBUF;
    EUSCI_A0->IFG &= ~EUSCI_A_IFG_RXIFG;
    P4->OUT ^= BIT6;
    fl ^= 1;
    printf("%d",fl);
    if(fl == 0){
    strcpy(TXData, "ACW ");
    }
    else if(fl == 1){
    //printf("why");
    strcpy(TXData, "CW ");
    }
    while(TXData[i]){
    while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));

    EUSCI_A0->TXBUF = EUSCI_A0->RXBUF;

    while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));
    EUSCI_A0->TXBUF = TXData[i];
    i++;
    }
    i=0;
    }
    P1->IFG &= ~BIT1;

    TIMER_A0->CCR[0] = 50000 - 1;
    TIMER_A0->CCR[4] = 50000 / 5;

    }
    if (ADC14->MEM[0] > 0xFF & ADC14->MEM[0] <= 0x7FF) {
    if (P1->IFG & BIT1) {
    if(EUSCI_A0->IFG & EUSCI_A_IFG_RXIFG)
    //temp = EUSCI_A0->RXBUF;
    EUSCI_A0->IFG &= ~EUSCI_A_IFG_RXIFG;
    P4->OUT ^= BIT6;
    fl ^= 1;
    printf("%d",fl);
    if(fl == 0){
    strcpy(TXData, "ACW ");
    }
    else if(fl == 1){
    //printf("why");
    strcpy(TXData, "CW ");
    }
    while(TXData[i]){
    while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));

    EUSCI_A0->TXBUF = EUSCI_A0->RXBUF;

    while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));
    EUSCI_A0->TXBUF = TXData[i];
    i++;
    }
    i=0;
    }
    P1->IFG &= ~BIT1;

    TIMER_A0->CCR[0] = 10000 - 1;
    TIMER_A0->CCR[4] = 10000 / 3;

    }
    if (ADC14->MEM[0] > 0x7FF & ADC14->MEM[0] <= 0xFFF) {
    if (P1->IFG & BIT1) {
    if(EUSCI_A0->IFG & EUSCI_A_IFG_RXIFG)
    //temp = EUSCI_A0->RXBUF;
    EUSCI_A0->IFG &= ~EUSCI_A_IFG_RXIFG;
    P4->OUT ^= BIT6;
    fl ^=1;

    if(fl == 0){
    strcpy(TXData, "CW ");
    }
    else if(fl == 1){
    //printf("why");
    strcpy(TXData, "ACW");
    }
    while(TXData[i]){
    while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));

    EUSCI_A0->TXBUF = EUSCI_A0->RXBUF;

    while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));
    EUSCI_A0->TXBUF = TXData[i];
    i++;
    }
    i=0;
    }
    P1->IFG &= ~BIT1;

    TIMER_A0->CCR[0] = 5000 - 1;
    TIMER_A0->CCR[4] = 5000 / 2;

    }

    }

  • How do you tell that this is happening (or not happening)? A breakpoint? The LED? A scope? What code do you actually remove?

    The primary side-effect of running the UART in blocking mode like this is that the sequence takes longer.

    Sending 4 bytes, ("ACW ") plus 4 copies of RXBUF takes 8ms, which is shorter than 50000 ticks (16ms) but longer than 10000 ticks (3ms). That might create one illusion.

    Adding 8ms to the ISR would have the effect of de-bouncing the button, which might create a different illusion.

    One thing to watch out for is that as you turn the pot down near 0V, you're increasing the source impedance to the ADC, which will lengthen its (required) Sample/Hold time. That could in turn throw your readings off.  This would not be an artifact of the UART code.

  • I am using an oscilloscope to check the pwm wave . I tried decreasing the CCR0 values so that the time required to count will be less than 8 ms, but there is not much change. Sorry for the lack of clarity:

    I was talking about this code:

    // Configure UART pins
    P1->SEL0 |= BIT2 | BIT3; // set 2-UART pin as second function
    //UART config
    EUSCI_A0->CTLW0 |= EUSCI_A_CTLW0_SWRST; // Put eUSCI in reset
    EUSCI_A0->CTLW0 = EUSCI_A_CTLW0_SWRST |EUSCI_A_CTLW0_SSEL__SMCLK; // Remain eUSCI in reset and Configure eUSCI clock source for SMCLK

    EUSCI_A0->BRW = 313; // 12000000/16/9600
    EUSCI_A0->MCTLW = 0*EUSCI_A_MCTLW_OS16;
    EUSCI_A0->CTLW0 &= ~EUSCI_A_CTLW0_SWRST; // Initialize eUSCI
    EUSCI_A0->IFG &= ~EUSCI_A_IFG_RXIFG; // Clear eUSCI RX interrupt flag
    EUSCI_A0->IE |= EUSCI_A_IE_RXIE; // Enable USCI_A0 RX interrupt

    AND also this part in the button interrupt. The only line inside the button interrupt (P1->IFG & BIT1) that will be present is flipping the port 4.6 value. 

    if(EUSCI_A0->IFG & EUSCI_A_IFG_RXIFG)
    //temp = EUSCI_A0->RXBUF;
    EUSCI_A0->IFG &= ~EUSCI_A_IFG_RXIFG;
    P4->OUT ^= BIT6;
    fl ^=1;

    if(fl == 0){
    strcpy(TXData, "CW ");
    }
    else if(fl == 1){
    //printf("why");
    strcpy(TXData, "ACW");
    }
    while(TXData[i]){
    while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));

    EUSCI_A0->TXBUF = EUSCI_A0->RXBUF;

    while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));
    EUSCI_A0->TXBUF = TXData[i];
    i++;
    }
    i=0;

  • >char TXData[] = { "CW " };

    This isn't big enough to hold "ACW ", and the strcpy is overrunning and changing "fl". You're not short of memory, so add some extra:

    >char TXData[9+1] = { "CW " };

    ----------------

    Set a breakpoint where you're setting CCR[0]. If you reach the breakpoint, that implies there's something with the way you're measuring. If you don't, then pause the program (two vertical bars button) and look at ADC14->MEM[0] in the Registers view to see what value you're actually getting. Either way, that should tell you which direction to look.

    I don't have your equipment, so you'll need to dig into this.

  • Hi,

    I tried checking the value in ADC14->MEM[0].After adjusting the potentiometer, the value I see in the register are either 0x5F which is indicated by the 20% duty cycle or the value is at 0x47F indicated by the 50% duty cycle .I tried changing the condition to check if the value in ADC14->MEM[0]  is between these values and I am not getting any results for that. So its either at 5F or 47F depending on the direction in which I turn the potentiometer

  • 0x47F should fall into the range for 10000/3=33%. I'm not sure what you're measuring.

    Do I understand that the only two MEM values you can generate are 0x5F (0.077V) or 0x47F (0.927V)? What voltage do you see with a voltmeter at the P5.4 pin?

  • Hi Bruce,

    I made slight changes in the code. Here it is. I measured the voltage at Pin5.4,it is showing 4.0 V and the duty cycle at this time is 50%. The ADCMEM[0] value is 0x00000524. When I measured the voltage at Pin 5.4  for a duty cycle of 25%, it's showing 0.01V. The ADCMEM[0] value is 0x0000005A.

    #include "ti/devices/msp432p4xx/inc/msp.h"
    volatile unsigned int i;
    int fl = 0;
    char TXData [10]= {""};
    int main(void) {

    WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD; // Stop WDT


    // GPIO Setup
    P4->OUT &= ~BIT6; //Direction of Motor
    P4->DIR |= BIT6; //Set Direction of the motor

    P1->OUT = BIT1;
    P1->REN = BIT1; // Enable pull-up resistor (P1.1 output high)
    P1->IFG = 0; // Clear all P1 interrupt flags
    P1->IE = BIT1; // Enable interrupt for P1.1
    P1->IES = BIT1; // Interrupt on high-to-low transition


    P2->SEL0 |= 0x80;
    P2->SEL1 &= ~0x80;//PWM
    P2->DIR |= 0x80;


    TIMER_A0->CCTL[4] = 0xE0; /* CCR4 reset/set mode */
    TIMER_A0->CTL = 0x0214; /* use SMCLK, count up, clear TA0R register */

    P5->SEL1 |= BIT4; // Configure P5.4 for ADC
    P5->SEL0 |= BIT4;


    //Ports for UART and LED

    P1->DIR |= BIT0;
    P1->OUT &= ~BIT0; // P1.0 LED

    // Configure UART pins
    P1->SEL0 |= BIT2 | BIT3; // set 2-UART pin as second function
    //UART config
    EUSCI_A0->CTLW0 |= EUSCI_A_CTLW0_SWRST; // Put eUSCI in reset
    EUSCI_A0->CTLW0 = EUSCI_A_CTLW0_SWRST |EUSCI_A_CTLW0_SSEL__SMCLK; // Remain eUSCI in reset and Configure eUSCI clock source for SMCLK
    EUSCI_A0->BRW = 313; // 3Mhz/9600
    EUSCI_A0->MCTLW = 0*EUSCI_A_MCTLW_OS16;
    EUSCI_A0->CTLW0 &= ~EUSCI_A_CTLW0_SWRST; // Initialize eUSCI
    EUSCI_A0->IFG &= ~EUSCI_A_IFG_RXIFG; // Clear eUSCI RX interrupt flag
    EUSCI_A0->IE |= EUSCI_A_IE_RXIE; // Enable USCI_A0 RX interrupt


    // Enable global interrupt
    __enable_irq(); // Enable ADC interrupt in NVIC module
    NVIC->ISER[0] = 1 << ((ADC14_IRQn) & 31);

    // Sampling time, S&H=16, ADC14 on
    ADC14->CTL0 = ADC14_CTL0_SHT0_2 | ADC14_CTL0_SHP | ADC14_CTL0_ON;//,Pulse sample mode is selected,core is ready to power up when a valid conversion is triggered.
    ADC14->CTL1 = ADC14_CTL1_RES_2; // Use sampling timer, 12-bit conversion results

    ADC14->MCTL[0] |= ADC14_MCTLN_INCH_1; // A1 ADC input select; Vref=AVCC
    ADC14->IER0 |= ADC14_IER0_IE0; // Enable ADC conv complete interrupt

    ADC14->IER0 = ADC14_IER0_IE0; // Enable ADC14IFG.0
    SCB->SCR &= ~SCB_SCR_SLEEPONEXIT_Msk; // Wake up on exit from ISR

    // Ensures SLEEPONEXIT takes effect immediately
    __DSB();

    while (1)
    {


    //Start sampling/conversion
    ADC14->CTL0 |= ADC14_CTL0_ENC | ADC14_CTL0_SC;
    __sleep();

    __no_operation(); // For debugger
    }
    }

    // ADC14 interrupt service routine
    void ADC14_IRQHandler(void) {

    if (ADC14->MEM[0] > 0x00 & ADC14->MEM[0] <= 0xFF) {
    if (P1->IFG & BIT1) {
    if(EUSCI_A0->IFG & EUSCI_A_IFG_RXIFG)
    //temp = EUSCI_A0->RXBUF;
    EUSCI_A0->IFG &= ~EUSCI_A_IFG_RXIFG;
    P4->OUT ^= BIT6;
    fl ^= 1;
    printf("%d",fl);
    if(fl == 0){
    strcpy(TXData, "ACW ");
    }
    else if(fl == 1){
    //printf("why");
    strcpy(TXData, "CW ");
    }
    while(TXData[i]){
    while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));

    EUSCI_A0->TXBUF = EUSCI_A0->RXBUF;

    while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));
    EUSCI_A0->TXBUF = TXData[i];
    i++;
    }
    i=0;
    __delay_cycles(8000);
    P1->IFG &= ~BIT1;
    }


    TIMER_A0->CCR[0] = 50000 - 1;
    TIMER_A0->CCR[4] = 50000 / 4;

    }
    if (ADC14->MEM[0] > 0xFF & ADC14->MEM[0] <= 0xFFF) {
    if (P1->IFG & BIT1) {
    if(EUSCI_A0->IFG & EUSCI_A_IFG_RXIFG)
    //temp = EUSCI_A0->RXBUF;
    EUSCI_A0->IFG &= ~EUSCI_A_IFG_RXIFG;
    P4->OUT ^= BIT6;
    fl ^= 1;
    printf("%d",fl);
    if(fl == 0){
    strcpy(TXData, "ACW ");
    }
    else if(fl == 1){
    //printf("why");
    strcpy(TXData, "CW ");
    }
    while(TXData[i]){
    while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));

    EUSCI_A0->TXBUF = EUSCI_A0->RXBUF;

    while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));
    EUSCI_A0->TXBUF = TXData[i];
    i++;
    }
    i=0;
    __delay_cycles(8000);
    P1->IFG &= ~BIT1;
    }


    TIMER_A0->CCR[0] = 10000 - 1;
    TIMER_A0->CCR[4] = 10000 / 2;

    }

    }

  • It sounds as though you're getting predictable results from your code. The actual readings seem proportional but not quite right.

    1) Don't supply 4V to the pin. With Vcc=3.3V, the max is 3.6V. [Ref data sheet (SLAS826G) Sec 5.1] Overvoltage can damage the device.

    2) What are the specifications for your pot (range, tap resistance)? You're requesting 16 clocks for sample/hold, which with MODCLK=25MHz is about 0.6usec. This is good up to about 2kOhm of source impedance. As I mentioned earlier one of the hazards with a pot is that the source impedance is varying -- for some it varies quite a bit -- and this can throw your readings off. A simple experiment is to just increase the SHT setting [Ref TRM Table 22-5] and see whether you get better readings. You're in no real hurry, so try making it very long, maybe 192 clocks. If the pot is not your intended input device, you can compute the S/H time using the formula in TRM (SLAU356I) Sec 22.2.6.3

**Attention** This is a public forum