ADC and DMA help.

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

ADC and DMA help.

Jump to solution
1,359 Views
patricio
Contributor IV

Hello all,

I am woriking with the FRDM-KL25Z board in a project where I need to make about 2000 ADC conversions with a very low conversion time.

Using ADC_LDD component, I am able to configure the component reducing the conversion time up to 1.58us. But then, when I run the project and I measure the real conversion time with the oscilloscope I see that it takes 8us each conversion (I measure the time needed for the 2000 conversions and then I divide it by 2000).

So I am dealing with the DMA in order to reduce the convesion time. I read the KL25 sub-family reference manual as well as other documents, posts and tutorials, and I think at last I understood how DMA works more or less. What I would need is to transfer the data from the ADC Result Register to a memory buffer.

Peripheral to memory transfer.png

Could your please help me with the following questions?

1.- Cycle-steal mode or Constinuos mode?. The datasheet says:

• Cycle-steal mode (DCRn[CS] = 1)—Only one complete transfer from source to destination occurs for each request. If DCRn[ERQ] is set, the request is peripheral initiated. A software-initiated request is enabled by setting DCRn[START].

• Continuous mode (DCRn[CS] = 0)—After a software-initiated or peripheral request, the DMA continuously transfers data until BCRn reaches zero. The DMA performs the specified number of transfers, then retires the channel.

If DMA is configured in Continuos mode, initiated by peripheral request (by ADC0_DMA_Request) and BCR (Byte Counter Register) = 2000, does it means that every data transfer "waits" until each conversion is finished? Or should I work in Cycle-steal mode and repeit it 2000 times?

2.- What of the components of the PE should I use? DMA_LDD, DMAChannel_LDD, DMATransfer_LDD, Init_DMA? All of them?

Every time I add the component DMA_LDD, the following error message is shown: "Peripheral is already in used by the component DMA1".

I remove the component and add it again to the project and I get the same message. Any help?

I am afraid I am a beginner and any help will be appreciated.

Thank you in advance.

Aitor.

0 Kudos
1 Solution
848 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello ,

1.  My project just one test project , and i have not change the destination address , if you want save the ADC result to a place,  you can define the array as you

done.

2, "Byte count" is refer to the number of bytes to be transferred for a given blok , the register : DMA_DSR_BCR -> BCR bit .

3. On you side , whether it only can transferred to the first destination place ?

  I test on my side , when configure the DMA to cycle - steal mode , the destination address won't increase even configure the DINC bit .

So i plus the destination address by hand , please see the attachment , does it can meet your requirement ?

And on my project the ADC only convert once at one time , you can refer to your requirement configure it .

Hope it helps

Alice

View solution in original post

14 Replies
848 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello Aitor,

1.  I think you can use the Cycle-steal mode (DCRn[CS] = 1), for  after  enable the DMA on  ADCx_SC2 register, the ADC DMA request will be asserted when any of the

SC1n[coco] flag is asserted . So when complete one ADC event , it will generate one ADC DMA request .

2. You can add the component of "DMATransfer_LDD" , then you can refer to the typical usage (right click the component , then select "help on component")to configure the component.

pastedImage_0.png

Hope it helps


Have a great day,
Alice

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

848 Views
patricio
Contributor IV

Thank you Alice,

I found the reason of the error "Peripheral is already in used by the component DMA1":

Beeing in component inspector of ADC_LDD, and if DMA is enabled, automatically AD1_DMA0:DMAChannel_LDD and DMA1:DMAController components are added. Then I tried to add again DMAController component, so the mentioned error was shown.

In another hand, in the "help on Component" of the ADC_LDD I found the followin typical usage: Measurement of 200 samples to buffer with DMA. I think it suits what I am looking for, but I am not able to make it work:

-  As I mentioned before, when  DMA is enabled in ADC_LDD component, DMAController and DMAChannel_LDD components are loaded automatically. So I suppose that non other component is needed. I am right?

- Trigger configuration needs to be enabled in order to enable AD1_StartLoopTriggeredMeasurement() method.

ADC_LDD and DMA enabled.png

- In the following picture, DMAChannel_LDD configuration is shown.

DMAChannel_LDD configuration.png

DMAChannel_LDD configuration 1.png

- And finally the code adapted from the typical usage.

ADC_LDD and DMA code.png

Could you please tell me what am I making wrong? I am sure I am missing something. :smileysad:

Thank you.

0 Kudos
848 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello AITOR,

1. "-  As I mentioned before, when  DMA is enabled in ADC_LDD component, DMAController and DMAChannel_LDD components are loaded automatically. So I suppose that non other component is needed. I am right?" --- yes, you are right.

2. pastedImage_0.png

Do you want save the ADC result to memory 0x0 ? If not , please configure it .

And about how to configure the DMA,  i recommend you refer to the sample code  on the component of "DMATransfer_LDD" i mentioned above.

3. And if  it still can not work , please firstly confirm there is the ADC result data , then check the DMA .

And the attachment is a sample code by myself long ago , while it not use the component as yours , i think you the  DMA configure is the same ,you can refer to .

Hope it helps

Alice

848 Views
patricio
Contributor IV

Hi Alice,

I will try the different options and I will keep you informed.

Thank you.

Aitor.

0 Kudos
848 Views
patricio
Contributor IV

Hello Alice,

I keep trying with a project based on the one attached by you, but I am afraid I am not able to make it work. Althoug my intention is to make 2000 conversions, I started making just one.

- I added the same two components: ADC and Init_DMA. In the picture below I show you the configuration of the ADC. I tried to reduce the conversion time as much as possible.

ADC + DMA 1.png

- In the picture below, the configuration of the component Init_DMA.

 

ADC + DMA 2.png

- Find below the code generated. Everytime a button is pressed, the ADC conversion should be repeated.

ADC + DMA code.png

I have the folowing doubt:

In my case, the "destination address" points to an array of 3000 uint16: uiArrayADCvalue[3000]. And as I could see in your project "destination address" points to a variable that is declared as:

     uint16_t Adr1 = 0x8899;

And as the "destination address increment" is disable, I suppose that only one measurement will be made. So in that case, why "Byte count" is configured as 2? Does it means that there will be two measurements?

In spite I made different changings, I am not able no make it work. When the project is debuged, the program always is waiting to the BCR Done flag.

Any help?

Thank you in advance.

849 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello ,

1.  My project just one test project , and i have not change the destination address , if you want save the ADC result to a place,  you can define the array as you

done.

2, "Byte count" is refer to the number of bytes to be transferred for a given blok , the register : DMA_DSR_BCR -> BCR bit .

3. On you side , whether it only can transferred to the first destination place ?

  I test on my side , when configure the DMA to cycle - steal mode , the destination address won't increase even configure the DINC bit .

So i plus the destination address by hand , please see the attachment , does it can meet your requirement ?

And on my project the ADC only convert once at one time , you can refer to your requirement configure it .

Hope it helps

Alice

848 Views
patricio
Contributor IV

Hi Alice,

I am afraid that I found a mistake in my project. In the configuration of the component Init_DMA, channel 0/ Initialization/ External request was disabled. :smileyshocked:

So this way there was no transfer of data by DMA.

Once I made it work, I tried with the 3000 measurements. Thank you very much for your second project attached, it has been very helpful :smileyhappy:. I could test and try different configurations.

I made a project with the ADC and Init_DMA components, but the conversion time was too long. So I changed it to make it work with the ADC_LDD. I manage to lower the conversion time up to 5.6us, but I need to get to the 2 or 3us.

ADC + DMA code 1.png

With the code above, I get 8us per conversion. I changed the method DMA_Init for only some of the lines of it in order to reduce a bit more time.

pastedImage_3.png

With the code above, I get 5.6us per conversion. Is there any way to reduce a bit more the conversion time?

Can I do something with the clock configuration? Please find below my configuration.

CPU 1.png

CPU 2.png

CPU 3.png

Thank you again.

Aitor.

848 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello Aitor,

1.  you can configure the core clock/system clock  to 48Mhz , the bus clock also 48MHZ;

2. you can configure the ADC conversion time here :

pastedImage_0.png

3. And you can try configure the ADC to continuous mode to 3000 times , check whether it can reduce the conversion time .

Best Regards,

Alice

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

If this post answers your question, please click the Correct Answer button.

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

If this post help your question, please click the helpful Answer button.

848 Views
patricio
Contributor IV

Hello Alice,

I keep on trying but I am afraid I have no results. Regarding your recomendations:

1. The KL25 Sub-Family Reference Manual says that the bus clock can run up to 24MHz. Actually, 24MHz is the highest frecuency the bus clock can be configured by the PE.

Is there any way increase this frecuency? Maybe adding and external clock/crystal?

2. I am using it already, I  think I configured it to the lowest conversion time:

     ADC Resolution: 12 bits.

     High speed conversion mode: Enabled.

     Number of convertions: 1

So I get a theoretical conversion time of 1.83us. I can reduce a bit more defining 8 bit resolution, but I would like to maintain the 12 bits.

3. I tried the continuous conversions but I am afraid it takes longer.

The continuous mode is defined by the bit ADCO of the ADCx_SC3 register, and it says that Hardware Average must be enabled (AVGE = 1), which means that in each conversion it will need 4 samples minimum.

CONTINUOUS CONVERSIONS.png

I tried this option and unfortunately the conversion time increases to 7.3us. It is a shame. Please find below my code:

CONTINUOUS CONVERSIONS CODE.png

Any help?

Thank you in advance.

Aitor.

0 Kudos
848 Views
patricio
Contributor IV

Hi again Alice,

I keep reding and working on it, trying to get a solution. I read the KL25 Sub-family Data Sheet document, Rev 5 08_2014, and I found this table on the page 28.

CONTINUOUS CONVERSION TABLE.png

I says that with less than 13 bits resolution can get a conversión rate of 818Ksps in continuous conversion mode and no ADC hardware averaging.

However, in the document KL25 Sub-family reference manual, Rev 3 09_2012, the table that describes the bits of the register ADCx_SC3 (please find it in my previous reply) says that hardware average should be enabled to work in continuous mode.

Is one of the documents wrong? Am I understanding wrong?

The point is that I am only able to make the ADC to work in continuous mode if the bit AVGE = 1 (hardware average enabled). Please find the code in my previous  reply.

Thank you for your help.

Aitor.

0 Kudos
848 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello Aitor,

- Sorry for you have some misunderstand , in ADC continuous conversion , it is not must be set the AVGE = 1,

  that is to say can only enable the continuous conversion without hardware average .

About the describe on RM :

"

Continuous conversions or sets of conversions if the hardware average function is enabled, that is,

AVGE=1, after initiating a conversion.

"

it mean when ADC0 =1 , the ADC can work on two mode : Continuous conversions (AVGE = 0) and sets of conversions (AVGE = 1) .

- Yes , you are right , the max bus clock  of MKL25Z128VLK4 is 24MHZ .

  And another need to pay attention is the ADC CLOCk divide select  pastedImage_0.png

that's all , i think there have no pace can improve the time of conversion.

Hope it helps


Have a great day,

Alice

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

848 Views
patricio
Contributor IV

Hello Alice,

Thank you for your explanation. However I am not able to make the kl25 work in the continuos mode with AVGE = 0. What am I making wrong?

If I set AVGE = 1, I am able to make the 3000 measurements non stop.

In another hand, I noticed that if the "high-speed conversion" is enabled, the converion is slower. How is that possible?

Thank you again.

Aitor.

0 Kudos
848 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello AITOR,

I think we have off the main subject now .

You aim is configure the ADC conversation to high speed , maybe i mislead you , the speed of one ADC conversion is no relate to the mode of ADC .

So you can use one time ADC conversion or continuous .

Now , you use the 24MHZ bus clock , and the ADC CLOCk divide select register choose 00 , then refer to the RM calculate the ADC conversation time ,

does it still can not meet your requirement ?

BR

Alice

0 Kudos
848 Views
patricio
Contributor IV

Hello Alice,

My aim is to get the fastest conversion time as possible, when I do 3000 measurements. There are different ways to

My aim is to get 3000 ADC measurements as fastest as possible. There have been many ways to reduce this time, as using ADC_LDD instead of ADC, using DMA to store the 3000 values, code optimization, etc. I suppose that working in continuous mode will make to get the 3000 measurement faster, although I have not been able to make it to work yet. Regarding high-speed conversion, seen its name, I thought it would be an advantage to make the 3000 measurements faster.

However I am afraid you are right, as I created the subject asking help for DMA and my last questions are not related to the DMA. Maybe I should open a new discussion to get a solution to my last questions.

Thank very much for all your help.  It has been a pleasure.:smileyhappy:

Best regards.

Aitor.

0 Kudos