ADC K60 setup SC1A and SC1B to return result in one interrupt

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

ADC K60 setup SC1A and SC1B to return result in one interrupt

Jump to solution
2,571 Views
aroste
Contributor IV

Hi all,

I read many things but still don't know what I can do or not.

In hardware there are to channels that can be set in K60 processor with configuration register ADCx_SC1A and B.

How do I have to setup everything to start a conversion of those 2 channels and get one interruption when both are finished?

I use tower TWR-K60F120M and configured the PE to generate the code. Depending the configuration the interface allow, or not, the use of 2 channels. (Discontinuous mode)

I check the all the ADC registers details in the reference manual, my conclusions at this point are :

- Both ADC channels have to be started separately.

- SC1A can start by software or hardware trigger.

- SC1B only hardware trigger.

Thanks

stephan

Labels (1)
1 Solution
1,326 Views
paulmartin
Contributor III

Hi,

I also tried to use the A and B parts of one ADC module, but I never got it to work the way I wanted it to. Especially since I needed more than two results anyway.

I think the triggering can be done with the PDB. As far as I understand it you would  tell the PDB to cycle, lets say every 1ms, and then trigger register set A at 0ms and register set B at 0.5ms. At least that is why it is called programmable delay block (synchronizing multiple ADC/DAC/PWM signals with delays). But again I never got it to work right.

For reference I attached my ADC code, because I will be gone for a week and cannot answer. You will see everything is there twice (ADC0 and ADC1). You will probably have to adapt all register names since we use KEIL uVision IDE. The basic steps are

1. initializing the ADCs

2. Calibration

3. Setup all DMA channels (the chain is channel 2->1->5->4, only channel 2 is triggered by ADC0 conversion complete)

     -2 read result ADC0

     -1 write next ADC0 channel

     -5 read result ADC1

     -4 write next ADC1 channel

     (You can have as many ADC channels looped as you want.The DMA just needs to cycle through them. It could even be different numbers for ADC0 and ADC1)

4. only after setting everything up, activate DMA request

5. setup PDB trigger

I hope this helps.

View solution in original post

0 Kudos
14 Replies
1,326 Views
aroste
Contributor IV

Ah ok, I will follow that if I want to use the PDD method instead.

About the ADC init I meant the full setup, so I put the SWTRIG bit set at the end of everything as you mentioned.

Thanks for your support.

Best regards

0 Kudos
1,326 Views
aroste
Contributor IV

Hi again,

I finally got it working.

I checked the specs according to your solutions and your last command, I added directly that after the ADC init:

PDB0_SC |= PDB_SC_SWTRIG_MASK;

Thanks for your support.

BR

-stéphan-

P.S: It was not working directly, I had to manipulate the PE for ADC and PDB and recompile it to get it working. I assume one configuration was not compiled properly at my first try.

0 Kudos
1,326 Views
jch
NXP Employee
NXP Employee

Hi Stephan,

yes that is the correct approach, but it is more safe to start the PDB trigger after the all settings of the ADC (methods Init, SelectSampleGroup, StartLoopTriggerMeasurement) are done.

See my comment above for including the PDB_PDD.h.

Thanks

Jiri

0 Kudos
1,326 Views
aroste
Contributor IV

Hi,

So, I tried to reproduce your solution. For the configuration in PE the only difference with what I tried previously is the PDB trigger channel, I used the CH0 instead of the CH1.  Others I think I did correct.

PDB is configured with prescaler 128. divider 10, modulus 46875 (1000ms = 1s), Continuous, interrupt delay 65535 (1398ms) as I don't need I think, Load immediate.

My ADC is set for 2 channels so far, 12bits, 4 clocks periods, 16 conversions, 51.2us conversion time.  Configuration was working fine with my solution.

Now I changed the trigger for PDB as you mentioned, updated the interrupt routine by just read back the result with the method provided.

For the init of ADC and PDB I do so:

EventStruct.ADC1_UserDatas.DeviceDatas = AD1_Init(&EventStruct);

if (AD1_SelectSampleGroup(EventStruct.ADC1_UserDatas.DeviceDatas, 0) != ERR_OK)

        printf("Failed AD1_CreateSampleGroup\n");

//; /* Prepare ADC to be ready for measure on trigger */
if (AD1_StartLoopTriggeredMeasurement(EventStruct.ADC1_UserDatas.DeviceDatas) != ERR_OK)

        printf("Failed AD1_StartLoopTriggeredMeasurement in hwtimer_task\n");

PDB1_Init();

In your code example at the end of that you use the following routine that I cannot find or add, either the include of "PDB_PDD.h":

  PDB_PDD_SoftwareTrigger(PDB0_DEVICE); /* Create SW trigger to start PDB which is selected as trigger source for ADC */

Result is that it doesn't work, it doesn't go into the interrupt and if I stop the execution I can see in the ADC registers RA/B that no measurement have been performed.

Can you help me with that ?

BR

-stéphan-

0 Kudos
1,326 Views
jch
NXP Employee
NXP Employee

Hi Stephan,

for using the PDB_PDD.h it is necessary to have set correctly the path in the Compiler -> directories: "${ProcessorExpertPath}/lib/Kinetis/pdd/inc"Path settings.png

In the step:   PDB_PDD_SoftwareTrigger(PDB0_DEVICE); /* Create SW trigger to start PDB which is selected as trigger source for ADC */ is written to the bit PDBx_SC[SWTRIG] = 1 which starts the PDB, cause SW trigger is selected as trigger source for PDB in the previous preject. This write is necessary to start project working. You can also choose another trigger for PDB, if you need.

I tryied the project on HW and it works well.

Thanks

Jiri

1,326 Views
aroste
Contributor IV

Hi,

I see this answer only now. (thanks to the new email notification rules)

I downloaded the solution, I will have a look as soon as I can.    I'm stuck now to find how to use "arcsin" functionality for an inclinometer sensor, I cannot find any info about that yet.

I will keep you informed.

Thanks

BR

-stéphan-

1,326 Views
aroste
Contributor IV

Thanks, I will keep your file for my next implementation.

I finally succeeded to start a conversion on channel B.  I setup HW TRG on channel B by PIT_LDVAL0 (TimerUnit_LDD).  I tried with PIT, FlexTimer, nothing was working.

So I do now:

1- Init Trig HW conversion channel B.

2- Read result channel B and start a SW conversion on channel A

3- read result channel A and set HW conversion channel B

...

Thanks

BR

stephan

0 Kudos
1,326 Views
Monica
Senior Contributor III

Hello Stephan,

was this workaround effective? Don't forget to keep us posted :smileywink:

Best,

Monica.

0 Kudos
1,326 Views
jch
NXP Employee
NXP Employee

Hi Stephan,

I create the project with Processor Expert, which fulfil your first stage project. It measures the 2 channels with trigger A and B produced by PDB and after those are measured in the interrupt are changed the channels to other pair and then measured also by trigger A and B. And those two groups are continuously changed in interrupt and periodically triggered by the PDB.


In the project are used components: ADC_LDD with selected: 4 channels - please change them to those you want. Two groups are created from them to first group (channel 0 and 1), second group (channel 2 and 3). To be able to create group of two channels it is necessarily selected the Discontinuous mode. Then the trigger source is specified as PDB channel 1 trigger A for first channels in the groups (0,2) and PDB channel 1 trigger B for second channels in the groups (1,3). For info: PDB channel 1 is connected to the ADC1.

In the Init_PDB component (group Referenced_Components) is Enabled channel 1 part A and B with specified delays from start of the PDB period and period itself - please change the period and delays to wanted values, the back to back operation is also possible to set (after measument of the SC1A automatically the SC1B part get trigger). Triggers are periodically fired to the ADC with PDB period in this settings.

Interrupt is called after each group finish measurement. In event OnMeasurementComplete (called from interrupt) the measured data are stored to the Result[4] array, canceled previous measurement and then switch between groups and start new triggered measurement.

The project is saved with the breakpoint inside the OnMeasurementComplete event, for check the actual measured values. Project is created for the P&E multilink and GCC compiler.

Please try the project  and let me know if it helps.

Thanks

Jiri

0 Kudos
1,326 Views
aroste
Contributor IV

hi,

Thanks for your reply.

For the moment I basically just want to measure both channels of ADC1 (A & B) and return the result after the conversion.

No limitations at this point.

Then I will certainly need to use DMA as you suggest for more channels, at the end I will need 4 channels on ADC1.

But I go step by step to understand the setup and features of this K60, it's why I first want to start a conversion on A & B en return result.

Thanks

BR

stephan

0 Kudos
1,326 Views
ndavies
Contributor V

The ADC1a and ADC1b are not separate ADCs. They are 2 sets of control registers for 1 ADC.

The A and B registers are designed to be used in a ping - pong fashion. You load up the A registers and tell the ADC to go, It will begin the conversion on channel 1. As the A registers are converting, you load up the B registers. When the A register completes, you now need to trigger the B register on ADC1. You can now read the A registers while the B registers are converting. After reading the A register, You then set up the A registers for the next conversion. This allows you to configure the next conversion for a channel while a conversion is already in process on that channel.

This helps in getting higher conversion throughput. The ADC isn't idle while you're filling in all those registers.

0 Kudos
1,326 Views
aroste
Contributor IV

Hi,

Ok, it is what I almost understood. But my point now is how to setup each channel to do, or start, the conversion ?

Because channel B seems to support only hardware trigger.

By setting channel A in SW TRG and then write in SC1A register it starts the conversion, OK.

But writing in channel B doesn't work.  I setup the Flextimer 1 to trig channel B, but it doesn't work.

0 Kudos
1,327 Views
paulmartin
Contributor III

Hi,

I also tried to use the A and B parts of one ADC module, but I never got it to work the way I wanted it to. Especially since I needed more than two results anyway.

I think the triggering can be done with the PDB. As far as I understand it you would  tell the PDB to cycle, lets say every 1ms, and then trigger register set A at 0ms and register set B at 0.5ms. At least that is why it is called programmable delay block (synchronizing multiple ADC/DAC/PWM signals with delays). But again I never got it to work right.

For reference I attached my ADC code, because I will be gone for a week and cannot answer. You will see everything is there twice (ADC0 and ADC1). You will probably have to adapt all register names since we use KEIL uVision IDE. The basic steps are

1. initializing the ADCs

2. Calibration

3. Setup all DMA channels (the chain is channel 2->1->5->4, only channel 2 is triggered by ADC0 conversion complete)

     -2 read result ADC0

     -1 write next ADC0 channel

     -5 read result ADC1

     -4 write next ADC1 channel

     (You can have as many ADC channels looped as you want.The DMA just needs to cycle through them. It could even be different numbers for ADC0 and ADC1)

4. only after setting everything up, activate DMA request

5. setup PDB trigger

I hope this helps.

0 Kudos
1,326 Views
paulmartin
Contributor III

Just to cover all options:

Is  2 measurements/channels all you need? Because you could use the two ADCs of the K60 simultaneous for that.

And why do you want to measure discontinuously? Is it power consumption?

If you actually need more, for example 2 channels on ADC0 and something completely different on ADC1, then I would suggest a DMA chain.

At least that worked for me.

What i do is measure 4 channels with each ADC continuously. That is 8 measurements each millisecond. I use the DMA to write the ADC_SC1 register and then when the conversion is finished the DMA reads the result into a specified RAM location.

Both ADCs are triggered by the PDB module every 240ms. This way I never have to worry about the ADCs after initialization. I only read the latest result from RAM.

But it really depends on your application whether this approach fits.

So what exactly do you need to do? (number of channels, timing, etc. )

Martin

0 Kudos