Davide Di Vita

Multichannel ADC scan conversion out of sync (shifted channels)

Discussion created by Davide Di Vita on Jun 1, 2018
Latest reply on Jun 7, 2018 by Clive Two.Zero

I have an issue with the multichannel scan conversion of the ADC: I want to convert 8 ADC channels triggered by an external signal, store them in the uController and send them via UART to another uC and then a PC.

It all works fine except that every now and then I get a conversion with scrambled channels (actually they are shifted by 1 or more positions). This gets worse if I increase the frequency of the trigger signal, i.e. @100Hz it happens rarely, increasing to 1KHz makes it happens more frequently and at 100KHz the majority of the conversion are with shifted channels.

Data are taken from the ADC with DMA, which triggers an interrupt (HAL_ADC_ConvCpltCallback) after every conversion of the 8 channels, in which data are copied in another variable, then stops the ADC (HAL_ADC_Stop_DMA) and then restarts, ready for the next trigger event.

 

CubeMX settings and initialization are in the attached files.

The problem seems similar to the one in the Dec 2014 thread "ADC/DMA out of sync" by ebommer, but his solution didn't worked.

 

Here's some of the code (just the useful parts):

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
// ADC
#define ADC_BUFF_LEN 8
#define ADC_VALUE_LEN 2008
#define ADC_CHANNELS 8
uint16_t adc_buff[ADC_BUFF_LEN] = {0};
uint16_t adc_value[ADC_VALUE_LEN] = {0};
uint16_t conv_counter = 0;
uint16_t number_of_conversions = (ADC_VALUE_LEN-8)/(ADC_BUFF_LEN+2);
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
     if(hadc->Instance == ADC1)
     {
          HAL_NVIC_DisableIRQ(EXTI15_10_IRQn); // Disabilito l'interrupt dell'ADC
          ++conv_counter;
          if(conv_counter <= number_of_conversions)
          {
               adc_value[4+(conv_counter-1)*(ADC_BUFF_LEN+2)] = conv_counter;
               memcpy(&adc_value[5+(conv_counter-1)*(ADC_BUFF_LEN+2)], adc_buff, sizeof(adc_buff));
               adc_value[13+(conv_counter-1)*(ADC_BUFF_LEN+2)] = conv_counter;
               curr_state = reset;
          }
          else
          {
               HAL_ADC_Stop_DMA(&hadc1);
               mem_full = 1;
               HAL_GPIO_WritePin(GPIOA, BUFF_FULL_Pin, GPIO_PIN_SET);
               curr_state = wait;
          }
     }
}
          /****************************************************************
          ***********************   RESET ADC   ***************************
          ****************************************************************/

          case reset:
               HAL_ADC_Stop_DMA(&hadc1);
               HAL_ADC_Start_DMA(&hadc1, (uint32_t*) adc_buff, ADC_BUFF_LEN);
               HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
               curr_state = wait;
               break;
          /****************************************************************
          ***********************      RX        **************************
          ****************************************************************/

          case rx:     
               // **********      START      **********
               if(rx_command[0] == ...)
               {
                    HAL_ADC_Start_DMA(&hadc1, (uint32_t*) adc_buff, ADC_BUFF_LEN);
                    HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
               }
               // **********      STOP      **********
               else if(rx_command[0] == ...)
               {
                    HAL_NVIC_DisableIRQ(EXTI15_10_IRQn);
                    HAL_ADC_Stop_DMA(&hadc1);
                    HAL_GPIO_WritePin(GPIOA, BUFF_FULL_Pin, GPIO_PIN_RESET);
                    //Clear adc_value and adc_buff
                    memset(adc_value, 0, sizeof(adc_value));
                    memset(adc_buff, 0, sizeof(adc_buff));
                    conv_counter = 0;
                    mem_full = 0;
               }
               // **********      TXDS      **********
               else if(rx_command[0] == ...)
               {
                    adc_value[0] = 'D';
                    adc_value[1] = 'A';
                    adc_value[2] = 'T';
                    adc_value[3] = 'A';
                    adc_value[ADC_VALUE_LEN-4] = 'E';
                    adc_value[ADC_VALUE_LEN-3] = 'N';
                    adc_value[ADC_VALUE_LEN-2] = 'D';
                    adc_value[ADC_VALUE_LEN-1] = '!';

                    HAL_UART_Transmit(&huart4, (uint8_t *)adc_value, sizeof(adc_value), 5000);
                    mem_full = 0;
                    conv_counter = 0;
                    HAL_GPIO_WritePin(GPIOA, BUFF_FULL_Pin, GPIO_PIN_RESET);
                    //Re-enable ADC and DMA
                    HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
                    HAL_ADC_Start_DMA(&hadc1, (uint32_t*) adc_buff, ADC_BUFF_LEN);
               }

 

Thanks

Attachments

Outcomes