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/LAUNCHXL-F28379D: Matlab triggered SCI_UART with EPWM triggered ADC

Part Number: LAUNCHXL-F28379D


Tool/software: Code Composer Studio

Hi,

I am trying make a system using the lauchpad-F28379D where, the ADC is triggered by EPWM (for precise sampling rate), and the samples are then sent to PC (Matlab) via SCI_UART.

The whole operation is triggered by MATLAB, as soon as the MIcrocontroller receives data from matlab over UART.

The ADC is set at 12bit resolution and ACQPS = 19 (=100ns for 200MHz CPU)

ADC sampling Rate = 1 MHz (EPWM CLK = 100 MHz, TBPRD = 99),

So the problem occurs when the TBPRD (EPWM) is set such that the sampling rate exceeds 1 MHz, say 2 MHz (TBRD = 49)

The code somwhow doesn't stop at; while(SciaRegs.SCIFFRX.bit.RXFFST == 0) { } and the value of startup gets set to 1 which should not happen... Please help. Thanks!!

Please refer to the code below.

void main(void)
{
//--- CPU Initialization
InitSysCtrl(); // Initialize the CPU (FILE: SysCtrl.c)
InitGpio(); // Initialize the shared GPIO pins (FILE: Gpio.c)
InitXbar(); // Initialize the input, output & ePWM X-Bar (FILE: Xbar.c)
InitPieCtrl(); // Initialize and enable the PIE (FILE: PieCtrl.c)
InitWatchdog(); // Initialize the Watchdog Timer (FILE: WatchDog.c)

//--- Peripheral Initialization
InitAdca(); // Initialize the ADC-A (FILE: Adc.c)
InitDacb(); // Initialize the DAC-B (File: Dac.c)
InitEPwm(); // Initialize the EPwm (FILE: EPwm.c)
InitScia(); // Initialize the SCI-A (FILE: Sci.c)

//--- Enable global interrupts
asm(" CLRC INTM, DBGM"); // Enable global interrupts and realtime debug

//--- Main Loop
while(1) // endless loop - wait for an interrupt
{
// Wait for inc character (wait for receiving data from Matlab)
while(SciaRegs.SCIFFRX.bit.RXFFST == 0) { } // wait for empty state

Rx_char = SciaRegs.SCIRXBUF.all;

startup = 1;
EPwm2Regs.ETSEL.all = 0x0A00; // Enable SOCA to ADC
EPwm2Regs.TBCTL.bit.CTRMODE = 0; //unfreeze, and enter up count mode

} //end while : Main loop
} //end of main()

ISR:

interrupt void ADCA1_ISR(void) // PIE1.1 @ 0x000D40 ADC-A interrupt #1
{
static Uint16 *AdcBufPtr = AdcBuf; // Pointer to buffer
static Uint16 iQuadratureTable = 0; // Quadrature table index
static volatile Uint16 GPIO34_count = 0; // Counter for pin toggle

int byte[2]; // changing 16-bits to 2 8-bit numbers for SCI_UART transmission
Uint16 i = 0;

if(startup == 1){

PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Must acknowledge the PIE group

//--- Manage the ADC registers
AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // Clear ADCINT1 flag

//--- Read the ADC result
*AdcBufPtr++ = AdcaResultRegs.ADCRESULT0; // Read the result

//--- Brute-force the circular buffer
if( AdcBufPtr == (AdcBuf + ADC_BUF_LEN) )
{
AdcBufPtr = AdcBuf; // Rewind the pointer to beginning
}

//--- Write to DAC-B to create input to ADC-A0
if(SINE_ENABLE == 1)
{
DacOutput = DacOffset + ((QuadratureTable[iQuadratureTable++] ^ 0x8000) >> 5);
}
else
{
DacOutput = DacOffset;
}
if(iQuadratureTable > (SINE_PTS - 1)) // Wrap the index
{
iQuadratureTable = 0;
}
DacbRegs.DACVALS.all = DacOutput;

counter++;
}//startup

if(counter == ADC_BUF_LEN){
EPwm2Regs.ETSEL.all = 0x0000; //disable SOCA
EPwm2Regs.TBCTL.bit.CTRMODE = 3; //freeze counter
startup = 0;

i = 0;
counter = 0;
while(i < ADC_BUF_LEN ){
byte[0] = AdcBuf[i] >> 8; // high byte
byte[1] = AdcBuf[i] & 0x00FF; // low byte
scia_xmit(byte[0]);
scia_xmit(byte[1]);
i++;}

}// end if 


}// end ISR

  • Hi Bhuwan,

    You need to calculate the maximum SCI baud rate that your system can support, and then work backwards, because this will be the limiting factor.

    e.g. if the ADC is sampling at 1MSPS and you send two bytes per sample, then you need at least (8 data bits + start bit + stop bit) x 2 = 20Mbaud, which is really fast!  

    In fact, forgetting about the SCI module and whatever physical interface you are using (FTDI or something like an RS-485 transceiver) - both of which will also be important in determining maximum baud rate - the GPIO on the device are only rated to a maximum speed of 25MHz:

  • Hi Devin,

    If you see my ISR code, the ADC operation is independent of the SCI_UART program, I am storing the ADC samples in a buffer, and once it reaches a certain length, the EPWM (which triggers the ADC is frozen, so ADC conversion stops) and then, the collected data (array) is sent over to the PC via UART.

    I have set my baud rate at 3125000 (LSPCLK = 200/4 = 50MHz, Baudrate = 50MHz/16 = 3125000)

    The thing is that it works perfectly fine for ADC sampling rate = 1 MHz but not beyond that ?

    Thanks for the quick response, please advise.

  • Hi Bhuwan,

    You might want to dig into your code and figure out exactly when the ADC will start sampling.  My guess is that at the ISR takes too long either all the time or through some conditional paths and you end up either:

    • Starving the background loop, which could include not making it through the rest of the initializations
    • Or, overflowing the ADC INT flag such that you can't send more interrupts, and the ISR no longer occurs

    On the second point, you can check the ADCINTOVF flag to see if the ADCINT overflowed (if the ADC finished a sample and tried to set the ADCINT flag but it was still set because the previous ISR hadn't serviced it yet).  You may also want to check out and implement the below erratum (see http://www.ti.com/lit/er/sprz412k/sprz412k.pdf):