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.

Streaming 8 channels of ADC 8KHz from MSP432 to computer through UART



Hello everyone, this is my first post here !

I am a newbie to CCS and CMSIS. I am student and I bought MSP432 launchpad for my research project to control a LED driver and also to record 8 analog channels and stream them to a computer. Where I got stuck is the streaming part via UART... I tried to dig through the MSPWare examples and inspire me from them but all I tried at the current time failed to function properly.

I explain more in details. For each of the 8 channels (A0-7) I want a loop to be :

- send on TXBUF the int 79 two times (it serves for verification of the received data on the link and as a scaling flag on the computer software interface as I want the UART out from the MSP432 to be an asynchronous stream)

- then send the channel number on TXBUF

- finally send the two bytes of ADC14MEM corresponding to the channel

I configured a DCO -> SMCLK @ 48 MHz to serve as source for the eUSCIa , and divided by UCABRS=100 to get a 480 Kbps baudrate .

Here is the CCS code :

#include "msp.h"
#include <stdint.h>

static uint8_t ch;

int main(void)
{
  WDT_A->CTL = WDT_A_CTL_PW+WDT_A_CTL_HOLD;                   // Stop watchdog timer

  CS->KEY = 0x695A; // unlock CS registers
  CS->CTL0 = 0; // reset DCO settings
  CS->CTL0 = CS_CTL0_DCORSEL_5; // select DCO 5 (48MHz)
  CS->CTL1 = CS_CTL1_SELS__DCOCLK | CS_CTL1_SELM__DCOCLK; // ACLK = REFOCLK, SMCLK = MCLK = DCOCLK
  CS->KEY = 0; // lock CS registers

  // Configure GPIO
  P5->SEL1 |= BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0;       // Enable A/D channel A0-A5
  P5->SEL0 |= BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0;
  P4->SEL1 |= BIT7 | BIT6;     				    // Enable A/D channel A6-A7
  P4->SEL0 |= BIT7 | BIT6;

   // ADC14 Configuration
  ADC14->CTL0 = ADC14_CTL0_PDIV__32 | ADC14_CTL0_DIV_2 | ADC14_CTL0_ON | ADC14_CTL0_MSC | ADC14_CTL0_SHT0_0 | ADC14_CTL0_SHP | ADC14_CTL0_CONSEQ_3; // Turn on ADC14 750KHz, extend sampling time
  ADC14->CTL1 =  ADC14_CTL1_RES_3;                                                                            // to avoid overflow of results

  ADC14->MCTL[0] = ADC14_MCTLN_INCH_0;                 // ref+=AVcc, channel = A0
  ADC14->MCTL[1] = ADC14_MCTLN_INCH_1;                 // ref+=AVcc, channel = A1
  ADC14->MCTL[2] = ADC14_MCTLN_INCH_2;                 // ref+=AVcc, channel = A2
  ADC14->MCTL[3] = ADC14_MCTLN_INCH_3;       		   // ref+=AVcc, channel = A3.
  ADC14->MCTL[4] = ADC14_MCTLN_INCH_4;                 // ref+=AVcc, channel = A4
  ADC14->MCTL[5] = ADC14_MCTLN_INCH_5;                 // ref+=AVcc, channel = A5
  ADC14->MCTL[6] = ADC14_MCTLN_INCH_6;                 // ref+=AVcc, channel = A6
  ADC14->MCTL[7] = ADC14_MCTLN_INCH_7+ADC14_MCTLN_EOS; // +ADC14_MCTLN_VRSEL_14 ref+=AVcc, channel = A7, end seq.

  SCB->SCR &= ~SCB_SCR_SLEEPONEXIT_Msk;             // Wake up on exit from ISR

  // Configure UART pins
  P1->SEL0 |= BIT2 | BIT3;                    		// set 2-UART pin as second function

      // Configure UART
  EUSCI_A0->CTLW0 |= EUSCI_A_CTLW0_SWRST;				// Put eUSCI in reset
  EUSCI_A0->CTLW0 |= EUSCI_A_CTLW0_SSEL__SMCLK;         // Select SMCLK as eUSCIa clock source
      // Baud Rate calculation
  UCA0BR0 = 100;                              // 48000000/100 = 480000 bps
  UCA0BR1 = 0;
  EUSCI_A0->MCTLW = 0;
  EUSCI_A0->CTLW0 &= ~EUSCI_A_CTLW0_SWRST;                    // Initialize eUSCI
  EUSCI_A0->IE |= EUSCI_A_IE_RXIE;                         // Enable USCI_A0 RX interrupt

  SCB->SCR &= ~SCB_SCR_SLEEPONEXIT_Msk;   // Wake up on exit from ISR

  ADC14->CTL0 |= ADC14_CTL0_ENC | ADC14_CTL0_SC;        // Start conversion-software trigger

  while(1)
  {
    for(ch=0;ch<8;ch++)
    {
    	while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));
    	EUSCI_A0->TXBUF = 79;								// Send marker-1 = 79 for stream scaling on computer side
    	while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));
    	EUSCI_A0->TXBUF = 79;								// Send marker-2 = 79 for stream scaling on computer side
    	while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));
     	EUSCI_A0->TXBUF = ch+1;								// Send channel number
     	while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));
        EUSCI_A0->TXBUF = ADC14->MEM[ch]>>8;				                // Send MSByte from ADC14MEMch
        while(!(EUSCI_A0->IFG & EUSCI_A_IFG_TXIFG));
        EUSCI_A0->TXBUF = ADC14->MEM[ch];					        // Send LSByte from ADC14MEMch
    }
  }

}

// UART interrupt service routine
void EUSCIA0_IRQHandler(void)
{
    if (EUSCI_A0->IFG & EUSCI_A_IFG_RXIFG)
    {
        EUSCI_A0->IFG &=~ EUSCI_A_IFG_RXIFG;            // Clear interrupt
    }

}

On the other side I'm using python pySerial interface on Windows 8 and a time measure code for a serial read of 1 byte gives me very non-stable results (min value = 69us which is equivalent to 14Kbps and not 480 Kbps as expected from the baudrate). Python code :

while True :
        start= time.clock()
        self.ser.read(1)
        print time.clock()-start

Thus I can't record the ADC values at 480/8 Kbps (or any fixed sampling rate) .... Does it come from my CCS code or could it be a problem coming from python pySerial module ?

Thank you in advance !

  • Hi Mehdi, in the penultimate post of the link there is a code for transferring ADC samples from one channel trough UART to mi PC, the difference is that I use MATLAB (i believe that is similar to phyton), As you can see in the MATLAB graph I was able to recognize a 4000 Hz signal (With no so good resolution but fulfilling the Nyquist theorem) . For multiple ADC channels you just need to change the ADC buffer to get one sample from each ADC_MEM_x. 

    Good luck!!!

    e2e.ti.com/.../523880

  • Thank you very much for your reply Josue ! I will try it. Can you by any chance also share the matlab code with me ?

    - Which baudrate did you use with your configuration ? (48M / 26 ~= 1846154 bps ?)

    - Could you achieve a fixed sampling rate with such a configuration ? I am really focused on that problem as my python program will record signals from another source at the same time and I need a time scaling for the two sources

    Thanks in advance

  • Hi Mehdi, to calculate the baud rate you must use two things, the value of the clock source (in my case 48 MHz) and the Baud rate you want to achieve, to understand better what steps you must take to determinate the values of UCA0BR0 and UCA0BR1, read the MSP432 Technical Reference Manual, page 740, or you can also go to this link (software-dl.ti.com/.../index.html), select eUSCII for msp432.

    I have not tried to achieve a fixed sampling rate, that might be dificult because of you must know how much time does the ADC and UART interuption takes.The MATLAB code I got it from the MATLAB examples source (www.mathworks.com/.../serial-port-devices.html), is very simple (on MATLAB :D, I haven't tried yet on python or C).
    I hope this help you Mehdi.

**Attention** This is a public forum