cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 ADC Injected and DMA.

keaven
Associate II
Posted on August 05, 2015 at 23:54

I would like to benefit of the alternate trigger of the injected conversion.  I am using the DMA on my interleaved regular conversion.

I would like to know if it is possible to use the DMA controller for injected conversion also.  I tried without success and cannot find information of it in the reference manual.

Anyone knows?

Thank you

5 REPLIES 5
Posted on August 06, 2015 at 01:26

I don't think so. It doesn't have any specific DMA channel committed to such, and having it in the primary stream would just tend to cause all kinds of chaos in the data array. The point of injecting is to get some out-of-band conversions done.

If you pair ADC1+ADC2, you could use ADC3 independently.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
keaven
Associate II
Posted on August 06, 2015 at 18:38

Ok, so you said that I can do a regular dual interleaved ADC1+ADC2 and use the ADC3 in regular mode?  I tried but like in another post the status register was always busy

Posted on August 06, 2015 at 22:13

On paper it looks viable, I've done independent DMA on 3 ADC channels. I can't make a business case to prototype the solution here, and definitely not with the HAL.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
jpeacock
Associate II
Posted on August 06, 2015 at 22:43

I've used ADC1+ADC2 paired in DMA mode and ADC3 injected in interrupt mode, works fine. Since injected conversions are out of band you can't use DMA as it would trash your conversion buffers. All you have to do is set up ADC3 JEOC interrupt and read the injected conversion when the interrupt occurs.

Inside the ADC interrupt handler:

// power supply injected conversion, open AWD windows for all ADCs after debounce 
if(ADC_GetITStatus(ADC3, ADC_IT_JEOC) != RESET) 
{ // ADC3 injected conversion ready 
ADC_ClearITPendingBit(ADC3, ADC_IT_JEOC); // clear JEOC interrupt 
ADC_ClearFlag(ADC3, ADC_FLAG_JSTRT | ADC_FLAG_JEOC); 
adcInjects[ADC_IOB_MISC]++; // count ADC injections 
adcSample[ADCDEV_CHAN_POWER] = 
ADC_GetInjectedConversionValue(ADC3, ADC_InjectedChannel_1); // 24V power supply

Not sure what you mean by busy flag. All I test are interrupt status flags in interrupt handler. Jack Peacock
keaven
Associate II
Posted on August 18, 2015 at 23:05

I think I have found the problem. I am using the HAL STM32F4 Library. If you look at the function to start an injected conversion with interrupt you must use the ADC1 for the injection (last if block of the function).

So basically, I need to write another function to get start I guess.

HAL_StatusTypeDef HAL_ADCEx_InjectedStart_IT(ADC_HandleTypeDef* hadc)
{
__IO uint32_t counter = 0;
uint32_t tmp1 = 0, tmp2 =0;
/* Process locked */
__HAL_LOCK(hadc);
/* Check if a regular conversion is ongoing */
if(hadc->State == HAL_ADC_STATE_BUSY_REG)
{
/* Change ADC state */
hadc->State = HAL_ADC_STATE_BUSY_INJ_REG; 
}
else
{
/* Change ADC state */
hadc->State = HAL_ADC_STATE_BUSY_INJ;
}
/* Set ADC error code to none */
hadc->ErrorCode = HAL_ADC_ERROR_NONE;
/* Check if ADC peripheral is disabled in order to enable it and wait during 
Tstab time the ADC's stabilization */
if((hadc->Instance->CR2 & ADC_CR2_ADON) != ADC_CR2_ADON)
{ 
/* Enable the Peripheral */
__HAL_ADC_ENABLE(hadc);
/* Delay for temperature sensor stabilization time */
/* Compute number of CPU cycles to wait for */
counter = (ADC_STAB_DELAY_US * (SystemCoreClock / 1000000));
while(counter != 0)
{
counter--;
}
}
/* Enable the ADC end of conversion interrupt for injected group */
__HAL_ADC_ENABLE_IT(hadc, ADC_IT_JEOC);
/* Enable the ADC overrun interrupt */
__HAL_ADC_ENABLE_IT(hadc, ADC_IT_OVR);
/* Check if Multimode enabled */
if(HAL_IS_BIT_CLR(ADC->CCR, ADC_CCR_MULTI))
{
tmp1 = HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_JEXTEN);
tmp2 = HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO);
if(tmp1 && tmp2)
{
/* Enable the selected ADC software conversion for injected group */
hadc->Instance->CR2 |= ADC_CR2_JSWSTART;
}
}
else
{
tmp1 = HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_JEXTEN);
tmp2 = HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO);
if((hadc->Instance == ADC1) && tmp1 && tmp2) 
{
/* Enable the selected ADC software conversion for injected group */
hadc->Instance->CR2 |= ADC_CR2_JSWSTART;
}
}
/* Process unlocked */
__HAL_UNLOCK(hadc);
/* Return function status */
return HAL_OK;
}