Analogue Data Acquisition on the LaunchPad with Matlab

This example shows how to set up the ADC on the MSP430G2553 to capture a set of samples at the full rate (approximately 200kS/s) and then send these over the UART to matlab for further processing and display. There are two parts to this example the c code that runs on the MSP40G2553 and the Matlab function.

MSP430G2553 Source


/* Example showing how to set up the UART to receive single character commands and transmit bytes from an array in the
microprocessor memory. The UART receive interrupt is used to signal the reception of a character and if that character
matches the command ("D") then, firstly, a string is sent "Sending data" followed by the linefeed and carriage return terminator
characters,then the ADC is enabled and it captures 255 samples at the full ADC sample rate (Approx 200kS/s) from channel 5 (P1.5).
When the ADC interrupt signals that the data capture is complete the data is then transferred over the UARTone byte at a time.
If an incorrect command is received then "Unknown Command" is sent. In order to test this code the Timer TA0 is configured as a
10kHz pulse source.

Note: this code assumes you are using a microprocessor that has a hardware UART such as the MSP430G2553.
When using the hardware UART and the Launchpad MSP-EXP430G2 (Rev.1.5) it is necessary to rotate the jumpers on (J3) for HW UART

Benn Thomsen 2014 */

#include "msp430G2553.h"

#define SAMPLES 255

void ConfigureTimerAPWM(void);
void ConfigureADCBlock(void);
void ConfigureUART(void);
void UARTSendArray(unsigned char *TxString, unsigned int ArrayLength);
void UARTSendIntArray(unsigned int *TxArray, unsigned int ArrayLength);
void UARTSendTerminator(void);

// Define array of integers.
volatile unsigned int data[SAMPLES];

void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT

/* Use Factory stored presets to calibrate the internal oscillator */
BCSCTL1 = CALBC1_16MHZ; // Set DCO to 16MHz
DCOCTL = CALDCO_16MHZ;

P1DIR |= BIT0; // Set the LED on P1.0 outputs
P1OUT &= ~BIT0; // Turn on LED1 to indicate start of conversion

ConfigureUART();
ConfigureTimerAPWM();
ConfigureADCBlock();
__enable_interrupt(); // Enable interrupts.
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0, interrupts enabled
}

// Echo back RXed character, confirm TX buffer is ready first
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
if (UCA0RXBUF == 'D'){
UARTSendArray("Sending data\n\r", 14);
P1OUT |= BIT0; // Turn on LED1 to indicate start of conversion
ADC10SA = data; // Specify start location of data buffer
ADC10CTL0 |= ENC + ADC10SC; // ADC Sampling and conversion start
}
}

// ADC10 interrupt service routine
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR (void)
{
ADC10CTL0 &= ~ENC;
UARTSendArray(data,2*SAMPLES);
P1OUT &= ~BIT0; // Turn off LED1 to indicate transmission complete
}

void ConfigureTimerAPWM(void){
/* Define output pin functionality */
P1DIR |= BIT6; // Set P1.6 to output
P1SEL |= BIT6; // Select output P1.6 to be TA0.1
P1SEL2 &= ~BIT6; // Select output P1.6 to be TA0.1

/* Configure timer A as a pulse width modulator */
TA0CCR0 = 1600-1; // Set maximum count value to determine PWM Frequency = SMCLK/TACCR0 (16MHz/1600 = 10kHz)
TA0CCR1 = 800; // Initialise counter compare value 1 to control Duty Cycle = TACCR1/TACCR0 (400/1600 = 25%)
TA0CCTL1 = OUTMOD_7; // Set output to on when counter resets and off when counter equals TACCR1. Normal PWM.
TA0CTL = TASSEL_2 + MC_1; // Use the SMCLK to clock the counter and set to count up mode
}

void ConfigureADCBlock(void){
/* Configure ADC to capture a block of samples automatically on Channel 5 */
ADC10CTL1 = INCH_5 + SHS_0 + ADC10DIV_3 + ADC10SSEL_3 +CONSEQ_2 ; // Select input channel 5. Sample and hold source (0: ADCSCbit). ADC10CLK Divider (0: /1). ADC Clock source (0: internal 5MHz oscillator). Repeat single channel
ADC10CTL0 = SREF_0 + ADC10SHT_0 + MSC + ADC10ON + ADC10IE; // Reference Voltage (0: Vcc & Vss). Sample and hold time (0: 4 ADC clk cycles). Enable continous sampling. Turn ADC on. Enable ADC interrupt
ADC10AE0 |= BIT5; // Enable P1.5 as ADC input
ADC10DTC1 = SAMPLES;
}

void ConfigureUART(void){
// Configure the hardware UART to operate at 9600baud. Note to use the hardware UART on the Launchpad
// it is necessary to rotate jumpers for HW UART operation
P1SEL = BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD
P1SEL2 = BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD
UCA0CTL1 |= UCSSEL_2; // SMCLK
UCA0BR0 = 130; // 16MHz Clock 9600 Baud, see Data sheet 15.3.13
UCA0BR1 = 6; // 16MHz 9600
UCA0MCTL = UCBRS_6; // Modulation UCBRSx = 6
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
IE2 |= UCA0RXIE; // Enable USCI_A0 RX interrupt
}
void UARTSendArray(unsigned char *TxArray, unsigned int ArrayLength){
// Send number of bytes Specified in ArrayLength in the array at using the hardware UART 0
// Example usage: UARTSendArray("Hello", 5);
// int data[2]={1023, 235};
// UARTSendArray(data, 4); // Note because the UART transmits bytes it is necessary to send two bytes for each integer hence the data length is twice the array length

while(ArrayLength--){ // Loop until StringLength == 0 and post decrement
while(!(IFG2 & UCA0TXIFG)); // Wait for TX buffer to be ready for new data
UCA0TXBUF = *TxArray; //Write the character at the location specified py the pointer
TxArray++; //Increment the TxString pointer to point to the next character
}
}

void UARTSendIntArray(unsigned int *TxArray, unsigned int ArrayLength){
// Send number of bytes Specified in ArrayLength in the array at using the hardware UART 0
// Example usage: UARTSendArray("Hello", 5);
// int data[2]={1023, 235};
// UARTSendArray(data, 4); // Note because the UART transmits bytes it is necessary to send two bytes for each integer hence the data length is twice the array length

while(ArrayLength--){ // Loop until StringLength == 0 and post decrement
while(!(IFG2 & UCA0TXIFG)); // Wait for TX buffer to be ready for new data
UCA0TXBUF = (*TxArray >> 8); //Write the character at the location specified py the pointer
while(!(IFG2 & UCA0TXIFG)); // Wait for TX buffer to be ready for new data
UCA0TXBUF = (*TxArray & 0x00FF); //Write the character at the location specified py the pointer
TxArray++; //Increment the TxString pointer to point to the next character
}
}

Matlab function


function TI_MSP430SerialRx

% This function opens a serial connection to the MSP430 Launchpad attached
% via USB. You need to change the device address to match the address on
% your system. The function sends a 'D' command to initiate the data
% acquisition on the MSP430 and then reads in the data that is sent back.

Nstring = 14;
Nintdata = 248;
obj=serial('/dev/tty.uart-10FF49F37B51335A','BaudRate', 9600,'Terminator', 'LF/CR','InputBufferSize',2*Nintdata+Nstring);
fopen(obj);
finishup = onCleanup(@() fclose(obj));
command = 'D';
fprintf(obj,command);
string = fscanf(obj,'%c',14);
disp(['Response: ' string(1:end-2)])

if strcmp(string(1:end-2),'Sending data'),
data = fread(obj,Nintdata,'uint16');

N=length(data);
disp([num2str(N) ' integers received'])
Fs = 10e3/0.044
time = (0:N-1)./Fs;
figure(1),plot(data,'-o')
xlabel('Time (s)')
ylabel('Amplitude')
end

freq = [0:N/2-1,-N/2:-1].*(Fs/N);
Data = fft(data);
figure(2), plot(freq(1:N/2),20*log10(abs(Data(1:N/2))))
xlabel('Frequency (Hz)')
ylabel('Spectral Magnitude (dB)')

4 thoughts on “Analogue Data Acquisition on the LaunchPad with Matlab

  1. Hello,

    Just wondering which version of Energia you used? As I keep getting type conversion errors.

    sketch_mar20a.ino: In function ‘void USCI0RX_ISR()’:
    sketch_mar20a.ino:53:37: error: invalid conversion from ‘const char*’ to ‘unsigned char*’ [-fpermissive]
    sketch_mar20a.ino:21:6: error: initializing argument 1 of ‘void UARTSendArray(unsigned char*, unsigned int)’ [-fpermissive]
    sketch_mar20a.ino:55:11: error: invalid conversion from ‘volatile unsigned int*’ to ‘unsigned int’ [-fpermissive]
    sketch_mar20a.ino: In function ‘void ADC10_ISR()’:
    sketch_mar20a.ino:65:29: error: cannot convert ‘volatile unsigned int*’ to ‘unsigned char*’ for argument ‘1’ to ‘void UARTSendArray(unsigned char*, unsigned int)’

    Thank you.

    • Version 0101E004.However I suspect your problem is you have pasted my code example directly into an Energia Sketch. To compile c code in Energia you need to open a new tab with a filename ending in .c e.g. MyName.c The Energia Sketch file which ends in .ino should be blank. It functions a little bit like a project file in a fully fledged IDE. See this page for more info

  2. Hello Benn,
    What is the difference between Code composer studio and Energia. Can I still use this code on CCS? I try but it gave this erros:
    ../main.c”, line 40: error #515: a value of type “volatile unsigned int *” cannot be assigned to an entity of type “unsigned int”
    “../main.c”, line 50: error #169: argument of type “volatile unsigned int *” is incompatible with parameter of type “unsigned char *”
    2 errors detected in the compilation of “../main.c”.

    Any idea how to fix them?
    Thank you in advance.

    • The code should work in CCS however you probably need to use the CCS native types which are defined in the stdint.h header file

      #include

      then rather than using unsigned int you would use uint16_t

      or uint8_t for char

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