Перейти к содержанию

    

STM32F030F4 АЦП и HAL

Продолжаю попытки понять. STM32F030F4, Куб, Атоллик. Простой опрос каналов АЦП.

	  	  while(1)
	  	  	  {
	  	      	  adc_res_0 = 0;
	  	      	  sConfig.Channel = ADC_CHANNEL_0;
	  	      	  sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
	  	      	  sConfig.SamplingTime = ADC_SAMPLETIME_13CYCLES_5;
	  	      	  HAL_ADC_ConfigChannel(&hadc, &sConfig);					//выбрали канал IN0
	  	      	  for (count = 0; count < 8; count++)						//усредняем по 8-ми измерениям
	  	      	  	  {
	  	      		  	  HAL_ADC_Start(&hadc);								//запуск преобразования
	  	      	  		  HAL_ADC_PollForConversion(&hadc,100);				//ожидаем окончания преобразования
	  	      	  		  adc_res_0 = adc_res_0 + HAL_ADC_GetValue(&hadc);	//накапливаем результат
	  	      	  		  HAL_ADC_Stop(&hadc);								//стоп преобразования
	  	      	  	  }

	  	      	  adc_res_0 = adc_res_0 >> 4;								//усреднили

	  	      	  //HAL_ADC_DeInit(&hadc);
	  	      	  //HAL_ADC_Init(&hadc);

	  	      	  adc_res_7 = 0;
	  	      	  sConfig.Channel = ADC_CHANNEL_7;
	  	      	  sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
	  	      	  sConfig.SamplingTime = ADC_SAMPLETIME_13CYCLES_5;
	  	      	  HAL_ADC_ConfigChannel(&hadc, &sConfig);					//выбрали канал IN7
	  	      	  //ADC1 -> CHSELR = 128;
	  	      	  for (count = 0; count < 8; count++)						//усредняем по 8-ми измерениям
	  	      	  	  {
	  	      		  	  HAL_ADC_Start(&hadc);								//запуск преобразования
	  	      			  HAL_ADC_PollForConversion(&hadc,100);				//ожидаем окончания преобразования
	  	      			  adc_res_7 = adc_res_7 + HAL_ADC_GetValue(&hadc);	//накапливаем результат
	  	      			  HAL_ADC_Stop(&hadc);								//стоп преобразования
	  	      	  	  }

	  	      	  adc_res_7 = adc_res_7 >> 4;								//усреднили

	  	      	  g_var_0 = adc_res_0;
	  	      	  g_var_7 = adc_res_7;

	  	  	  }

Результат - канал 7 показывает тоже самое, что и канал 0. С точностью до двух бит, чуть-чуть разные значения.

Если включить: 

HAL_ADC_DeInit(&hadc);
HAL_ADC_Init(&hadc);

то все работает как надо. Вполне адекватные значения по каналам.

Вот сижу и думаю, что делаю неправильно? В pdf-нике на HAL ничего не нашел, что нужно деинить перед сменой каналов. Хотелось бы понять.

И по ходу второй вопрос: на пальцах объясните, что такое Rank в канале?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не верный подход!

Первое: HAL_ADC_ConfigChannel не должен вызываться в цикле, вызывается единожды для каждого канала!

Второе:

	  	      	  //HAL_ADC_DeInit(&hadc);
	  	      	  //HAL_ADC_Init(&hadc);

Если заглянуть в код HAL, там будет видно что повторная реинициализация возможно только после деинициализации, это же где-то описано в доках на HAL. Кроме того, если ваша hadc не была изначально проинициализирована нулями лучше вызать DeInit он сбросит основные поля хэндла.

 

On 11/9/2018 at 5:25 PM, Vlad_G said:

что такое Rank в канале?

верно! Проблема в понимании Rank.
Rank - это номер данного канала ADC в очереди во время запуска семплирования.


Организация работы должна иметь следующий вид:

... 
AdcHandle.Init.NbrOfConversion = 2;
HAL_ADC_Init(&AdcHandle);

...
sConfig.Rank = 1;
sConfig.Channel = ADC_CHANNEL0;
HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);

...
sConfig.Rank = 2;
sConfig.Channel = ADC_CHANNEL7;
HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);

for(;;) {

  HAL_ADC_Start(&AdcHandle);

  HAL_ADC_PollForConversion(&AdcHandle, 1000);
  ch0 = HAL_ADC_GetValue(&AdcHandle);

  HAL_ADC_PollForConversion(&AdcHandle, 1000);
  ch7 = HAL_ADC_GetValue(&AdcHandle);

  HAL_ADC_Stop(&AdcHandle); 
}

Вообще, эти все примеры, можно найти в папке HAL lib которые качает Cube.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо, Integro!

По Вашему раскладу заработало, даже объем кода уменьшился на 3%. Единственно, что - параметр AdcHandle.Init.NbrOfConversion = 2; найти не смог ни в каком виде и комбинациях. Возможно к данному МК не относится. Но если выбрать в кубе Продолжительный режим, то работает. Вообще, насколько я понял, то в 030F4 нельзя задать произвольную последовательность опроса каналов. Можно в регистре ADC_CHSELR выбрать нужные каналы и МК будет производить последовательный опрос выбранных каналов с верху вниз (или наоборот) по порядку.

Спрошу по ДМА. Верно ли, что нельзя задать каждому каналу АЦП свой буфер в памяти, что бы туда сваливались данные только с этого канала? Те, буфер один и запись в буфер будет чередоваться.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
27 минут назад, Vlad_G сказал:

Можно в регистре ADC_CHSELR выбрать нужные каналы и МК будет производить последовательный опрос выбранных каналов с верху вниз (или наоборот) по порядку.

Да, именно так. Произвольный порядок опроса можно задавать в более старших STM32.

27 минут назад, Vlad_G сказал:

Спрошу по ДМА. Верно ли, что нельзя задать каждому каналу АЦП свой буфер в памяти, что бы туда сваливались данные только с этого канала? Те, буфер один и запись в буфер будет чередоваться.

Если вы хотите оцифровывать несколько каналов в регулярном режиме - то нельзя. Но вы можете описать структуру с данными всех каналов, создать массив из таких структур и в программе перемещаться по этому массиву:

    typedef uint16_t sample;

    struct group
    {
        sample  U_ref;
        sample  U_in;
        sample  U_temp;
        sample  U_temp_ref;
        sample  U_bat;
    };

    group           Result[BUFFER_SIZE*2];

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
Авторизация