Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Решено. Re... stm32f030 ADC VferInt - что не так?
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
AnatolySh
Доброго всем!

STM32F030F4P6. Скомпилил в IAR ARM 7.50 созданный только что скачанным с st STM32CubeMX 4.13.0 и STM32CubeF0 1.5.0 код для оцифровки внутреннего источника опоры. Вместо 1.2 В по даташиту получаю (3.3В (питание) / 4095 (при 12 разрядах разрешения)) * 1947 (см. картинку ниже) = 1.57 В. Что я делаю не так?

Инициализация тактовых частот
CODE

/** System Clock Configuration
*/
void SystemClock_Config(void)
{

RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = 16;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL12;
RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV1;
HAL_RCC_OscConfig(&RCC_OscInitStruct);

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1);

HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}


АЦП
CODE

/**
******************************************************************************
* File Name : ADC.c
* Description : This file provides code for the configuration
* of the ADC instances.
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "adc.h"

volatile uint32_t ADC_result;
volatile uint8_t j;

ADC_HandleTypeDef hadc;

/* ADC init function */
void MX_ADC_Init(void)
{
ADC_ChannelConfTypeDef sConfig;

/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc.Instance = ADC1;
hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc.Init.Resolution = ADC_RESOLUTION12b;
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
hadc.Init.EOCSelection = EOC_SINGLE_CONV;
hadc.Init.LowPowerAutoWait = DISABLE;
hadc.Init.LowPowerAutoPowerOff = DISABLE;
hadc.Init.ContinuousConvMode = DISABLE;
hadc.Init.DiscontinuousConvMode = DISABLE;
hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc.Init.DMAContinuousRequests = DISABLE;
hadc.Init.Overrun = OVR_DATA_PRESERVED;
HAL_ADC_Init(&hadc);

/**Configure for the selected ADC regular channel to be converted.
*/
sConfig.Channel = ADC_CHANNEL_VREFINT;
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5; // ADC_SAMPLETIME_71CYCLES_5;
HAL_ADC_ConfigChannel(&hadc, &sConfig);

HAL_ADCEx_Calibration_Start(&hadc);

uint32_t Timeout = 1000;

for (uint8_t i = 0; i < 6; i++) {
HAL_ADC_Start(&hadc);
while (HAL_ADC_PollForConversion(&hadc, Timeout) != HAL_OK) {;}
ADC_result = HAL_ADC_GetValue(&hadc);
j = i;
}

}




Сам проект
AnatolySh
Цитата(AnatolySh @ Feb 25 2016, 11:56) *
3.3В (питание) / 4095 (при 12 разрядах разрешения)) * 1947 (см. картинку ниже) = 1.57 В. Что я делаю не так?
Разобрался. Питание было всё-таки не 3.3 В, а 2.5 В.
Посему ( 2.5 В / 4095 ) * 1947 = 1.19 В
Поднял до 3.3:
( 3.3 В / 4095 ) * 1531 (см. картинку ниже) = 1.23 В



Прошу простить за беспокойство.
ViKo
А почему делите на 4095, а не на 4096? Так где-то написано?
AnatolySh
Например здесь
Но сам я сомневаюсь... 05.gif
ViKo
Я не согласен. Когда-то здесь обсуждалось, наверное, можно найти.
Диапазон АЦП разбит на 4096 частей.
Мелочь, конечно...
adnega
Цитата(ViKo @ Feb 25 2016, 15:52) *
Диапазон АЦП разбит на 4096 частей.

При result на выходе модуля АЦП можно считать, что измеряемое напряжение находится в диапазоне
от Vadc * (result + 0) / 4096 до Vadc * (result + 1) / 4096.
ViKo
Цитата(adnega @ Feb 25 2016, 16:20) *
При result на выходе модуля АЦП можно считать, что измеряемое напряжение находится в диапазоне
от Vadc * (result + 0) / 4096 до Vadc * (result + 1) / 4096.

Да, можно приписать 0,5 к результату. Сместить на половину младшего разряда. Но делить-то надо на 4096.
adnega
Цитата(ViKo @ Feb 25 2016, 16:25) *
Но делить-то надо на 4096.

Кста, сдвиг в помощь.
Но не забываем, что это диапазон, а не какое-то конкретное значение.
ViKo
Цитата(adnega @ Feb 25 2016, 16:34) *
Кста, сдвиг в помощь.

Да, чего там... просто умножить результат преобразования на цену младшего бита. Еще учесть деления, усиления по пути, пока измеряемый сигнал доберется до АЦП.
TSerg
Цитата(ViKo @ Feb 25 2016, 15:52) *
Я не согласен. Когда-то здесь обсуждалось, наверное, можно найти.
Диапазон АЦП разбит на 4096 частей.


Не так. Резон тут такой для целочисленной- или fix - арифметики.
Максимальной величине Amax на входе АЦП соответствует максимальный двоичный код Kmax = 2^N -1
Соответственно МЗР (или масштабный коэффициент) определяется как МЗР = Amax / Kmax и никак иначе.
Поэтому, если у нас на выходе код *1111, то мы знаем, что входная величина не превысила Amax и нет насыщения.
Если считать, что АЦП срабатывает на 0.5 LSB (или мы принимаем за основу число элементарных шагов АЦП), тогда возникает недоопределенность и погрешность около 0 и около мах.

P.S.
Хотя.. сейчас всем это и многое другое - пофигу.

Цитата(AnatolySh @ Feb 25 2016, 15:38) *
Но сам я сомневаюсь... 05.gif


Не сомневайтесь и всегда делите максимальную входную величину на 2^N-1 для получения значения МЗР.
ViKo
Цитата(TSerg @ Feb 25 2016, 17:01) *
Не так. Резон тут такой для целочисленной- или fix - арифметики.
Максимальной величине Amax на входе АЦП соответствует максимальный двоичный код Kmax = 2^N -1
Соответственно МЗР (или масштабный коэффициент) определяется как МЗР = Amax / Kmax и никак иначе.
Поэтому, если у нас на выходе код *1111, то мы знаем, что входная величина не превысила Amax и нет насыщения.
Если считать, что АЦП срабатывает на 0.5 LSB (или мы принимаем за основу число элементарных шагов АЦП), тогда возникает недоопределенность и погрешность около 0 и около мах.

У меня другая логика. На выходе АЦП имеем 2^N чисел результатов, и каждое соответствует своему диапазону входного напряжения.
0 - это не просто 0 В и ничего выше. Нет, он выдается для диапазона от 0 В до Vref / 2^N. И так далее, вплоть до числа (2^N) - 1, которое соответствует диапазону от Vref - Vref / (2^N) до Vref. Грубо говоря - сработают все компараторы, сравнивающее входное напряжение с градациями опорного.
поправил числа...
TSerg
Цитата(ViKo @ Feb 25 2016, 17:16) *
У меня другая логика.


Логика может быть разная, главное, чтобы результат не пострадал. sm.gif

Цитата(ViKo @ Feb 25 2016, 17:16) *
На выходе АЦП имеем 2^N чисел результатов


На выходе АЦП, как ни крути, мы имеем максимальное число 2^N-1 и ему соответствует максимально возможное аналоговое напряжение с вышеуказанным МЗР.
В этом случае мы, умножив максимальный код на МЗР, получим максимально разрешенное входное напряжение.

Ну а так-то, можно играться с 0.5 МЗР, изучать как работает конкретный АЦП..
ViKo
Цитата(TSerg @ Feb 25 2016, 17:39) *
На выходе АЦП, как ни крути, мы имеем максимальное число 2^N-1 и ему соответствует...

(Vref / 2^N) * (2^N - 1). Т.е. чуть-чуть (единицу МЗР) не дотягивает до опорного. А 0,5 МЗР может слегка приблизить к нему (Vref). Тогда и 0 приподнимется на полразряда. Красиво, симметрично.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.