Sending MSP432’s ADC samples over “backchannel” UART

This is very cool. The MSP‑EXP432P401R LaunchPad™ [ slau597 ] supports an additional UART through XDS110 just for debug / sending data over to a PC. Even better:

The backchannel UART eUSCI_A0 is independent of the UART on the 40-pin BoosterPack connector eUSCI_A2.

Not that I am using any BoosterPacks, but that is very cool that we can keep serial writes to a computer separate from other things the MCU might be doing.

Now, the online community has written a printf function using this UART:

[ 43oh tutorial ] [ Sam Lewis’s note ]

Here’s a link to the CCS guide for MSP432 as that might also come in handy:

[ slau575b ]

And the resource explorer example for the making ADC conversions based on interrupts from Timer A:

[ adc14_single_conversion_repeat_timera_source.c ]

On my end, the printf and adc14 examples are working individually. I changed the baud rate to 57600 and printed out an unsigned 32 bit counter to PuTTy just to get an idea of how much data I could get through. It will probably be an overkill for just sampling ECG at 250 Hz, but I am sure it will work.

Here’s the slightly edited call to printf:

/* DriverLib Includes */
#include "driverlib.h";

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

/* UART Configuration Parameter. These are the configuration parameters to
* make the eUSCI A UART module to operate with a 9600 baud rate. These
* values were calculated using the online calculator that TI provides
* at:
*http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSP430BaudRateConverter/index.html
*/

// setting the baud rate to 57600 instead of 9600. It will easily support 250 Hz. 9600 should too, PuTTy is just printing slow.
// http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSP430BaudRateConverter/index.html
// use eUSCI, 12M clock
const eUSCI_UART_Config uartConfig =
{
EUSCI_A_UART_CLOCKSOURCE_SMCLK, // SMCLK Clock Source
13, //78, // BRDIV = 78
0, //2, // UCxBRF = 2
37, //0, // UCxBRS = 0
EUSCI_A_UART_NO_PARITY, // No Parity
EUSCI_A_UART_LSB_FIRST, // MSB First
EUSCI_A_UART_ONE_STOP_BIT, // One stop bit
EUSCI_A_UART_MODE, // UART mode
EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION // Oversampling
};

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

/* Selecting P1.2 and P1.3 in UART mode */
MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,
GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);

/* Setting DCO to 12MHz */
CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_12);

/* Configuring UART Module */
MAP_UART_initModule(EUSCI_A0_MODULE, &uartConfig);

/* Enable UART module */
MAP_UART_enableModule(EUSCI_A0_MODULE);

MAP_Interrupt_enableMaster();

/* Initialize values to display */
//char *s = "printf test";
//char c = '!';
//int i = 0;//-12345;
unsigned u = 0;//4321;
//long unsigned n = 1098765432;
//unsigned x = 0xABCD;

while(1)
{
//printf(EUSCI_A0_MODULE, "String %s\r\n", s);
//printf(EUSCI_A0_MODULE, "Char %c\r\n", c);
//printf(EUSCI_A0_MODULE, "Integer %i\r\n", i);
////printf(EUSCI_A0_MODULE, "%i\r\n", i);
//printf(EUSCI_A0_MODULE, "Unsigned %u\r\n";, u);
printf(EUSCI_A0_MODULE, "%u\r\n", u);
// printf(EUSCI_A0_MODULE, "Long %l\r\n", l);
//printf(EUSCI_A0_MODULE, "uNsigned loNg %n\r\n", n);
//printf(EUSCI_A0_MODULE, "heX %x\r\n", x);
u++;
}
}

I set the debug mode to release and set the optimizer to its max level. Lots of interesting advice popped out for setting pins to reduce current draw, and for replacing the while loop’s (for debugging) in TI’s .cmd file with timer modules.

The next step is to integrate the adc14 and printf codes. The simplest way of copy-paste combining the modules and commenting out irrelevant  lines works for a really slow rate, and I changing the comparator value (16000) isn’t really affecting anything. So I need to read the manual and find out what’s going on.

/*
* -------------------------------------------
* MSP432 DriverLib - v2_20_00_08
* -------------------------------------------
*
* --COPYRIGHT--,BSD,BSD
* Copyright (c) 2014, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS IS&quot;
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --/COPYRIGHT--*/
/*******************************************************************************
* MSP432 ADC14 - Single Channel Continuous Sample w/ Timer_A Trigger
*
* Description: In this ADC14 code example, a single input channel is sampled
* using the standard 3.3v reference. The source of the sample trigger for this
* example is Timer_A CCR1. The ADC is setup to continuously sample/convert
* from A0 when the trigger starts and store the results in resultsBuffer (it
* is setup to be a circular buffer where resPos overflows to 0). Timer_A is
* setup in Continuous mode and a Compare value of 16000 is set as the
* compare trigger. Once the Timer_A is started, after 0.5s it will trigger
* the ADC14 to start conversions. Inside the ADC ISR, the timer value is
* cleared and starts again from a 0 count. Essentially this example will use
* the Timer_A module to trigger an ADC conversion every 0.5 seconds.
*
* MSP432P401
* ------------------
* /|\| |
* | | |
* --|RST P5.5 |&amp;amp;lt;--- A0 (Analog Input)
* | |
* | |
* | |
* | |
* | |
*
* Author: Timothy Logan
******************************************************************************/
/* DriverLib Includes */
#include "driverlib.h"

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

#include <printf.h>;

/* Timer_A Continuous Mode Configuration Parameter */
const Timer_A_ContinuousModeConfig continuousModeConfig =
{
TIMER_A_CLOCKSOURCE_ACLK, // ACLK Clock Source
TIMER_A_CLOCKSOURCE_DIVIDER_1, // ACLK/1 = 32Khz
TIMER_A_TAIE_INTERRUPT_DISABLE, // Disable Timer ISR
TIMER_A_DO_CLEAR // Skip Clear Counter
};

/* Timer_A Compare Configuration Parameter */
const Timer_A_CompareModeConfig compareConfig =
{
TIMER_A_CAPTURECOMPARE_REGISTER_1, // Use CCR1
TIMER_A_CAPTURECOMPARE_INTERRUPT_DISABLE, // Disable CCR interrupt
TIMER_A_OUTPUTMODE_SET_RESET, // Toggle output but
16000 // 16000 Period
};

/* UART Configuration Parameter. These are the configuration parameters to
* make the eUSCI A UART module to operate with a 57600 //9600 baud rate. These
* values were calculated using the online calculator that TI provides
* at:
*http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSP430BaudRateConverter/index.html
* use eUSCI, 12M clock
*/
// setting the baud rate to 57600 instead of 9600. It will easily support 250 Hz. 9600 should too, PuTTy is just printing slow.

const eUSCI_UART_Config uartConfig =
{
EUSCI_A_UART_CLOCKSOURCE_SMCLK, // SMCLK Clock Source
13, //78, // BRDIV = 78
0, //2, // UCxBRF = 2
37, //0, // UCxBRS = 0
EUSCI_A_UART_NO_PARITY, // No Parity
EUSCI_A_UART_LSB_FIRST, // MSB First
EUSCI_A_UART_ONE_STOP_BIT, // One stop bit
EUSCI_A_UART_MODE, // UART mode
EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION // Oversampling
};

/* Statics */
// static volatile uint_fast16_t resultsBuffer[UINT8_MAX];
// static volatile uint8_t resPos;

int main(void)
{
/* Halting WDT */
MAP_WDT_A_holdTimer();
MAP_Interrupt_enableSleepOnIsrExit();
// resPos = 0;

/* Setting up clocks
* MCLK = MCLK = 3MHz
* ACLK = REFO/4 = 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 (5.5 A0) */
MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN5,
GPIO_TERTIARY_MODULE_FUNCTION);

/* Configuring ADC Memory */
MAP_ADC14_configureSingleSampleMode(ADC_MEM0, true);
MAP_ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_AVCC_VREFNEG_VSS,
ADC_INPUT_A0, false);

/* Configuring Timer_A in continuous mode and sourced from ACLK */
MAP_Timer_A_configureContinuousMode(TIMER_A0_MODULE, &continuousModeConfig);

/* Configuring Timer_A0 in CCR1 to trigger at 16000 (0.5s) */
MAP_Timer_A_initCompare(TIMER_A0_MODULE, &compareConfig);

/* Configuring the sample trigger to be sourced from Timer_A0 and setting it
* to automatic iteration after it is triggered*/
MAP_ADC14_setSampleHoldTrigger(ADC_TRIGGER_SOURCE1, false);

/* Enabling the interrupt when a conversion on channel 1 is complete and
* enabling conversions */
MAP_ADC14_enableInterrupt(ADC_INT0);
MAP_ADC14_enableConversion();

/* Enabling Interrupts */
MAP_Interrupt_enableInterrupt(INT_ADC14);
//MAP_Interrupt_enableMaster();

/* Starting the Timer */
MAP_Timer_A_startCounter(TIMER_A0_MODULE, TIMER_A_CONTINUOUS_MODE);

/* Selecting P1.2 and P1.3 in UART mode */
MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,
GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);

/* Setting DCO to 12MHz */
CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_12);

/* Configuring UART Module */
MAP_UART_initModule(EUSCI_A0_MODULE, &uartConfig);

/* Enable UART module */
MAP_UART_enableModule(EUSCI_A0_MODULE);

MAP_Interrupt_enableMaster();

/* Going to sleep */
while (1)
{
MAP_PCM_gotoLPM0();
//printf(EUSCI_A0_MODULE, "%u\r\n", resultsBuffer[resPos]); //MAP_ADC14_getResult(ADC_MEM0));
}
}

/* This interrupt is fired whenever a conversion is completed and placed in
* ADC_MEM0 */
void adc_isr(void)
{
uint64_t status;
MAP_Timer_A_clearTimer(TIMER_A0_MODULE);

status = MAP_ADC14_getEnabledInterruptStatus();
MAP_ADC14_clearInterruptFlag(status);

if (status &ADC_INT0)
{
//resultsBuffer[resPos++] = MAP_ADC14_getResult(ADC_MEM0);
printf(EUSCI_A0_MODULE, "%u\r\n", MAP_ADC14_getResult(ADC_MEM0));
}

}

References to try out next:

[ ADCPrintResults_4C123.zip | ~valvano serial ]

[ msp432 ValvanoWare ]

[ prachetverma github ]

[ msp430 ADC -> UART | nischal | reuben ]

Advertisements

4 thoughts on “Sending MSP432’s ADC samples over “backchannel” UART

  1. I’m eager to try this code out. But with both Chrome and Firefox the code examples above are malformed, with HTML escape sequences and truncated lines. For example in the main.c notice the #include lines near the beginning, and notice the truncation of line 57. This code doesn’t begin to compile. Before I spend a lot of time divining what the missing text should be could you perhaps correct this?
    Thanks.

    Like

    • Hello Pete. Sorry about that, not sure why but I have run into formatting issues whenever I copy paste in code.
      Also, this was only for personal reference: I don’t think this code actually changed the sampling frequency.
      If you intend to work with Code Composer Studio, you might want to just start with the DriverLib examples. However, if you just need some quick data, here’s a set of Energia sketches I used to transmit single channel ADC captures at ~333 Hz: https://github.com/3x10e8/analog_multiTask

      Like

  2. Thanks for the quick response. You’re right, the DriverLib examples are the way to go. I came across your writeup as part of the backchannel printf stuff and thought I’d build it as quick way of seeing Sam Lewis’ code build in a use case. But it wasn’t quite the two minute exercise I expected. 🙂

    Thanks for sharing your work!
    -Pete

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s