cancel
Showing results for 
Search instead for 
Did you mean: 

Using ADC1 for very fast readings of IN1 and readings of other channels every 100ms

MFend
Associate III

Hello,

I have 7 ADC1 channels that must be read every 100ms. I can't use polling because there are many other tasks being done in the foreground. I can either set up in the interrupt a type of chain in which each time one value is read the next one will be processed - or - use DMA.

The challenge is the follows:

IN1 must be sampled at least 50-100 times​ in the space of 50us (microseconds) every second after a certain timer trigger (and synchronized not to happen when the other ADC readings are being read/processed). For this I probably need the DMA and an accumulator.

​I'm trying to figure out how these ADC readings and channels can exist together.

​Until now I've used the STM-Cube to configure the ADC and read all channels every 25ms.

Any ideas would be appreciated.

Thanks,

Mechi​

7 REPLIES 7
TDK
Guru

What chip?

I would set ADC1 to do the 100ms readings and let ADC2 do the high speed readings. They could do their own thing independently.

You could also configure ADC1 to do both, but it would require some logic on your part. You would need to reconfigure ADC1 between the different types of readings, but there's no reason you can't do that. In either case, DMA seems to be the smartest way to go.

If you feel a post has answered your question, please click "Accept as Solution".
MFend
Associate III

We don't have ADC2.

All are wired on ADC1 - and the HW can't be changed.

I'm opening a case about this - because it seems to need more detailed explanation.

Thanks,

Mechi

> We don't have ADC2.

> All are wired on ADC1 - and the HW can't be changed.

To be blunt - it looks like this design is messed up.

You should have paid a little more attention to details before.

Forcing a 50us sampling rate on all channels is simple in software and does not require much performance if DMA is used.

But the design of the signal conditioning circuitry is much less relaxed as a result.

> ...and synchronized not to happen when the other ADC readings are being read/processed

I can see no convincing reason for this requirement.

Which STM32?

If I understand correctly, you have bursts of rapid readings of one channel, and then - guaranteed non-overlapping in time - slow readings of other channels. What is exactly the issue here? Simply reprogram the ADC and TIM (if used to trigger ADC) and DMA, whenever a new requirement/trigger appears.

JW

MFend
Associate III

STM32L451

That's exactly the issue - how to reprogram the ADC from 7 channels to just 1 channel.

And how to ensure that the 1 channel is read rapidly in 50us from the time it's started. After this rapid reading, I must then reprogram to the 7 channels which will be read using the main loop every 100ms.

The 1 channel rapid reading must be synchronized with the PWM - which is set as follows:

  HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);      //Start the PWM ch3
  htim3.Instance->CCR3 = htim3.Init.Period * 0.1;	     //Set Duty Cycle 10% of trigger pulse

Each time there's a pulse on htim3, the ADC config must be changed to capture the first 50us after the pulse.

At the moment all of the drivers and peripherals are configured using the ioc file - STM_Cube. For this dual configuration, I'll have to add "USER_CODE".

Any help or ideas would be appreciated.

Thanks,

Mechi

MFend
Associate III

There's an IRQ handler for TIM3 - so is where I should configure the ADC1 to do the rapid reading (every 5us) of the specific ADC1 channel.

Once started, after TBD samples, the ADC1 will be reconfigured in the main loop.

There is only a limited set of features out of the virtually unlimited possibilities of hardware, which can be used by clicking in CubeMX.

I assume that you can configure CubeMX into one of the required configurations, generate code and copy it , then configure it into the other configuration, again copy the resulting code; and use those two pieces of code alternatively as needed, maybe interspersed by DeinitADC() or something similar. I don't use Cube.

JW