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.
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.
Solved! Go to Solution.
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
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.
Hope it helps
Have a great day,
Alice
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
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.
- In the following picture, DMAChannel_LDD configuration is shown.
- And finally the code adapted from the typical usage.
Could you please tell me what am I making wrong? I am sure I am missing something. :smileysad:
Thank you.
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.
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
Hi Alice,
I will try the different options and I will keep you informed.
Thank you.
Aitor.
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.
- In the picture below, the configuration of the component Init_DMA.
- Find below the code generated. Everytime a button is pressed, the ADC conversion should be repeated.
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.
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
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.
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.
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.
Thank you again.
Aitor.
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 :
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.
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.
I tried this option and unfortunately the conversion time increases to 7.3us. It is a shame. Please find below my code:
Any help?
Thank you in advance.
Aitor.
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.
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.
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
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!
-----------------------------------------------------------------------------------------------------------------------
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.
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
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.