Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
lock attach
Attachments are accessible only for community members.
Not applicable
Guys,

I need to use a CPU to read 6 analog signals (12 bits) and send by SPI to a FPGA.
The only function of this CPU is this, receive an external trigger, read the ADC and send by SPI.
I have the XMC4500 with relax kit.

I did the program attached, but my best time between press the trigger and finish the 6 data sending is 20us.

Can I do something different to reduce this time?
There is any other way to make it faster?
I need to do this as fast as possible with this CPU.

I programed ADC for start by external trigger, and programed ADSYNC with 6 channels.
ADSYNC_A generate an interrupt when it´s finished.
I put the result in a int16 variable and send it by SPI.


I measure the times with a scope, and check that:
1,8us - Press the button, do the ADC and enter at the interrupt.

1,8us - each line ADCSYNC001_GetResult(&ADCSYNC001_Handle0, &ADCSYNC001_MSYNCA_SB_Handle0, &envia1);
I measure this in a test only doing this line, and toggle a pin before and after this comand.

17,6us - Total time between press the button and finish the Send 6 data, 12 bit each with 20MHz SPI.
18,2us - Total time between press the button and finish the Send 6 data, 12 bit each with 10MHz SPI.

The operation that is taking much time is the aquisition from the GetResult.

Best Regards,



0 Likes
12 Replies
Not applicable
I look at the code, and change the program.
I note that every time that it entry at ADCSYNC001_GetResult, it´s execute several functions.

I try to use only this line: teste_data2 = (uint16_t)VADCGroupPtr[1]->RES[3];
And it´s working well.
There is any problem to use this or I need to use ADCSYNC001_GetResult?
I get only 7,7us between press the button and finish the data sent with only this line.


void ChannelAResultEvt(void)
{
VADC_G_TypeDef *VADCGroupPtr[4];

VADCGroupPtr[0] = (VADC_G_TypeDef*)(void*)VADC_G0;
VADCGroupPtr[1] = (VADC_G_TypeDef*)(void*)VADC_G1;
VADCGroupPtr[2] = (VADC_G_TypeDef*)(void*)VADC_G2;

IO004_TogglePin(IO004_Handle1);
/* Result of the Master Channel A*/

teste_data1 = (uint16_t)VADCGroupPtr[0]->RES[15];
// ADCSYNC001_GetResult(&ADCSYNC001_Handle0, &ADCSYNC001_MSYNCA_Handle0, &testeDMA1);
SPI001_WriteData(&SPI001_Handle0,&teste_data1,SPI001_STANDARD);

teste_data2 = (uint16_t)VADCGroupPtr[1]->RES[3];
// ADCSYNC001_GetResult(&ADCSYNC001_Handle0, &ADCSYNC001_MSYNCA_SA_Handle0, &testeDMA2);
SPI001_WriteData(&SPI001_Handle0,&teste_data2,SPI001_STANDARD);

teste_data3 = (uint16_t)VADCGroupPtr[2]->RES[0];
// ADCSYNC001_GetResult(&ADCSYNC001_Handle0, &ADCSYNC001_MSYNCA_SB_Handle0, &testeDMA3);
SPI001_WriteData(&SPI001_Handle0,&teste_data3,SPI001_STANDARD);

teste_data4 = (uint16_t)VADCGroupPtr[0]->RES[4];
// ADCSYNC001_GetResult(&ADCSYNC001_Handle0, &ADCSYNC001_MSYNCB_Handle0, &testeDMA4);
SPI001_WriteData(&SPI001_Handle0,&teste_data4,SPI001_STANDARD);

testeDMA5 = (uint16_t)VADCGroupPtr[1]->RES[15];
// ADCSYNC001_GetResult(&ADCSYNC001_Handle0, &ADCSYNC001_MSYNCB_SA_Handle0, &teste_data5);
SPI001_WriteData(&SPI001_Handle0,&teste_data5,SPI001_STANDARD);

teste_data6 = (uint16_t)VADCGroupPtr[2]->RES[1];
// ADCSYNC001_GetResult(&ADCSYNC001_Handle0, &ADCSYNC001_MSYNCB_SB_Handle0, &testeDMA6);
SPI001_WriteData(&SPI001_Handle0,&teste_data6,SPI001_STANDARD);

IO004_TogglePin(IO004_Handle1);


}
0 Likes
Not applicable
This code, did not work.
I generate the interrupt only for chanel A...

I need to change, and generate both interrupts, channel A and channel B separeted.

If anyone has some tip to make it faster, I accept it.


void ChannelAResultEvt(void)
{
VADC_G_TypeDef *VADCGroupPtr[3];

VADCGroupPtr[0] = (VADC_G_TypeDef*)(void*)VADC_G0;
VADCGroupPtr[1] = (VADC_G_TypeDef*)(void*)VADC_G1;
VADCGroupPtr[2] = (VADC_G_TypeDef*)(void*)VADC_G2;

IO004_TogglePin(IO004_Handle1);

//Canal 0
// teste_data1 = (uint16_t)VADCGroupPtr[0]->RES[15];
ADCSYNC001_GetResult(&ADCSYNC001_Handle0, &ADCSYNC001_MSYNCA_Handle0, &teste_data1);
SPI001_WriteData(&SPI001_Handle0,&teste_data1,SPI001_STANDARD);

//Canal 1
// teste_data2 = (uint16_t)VADCGroupPtr[1]->RES[3];
ADCSYNC001_GetResult(&ADCSYNC001_Handle0, &ADCSYNC001_MSYNCA_SA_Handle0, &teste_data2);
SPI001_WriteData(&SPI001_Handle0,&teste_data2,SPI001_STANDARD);

//Canal 2
// teste_data3 = (uint16_t)VADCGroupPtr[2]->RES[0];
ADCSYNC001_GetResult(&ADCSYNC001_Handle0, &ADCSYNC001_MSYNCA_SB_Handle0, &teste_data3);
SPI001_WriteData(&SPI001_Handle0,&teste_data3,SPI001_STANDARD);
/*
//Canal 3
// teste_data4 = (uint16_t)VADCGroupPtr[0]->RES[4];
ADCSYNC001_GetResult(&ADCSYNC001_Handle0, &ADCSYNC001_MSYNCB_Handle0, &teste_data4);
SPI001_WriteData(&SPI001_Handle0,&teste_data4,SPI001_STANDARD);

//Canal 4
// teste_data5 = (uint16_t)VADCGroupPtr[1]->RES[15];
ADCSYNC001_GetResult(&ADCSYNC001_Handle0, &ADCSYNC001_MSYNCB_SA_Handle0, &teste_data5);
SPI001_WriteData(&SPI001_Handle0,&teste_data5,SPI001_STANDARD);

//Canal 5
// teste_data6 = (uint16_t)VADCGroupPtr[2]->RES[1];
ADCSYNC001_GetResult(&ADCSYNC001_Handle0, &ADCSYNC001_MSYNCB_SB_Handle0, &teste_data6);
SPI001_WriteData(&SPI001_Handle0,&teste_data6,SPI001_STANDARD);
*/
IO004_TogglePin(IO004_Handle1);


}

void ChannelBResultEvt(void)
{
VADC_G_TypeDef *VADCGroupPtr[3];

VADCGroupPtr[0] = (VADC_G_TypeDef*)(void*)VADC_G0;
VADCGroupPtr[1] = (VADC_G_TypeDef*)(void*)VADC_G1;
VADCGroupPtr[2] = (VADC_G_TypeDef*)(void*)VADC_G2;

IO004_TogglePin(IO004_Handle1);

/* //Canal 0
// teste_data1 = (uint16_t)VADCGroupPtr[0]->RES[15];
ADCSYNC001_GetResult(&ADCSYNC001_Handle0, &ADCSYNC001_MSYNCA_Handle0, &teste_data1);
SPI001_WriteData(&SPI001_Handle0,&teste_data1,SPI001_STANDARD);

//Canal 1
// teste_data2 = (uint16_t)VADCGroupPtr[1]->RES[3];
ADCSYNC001_GetResult(&ADCSYNC001_Handle0, &ADCSYNC001_MSYNCA_SA_Handle0, &teste_data2);
SPI001_WriteData(&SPI001_Handle0,&teste_data2,SPI001_STANDARD);

//Canal 2
// teste_data3 = (uint16_t)VADCGroupPtr[2]->RES[0];
ADCSYNC001_GetResult(&ADCSYNC001_Handle0, &ADCSYNC001_MSYNCA_SB_Handle0, &teste_data3);
SPI001_WriteData(&SPI001_Handle0,&teste_data3,SPI001_STANDARD);
*/
//Canal 3
// teste_data4 = (uint16_t)VADCGroupPtr[0]->RES[4];
ADCSYNC001_GetResult(&ADCSYNC001_Handle0, &ADCSYNC001_MSYNCB_Handle0, &teste_data4);
SPI001_WriteData(&SPI001_Handle0,&teste_data4,SPI001_STANDARD);

//Canal 4
// teste_data5 = (uint16_t)VADCGroupPtr[1]->RES[15];
ADCSYNC001_GetResult(&ADCSYNC001_Handle0, &ADCSYNC001_MSYNCB_SA_Handle0, &teste_data5);
SPI001_WriteData(&SPI001_Handle0,&teste_data5,SPI001_STANDARD);

//Canal 5
// teste_data6 = (uint16_t)VADCGroupPtr[2]->RES[1];
ADCSYNC001_GetResult(&ADCSYNC001_Handle0, &ADCSYNC001_MSYNCB_SB_Handle0, &teste_data6);
SPI001_WriteData(&SPI001_Handle0,&teste_data6,SPI001_STANDARD);

IO004_TogglePin(IO004_Handle1);


}
0 Likes
Not applicable
I came back to here, to tell that my program not work when I try to converte some AD.

I needed to change it again, I configure ADSYNC to generate 6 interrupts, onde for each AD channel.
After all this interrupts, I sen the 6 data to the SPI.

I´m doing this in 19us, it´s more than I want, but this is the only way that all conversions are good.
0 Likes
Travis
Employee
Employee
First solution authored Welcome! 500 replies posted
Hi Smarley,

Let me look into this issue.

Best Regards
Travis
0 Likes
Travis
Employee
Employee
First solution authored Welcome! 500 replies posted
Hi,

I can reduce the ADC reading of the x6 channels to about 760ns excluding SPI transmission

can you replace

" ADCSYNC001_GetResult(&ADCSYNC001_Handle0, &ADCSYNC001_MSYNCA_Handle0, &envia1);"

with this

uint16_t envia[6];

void ChannelAResultEvt(void)
{

envia[0] = VADC_G0->RES[15];
envia[1] = VADC_G1->RES[3];
envia[2] = VADC_G2->RES[0];
envia[3] = VADC_G0->RES[4];
envia[4] = VADC_G1->RES[15];
envia[5] = VADC_G2->RES[1];


/* Start SPI transmit with for loop on envia */


}
0 Likes
Travis
Employee
Employee
First solution authored Welcome! 500 replies posted
You can also replace

SPI001_WriteData(&SPI001_Handle0,&envia1,SPI001_STANDARD);

with

void ASC_vSendData (uint32_t uwData)
{
UART001_Handle0.UartRegs->PSCR |= USIC_CH_PSCR_CTBIF_Msk;

UART001_Handle0.UartRegs->TBUF[0] = uwData;

while(!(UART001_Handle0.UartRegs->PSR_ASCMode & USIC_CH_PSR_TBIF_Msk ));

}
0 Likes
Not applicable
Thanks Travis, I will try that!

I put and Result Event Interrupt only for Msync A of ADCSync001.
Can I guarantee that all channels did those acquisitions or I need to do interrupt individually for each 6 channels to get the results?
0 Likes
lock attach
Attachments are accessible only for community members.
Not applicable
Dear Travis,

I try your suggestion but I had the same result that I had at the past.
The results are not OK.
if I use ADCSYNC001_GetResult, I receive 1530 for example, for all six channels (I put the same signal at all 6 channels).

If I use your suggestion, I receive:

envia[0] = 287
envia[1] = 302
envia[2] = 0
envia[3] = 0
envia[4] = 548
envia[5] = 1192

I disable all the interrupts of ADCSYNC001, and put only the A channel, like you suggest.

Do you have any idea why this happens?

And, If I trigger again the ADC conversion, the values do not change.
It remains static.



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

Then I put these lines:

envia[0] = VADC_G0->RES[15];
envia[1] = VADC_G1->RES[3];
envia[2] = VADC_G2->RES[0];
envia[3] = VADC_G0->RES[4];
envia[4] = VADC_G1->RES[15];
envia[5] = VADC_G2->RES[1];

At main(), after the interrupts.
At the first time that I press the button, I receive the right values os 4 and 5.
The second time I receive the 1 and 2.
But I never receive 3 and 4, and I never receive all at the same time.
Always 4/5 or 1/2.

Maybe I need to wait some time before ask the values?

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

When I put: while((IO004_ReadPin(IO004_Handle0)==0)) {}
before get the results, I get results from 1,2,3,5 and 6.
Only 4 did not came.
0 Likes
Not applicable
Travis,

I solve the problem, using 6 different interrupts, for each channels.
Now I don´t have an scope to check the times, I will check on February.
Thanks for your tip.

I will try to implement the directly SPI now.

#include //Declarations from DAVE3 Code Generation (includes SFR declaration)

uint16_t teste_data1, teste_data2, teste_data3, teste_data4, teste_data5, teste_data6;

uint16_t envia[6];

int main(void)
{
// status_t status; // Declaration of return variable for DAVE3 APIs (toggle comment if required)


DAVE_Init(); // Initialization of DAVE Apps


ADC002_InitializeQueue(&ADC002_Handle0);


while(1)
{

if(IO004_ReadPin(IO004_Handle0)==0)
{
ADC002_TriggerEvent((ADC002_HandleType*)&ADC002_Handle0);
/* while((IO004_ReadPin(IO004_Handle0)==0)) {}

envia[0] = (uint16_t)VADC_G0->RES[15];
envia[1] = (uint16_t)VADC_G1->RES[3];
envia[2] = (uint16_t)VADC_G2->RES[0];
envia[3] = (uint16_t)VADC_G0->RES[4];
envia[4] = (uint16_t)VADC_G1->RES[15];
envia[5] = (uint16_t)VADC_G2->RES[1];
*/

ADCSYNC001_ClearResultEvtFlag(&ADCSYNC001_Handle0, &ADCSYNC001_MSYNCA_Handle0);
// ADCSYNC001_ClearResultEvtFlag(&ADCSYNC001_Handle0, &ADCSYNC001_MSYNCB_Handle0);
ADC002_ClearSourceEventFlag((ADC002_HandleType*)&ADC002_Handle0);
IO004_TogglePin(IO004_Handle1);
while((IO004_ReadPin(IO004_Handle0)==0)) {}
}

}
return 0;
}



void ChannelAResultEvt(void)
{

IO004_TogglePin(IO004_Handle1);

/* envia[0] = (uint16_t)VADC_G0->RES[15];
envia[1] = (uint16_t)VADC_G1->RES[3];
envia[2] = (uint16_t)VADC_G2->RES[0];
envia[3] = (uint16_t)VADC_G0->RES[4];
envia[4] = (uint16_t)VADC_G1->RES[15];
envia[5] = (uint16_t)VADC_G2->RES[1];
*/
envia[0] = (uint16_t)VADC_G0->RES[15];
// ADCSYNC001_GetResult(&ADCSYNC001_Handle0, &ADCSYNC001_MSYNCA_Handle0, &teste_data1);
// SPI001_WriteData(&SPI001_Handle0,&teste_data1,SPI001_STANDARD);

}


void ChannelASA_ResultEvt(void)
{

envia[2] = (uint16_t)VADC_G2->RES[0];
// ADCSYNC001_GetResult(&ADCSYNC001_Handle0, &ADCSYNC001_MSYNCA_SA_Handle0, &teste_data2);
// SPI001_WriteData(&SPI001_Handle0,&teste_data2,SPI001_STANDARD);

}
void ChannelASB_ResultEvt(void)
{

envia[1] = (uint16_t)VADC_G1->RES[3];
// ADCSYNC001_GetResult(&ADCSYNC001_Handle0, &ADCSYNC001_MSYNCA_SB_Handle0, &teste_data3);
// SPI001_WriteData(&SPI001_Handle0,&teste_data3,SPI001_STANDARD);
// ADC002_TriggerEvent((ADC002_HandleType*)&ADC002_Handle0);

}

void ChannelBResultEvt(void)
{

envia[3] = (uint16_t)VADC_G0->RES[4];
// ADCSYNC001_GetResult(&ADCSYNC001_Handle0, &ADCSYNC001_MSYNCB_Handle0, &teste_data4);
// SPI001_WriteData(&SPI001_Handle0,&teste_data4,SPI001_STANDARD);

}

void ChannelBSA_ResultEvt(void)
{

envia[5] = (uint16_t)VADC_G2->RES[1];
// ADCSYNC001_GetResult(&ADCSYNC001_Handle0, &ADCSYNC001_MSYNCB_SA_Handle0, &teste_data5);
// SPI001_WriteData(&SPI001_Handle0,&teste_data5,SPI001_STANDARD);

}

void ChannelBSB_ResultEvt(void)
{

envia[4] = (uint16_t)VADC_G1->RES[15];
// ADCSYNC001_GetResult(&ADCSYNC001_Handle0, &ADCSYNC001_MSYNCB_SB_Handle0, &teste_data6);
// SPI001_WriteData(&SPI001_Handle0,&teste_data6,SPI001_STANDARD);

IO004_TogglePin(IO004_Handle1);

}
0 Likes
Not applicable
Can I measure time with DAVE?
For this case that I don´t have an scope with me.
0 Likes
Travis
Employee
Employee
First solution authored Welcome! 500 replies posted
smarley wrote:
Thanks Travis, I will try that!

I put and Result Event Interrupt only for Msync A of ADCSync001.
Can I guarantee that all channels did those acquisitions or I need to do interrupt individually for each 6 channels to get the results?


The AD conversion shall be done to all channel when the selected channel is being triggered for conversion. Which means there is no need to trigger each and every channel for AD conversion unless there is a special requirement needed to control every AD channels.
0 Likes
lock attach
Attachments are accessible only for community members.
Travis
Employee
Employee
First solution authored Welcome! 500 replies posted
smarley wrote:
Can I measure time with DAVE?
For this case that I don´t have an scope with me.


Nope.

Can you give this example a try, which uses only one interrupt to get all the results for AD channels?
0 Likes