Skip to main content
keaven
Associate III
August 5, 2015
Question

STM32F4 ADC Injected and DMA.

  • August 5, 2015
  • 5 replies
  • 3565 views
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

    This topic has been closed for replies.

    5 replies

    Tesla DeLorean
    Guru
    August 5, 2015
    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 (See Profile) Up vote any posts that you find helpful, it shows what's working..
    keaven
    keavenAuthor
    Associate III
    August 6, 2015
    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

    Tesla DeLorean
    Guru
    August 6, 2015
    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 (See Profile) Up vote any posts that you find helpful, it shows what's working..
    jpeacock
    Associate
    August 6, 2015
    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
    keavenAuthor
    Associate III
    August 18, 2015
    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;
    }