AnsweredAssumed Answered

STM32F405 ADC DMA reading problem

Question asked by Dworakowski.Karol on Oct 16, 2016
Latest reply on Oct 31, 2016 by Amel N
Hi

I'm using STM32F405RGT6 configured in CubeMX. I'm reading ADC inside TIM6 interrupt which is executed every 40us. As you can see in switch statement I read all 7 channels and next, one or two channels (I wrote a little functions to update SQR registers so that I don't need to call HAL config structure). If I read like this and check DR via Keil debugger I get strage values, that are really unstable. However if I move the code to main loop and disable TIM6 and read they are fine. I tried to change NVIC priorities, TIM6 has 3, ADC interrupt has 2 and ADC DMA int has 1 but it didnt helped.

Another question: I would like to send data in TIM6 interrupt after ADC readings. Atm I'm using HAL_USART_Transmit_DMA() to send data every 1ms. The problem is I'm not getting all data. I checked how much time this functions need to execute and it takes 3us, so it's not breaking the interrupt in any way.


TIM6 interrupt:

volatile uint8_t count;
  
void TIM6_DAC_IRQHandler(void)
{
  /* USER CODE BEGIN TIM6_DAC_IRQn 0 */
    //static int COUNTER_MAX = MOTOR_DRIVER_T/0.00002;
    //HAL_GPIO_WritePin(GPIOB, CS_A_Pin, GPIO_PIN_RESET);
        switch(count){
        case 0:
            ADCreadAmbient(); // read ambient light
            HAL_GPIO_WritePin(GPIOC, D_LF_Pin, GPIO_PIN_SET);
            break;
        case 1: // case 3: // 40us
            ADCreadChannel(CH2, &sensor[0].buf[2]); // LF read
            HAL_GPIO_WritePin(GPIOC, D_LF_Pin, GPIO_PIN_RESET);
            break;
        case 2: //120us case 6: // 100us
            HAL_GPIO_WritePin(GPIOC, D_RF_Pin, GPIO_PIN_SET);
            break;
        case 4: //160us case 8: // 140us
            ADCreadChannel(CH11, &sensor[1].buf[2]); // RF read
            HAL_GPIO_WritePin(GPIOC, D_RF_Pin, GPIO_PIN_RESET);
            break;
        case 6: // 240us case 11: // 200us
            HAL_GPIO_WritePin(GPIOA, D_L_Pin, GPIO_PIN_SET);
            HAL_GPIO_WritePin(GPIOC, D_R_Pin, GPIO_PIN_SET);
            break;
        case 7: // 280us case 13: // 240us
            ADCread2Channel(CH13, CH12, &read[0]); // L, R read
            HAL_GPIO_WritePin(GPIOA, D_L_Pin, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(GPIOC, D_R_Pin, GPIO_PIN_RESET);
            break;
        case 9: // 360us case 16: // 300us
            HAL_GPIO_WritePin(GPIOC, D_LS_Pin, GPIO_PIN_SET);
            HAL_GPIO_WritePin(GPIOC, D_RS_Pin, GPIO_PIN_SET);
            break;
        case 10: // case 18: // 340us
            ADCread2Channel(CH3, CH10, &read[2]); // LS, RS read
            HAL_GPIO_WritePin(GPIOC, D_LS_Pin, GPIO_PIN_RESET); // side sensors off
            HAL_GPIO_WritePin(GPIOC, D_RS_Pin, GPIO_PIN_RESET);
            break;
        case 12:
            GyroGetAngle(0.001);
            break;
          
        case 13:
            MotorUpdate();
            break;
    }
              
          
        ++count;
          
        if(count >= 25){ // execute every 1ms
            //HAL_GPIO_WritePin(GPIOB, CS_A_Pin, 1);
            count = 0;
        }
  
          
  /* USER CODE END TIM6_DAC_IRQn 0 */
  HAL_TIM_IRQHandler(&htim6);
  /* USER CODE BEGIN TIM6_DAC_IRQn 1 */
      
  /* USER CODE END TIM6_DAC_IRQn 1 */
}

ADC functions:

void ADCreadAmbient(){
    ADC1->SQR1 = (ADC_SQR1_L_2|ADC_SQR1_L_1); // 7 conversions (0x06, count from 0)
    // channels order is important!
    ADC1->SQR3 = (CH2)|(CH11<<5)|(CH13<<10)|(CH12<<15)|(CH3<<20)|(CH10<<25); // channels to convert: 2, 11, 12, 13 and 9 for battery
    ADC1->SQR2 = CH9;
    //CH3, CH10
    HAL_ADC_Start_DMA(&hadc1, cal, 7);
    //vbat = cal[6]; // *0.0025 + 0,067;
    if(cal[6] < 2884 && cal[6] > 2650){ // 7,4-6,8
        batError = 1;
        UI_LedOnAll();
    }
}
  
void ADCreadChannel(uint8_t CHx, uint32_t *buf){
    ADC1->SQR1 &= ~ADC_SQR1_L; // 1 conversion
    ADC1->SQR3 = CHx; // channel to be converted
    HAL_ADC_Start_DMA(&hadc1, buf, 1);
}
  
void ADCread2Channel(uint8_t CHx1, uint8_t CHx2, uint32_t *buf){
    ADC1->SQR1 = ADC_SQR1_L_0;
    ADC1->SQR3 = (CHx1)|(CHx2<<5);
    HAL_ADC_Start_DMA(&hadc1, buf, 2);
}

ADC config:

void MX_ADC1_Init(void)
{
  ADC_ChannelConfTypeDef sConfig;
  
    /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
    */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.ScanConvMode = ENABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 7;
  hadc1.Init.DMAContinuousRequests = ENABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }
  
    /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
    */
  sConfig.Channel = ADC_CHANNEL_2;
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_84CYCLES;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  
    /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
    */
  sConfig.Channel = ADC_CHANNEL_11;
  sConfig.Rank = 2;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  
    /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
    */
  sConfig.Channel = ADC_CHANNEL_13;
  sConfig.Rank = 3;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  
    /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
    */
  sConfig.Channel = ADC_CHANNEL_12;
  sConfig.Rank = 4;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  
    /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
    */
  sConfig.Channel = ADC_CHANNEL_3;
  sConfig.Rank = 5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  
    /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
    */
  sConfig.Channel = ADC_CHANNEL_10;
  sConfig.Rank = 6;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  
    /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
    */
  sConfig.Channel = ADC_CHANNEL_9;
  sConfig.Rank = 7;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  
}



Outcomes