реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Настройка ADC в STM32
Jenya7
сообщение Jul 25 2017, 05:45
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Есть возможность использовать откоректированное значение опорного напряжения.
Цитата
Calculating the actual VDDA voltage using the internal reference voltage
The VDDA power supply voltage applied to the microcontroller may be subject to variation or
not precisely known. The embedded internal voltage reference (VREFINT) and its calibration
data acquired by the ADC during the manufacturing process at VDDA = 3.3 V can be used to
evaluate the actual VDDA voltage level.
The following formula gives the actual VDDA voltage supplying the device:
VDDA = 3.3 V ₓ VREFINT_CAL / VREFINT_DATA
Where:
• VREFINT_CAL is the VREFINT calibration value
• VREFINT_DATA is the actual VREFINT output value converted by ADC

VREFINT_CAL как я понимаю мы берем из ADC1->CALFACT
а VREFINT_DATA - откуда берем?
Go to the top of the page
 
+Quote Post
Эдди
сообщение Jul 25 2017, 06:11
Сообщение #2


Знающий
****

Группа: Участник
Сообщений: 825
Регистрация: 16-04-15
Из: КЧР, Нижний Архыз
Пользователь №: 86 250



Данные из канала АЦП, вестимо (ADC1_IN17).
P.S. Я так понял, VREFINT_CAL есть только у L-серий. А у обычных F нужно это значение измерить.
Т.е. если, скажем, мерить с точностью до сотых вольты (только зачем?), то VDDA = X / CH17 → X = VDDA * CH17 (считать лучше в uint32_t).
Скажем, дает нам вольтметр 3.25В, а внутреннее опорное — 1540ADU, тогда X = 325*1540 = 500500, и в любой момент просто делим 500500 на данные с CH17, получая VDD.

Сообщение отредактировал Эдди - Jul 25 2017, 06:20
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Jul 25 2017, 06:50
Сообщение #3


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(Эдди @ Jul 25 2017, 11:11) *
Данные из канала АЦП, вестимо (ADC1_IN17).
P.S. Я так понял, VREFINT_CAL есть только у L-серий. А у обычных F нужно это значение измерить.
Т.е. если, скажем, мерить с точностью до сотых вольты (только зачем?), то VDDA = X / CH17 → X = VDDA * CH17 (считать лучше в uint32_t).
Скажем, дает нам вольтметр 3.25В, а внутреннее опорное — 1540ADU, тогда X = 325*1540 = 500500, и в любой момент просто делим 500500 на данные с CH17, получая VDD.

только для L-серий? не знаю, у меня в STM32F303VCT6 есть ADC1->CALFACT.
смотрим формулу
Цитата
VCHANNELx = 3.3 V * VREFINT_CAL * ADCx_DATA / VREFINT_DATA * FULL_SCALE

Where:
• VREFINT_CAL is the VREFINT calibration value
• ADCx_DATA is the value measured by the ADC on channel x (right-aligned)
• VREFINT_DATA is the actual VREFINT output value converted by the ADC
• FULL_SCALE is the maximum digital value of the ADC output. For example with 12-bit
resolution, it will be 212 - 1 = 4095 or with 8-bit resolution, 28 - 1 = 255.

"Данные из канала АЦП, вестимо" - это ADCx_DATA
а VREFINT_DATA откуда?
Go to the top of the page
 
+Quote Post
scifi
сообщение Jul 25 2017, 07:26
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Jenya7 @ Jul 25 2017, 09:50) *
VCHANNELx = 3.3 V * VREFINT_CAL * ADCx_DATA / VREFINT_DATA * FULL_SCALE

Очевидно же.
VREFINT_CAL - калибровка из ПЗУ.
VREFINT_DATA - измеренное на канале АЦП Vrefint
ADCx_DATA - измеренное на ином канале АЦП, результат именно этого измерения корректируется, приводится к вольтам и присваивается переменной VCHANNELx.
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Jul 25 2017, 07:49
Сообщение #5


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(scifi @ Jul 25 2017, 12:26) *
Очевидно же.
VREFINT_CAL - калибровка из ПЗУ.
VREFINT_DATA - измеренное на канале АЦП Vrefint
ADCx_DATA - измеренное на ином канале АЦП, результат именно этого измерения корректируется, приводится к вольтам и присваивается переменной VCHANNELx.

ааа понял. спасибо. то есть я должен измерить канал #define ADC_Channel_Vrefint ((uint8_t)ADC_Channel_18)
я могу передать его в функцию в качестве аргумента?
Код
uint32_t ADC_Read(uint32_t channel)
{
    uint32_t adc_val;
    
    ADC_RegularChannelConfig(ADCx, channel, 1, ADC_SampleTime_7Cycles5);
    
    /* Start ADC1 Software Conversion */
     ADCx->CR |= ADC_CR_ADSTART;
    
    /* Test EOC flag */
    while(ADC_GetFlagStatus(ADCx, ADC_FLAG_EOC) == RESET);
    
    /* Get ADC1 converted data */
    adc_val = (uint16_t)ADCx->DR;
    
    return adc_val;
}


Сообщение отредактировал Jenya7 - Jul 25 2017, 07:49
Go to the top of the page
 
+Quote Post
scifi
сообщение Jul 25 2017, 07:53
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Jenya7 @ Jul 25 2017, 10:49) *
я могу передать его в функцию в качестве аргумента?

Это как хотите. Есть множество способов всё это организовать.
Кстати, что за нездоровое увлечение типом uint32_t? Есть отличный тип int - всего 3 буквы, и работает ничуть не хуже.
Код
int ADC_Read(int channel)
{
    ...    
    return ADCx->DR;
}
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Jul 25 2017, 07:58
Сообщение #7


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(scifi @ Jul 25 2017, 12:53) *
Это как хотите. Есть множество способов всё это организовать.
Кстати, что за нездоровое увлечение типом uint32_t? Есть отличный тип int - всего 3 буквы, и работает ничуть не хуже.
Код
int ADC_Read(int channel)
{
    ...    
    return ADCx->DR;
}

рекомендуют так - uint32_t, для портабилити. int он signed вообще то.
Go to the top of the page
 
+Quote Post
scifi
сообщение Jul 25 2017, 08:07
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Jenya7 @ Jul 25 2017, 10:58) *
рекомендуют так - uint32_t, для портабилити

Это глупости и танцы с бубном. Какая такая портабилити кода, написанного для STM32? На другой STM32 он перенесётся и так, и эдак.

Цитата(Jenya7 @ Jul 25 2017, 10:58) *
int он signed вообще то.

Ну и что? Почему-то это никому не мешает делать, к примеру, вот так:
for (int i = 0; i < 10000; i++)

С другой стороны, я не настаиваю. Просто int короче. Ну и красивше, но это субъективное.
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Jul 25 2017, 08:07
Сообщение #9


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(scifi @ Jul 25 2017, 13:02) *
Это глупости и танцы с бубном. Какая такая портабилити кода, написанного для STM32? На другой STM32 он перенесётся и так, и эдак.
С другой стороны, я не настаиваю. Просто int короче. Ну и красивше, но это субъективное.

но int он знаковый. а unsigned int это уже не три это... много букаф. sm.gif
Цитата(scifi @ Jul 25 2017, 13:02) *
Ну и что? Почему-то это никому не мешает делать, к примеру, вот так:
for (int i = 0; i < 10000; i++)

ну вообще да. чего я боюсь. что мне не хватит 2^32 / 2.

кстати. VREFINT_DATA он ведь общий для ADC1 и ADC2. то есть мне достаточно померять на ADC1?

а в ADCx_CCR есть бит VREFEN: VREFINT enable - его надо выставить?

Сообщение отредактировал Jenya7 - Jul 25 2017, 08:29
Go to the top of the page
 
+Quote Post
Эдди
сообщение Jul 25 2017, 08:15
Сообщение #10


Знающий
****

Группа: Участник
Сообщений: 825
Регистрация: 16-04-15
Из: КЧР, Нижний Архыз
Пользователь №: 86 250



Цитата(Jenya7 @ Jul 25 2017, 09:50) *
только для L-серий? не знаю, у меня в STM32F303VCT6 есть ADC1->CALFACT.

А, у меня только F030, F042 и F103. Там такого нет, но несложно померить один раз — я серии железяк не делаю.
Вообще, при питании от кренки или чего понадежней нет такого размаха напряжения питания, чтобы прямо калибровать надо было. Во всяком случае, я резисторами калибровал — честные 12 бит было, никаких диких шумов…

Цитата(Jenya7 @ Jul 25 2017, 10:58) *
int он signed вообще то.

Лучше вообще не использовать типы вроде char/int/long и т.п. Мало ли — перенесете высокоуровневый код с STM32 на STM8, и получите жесть, т.к. типы данных будут разной длины!
Go to the top of the page
 
+Quote Post
scifi
сообщение Jul 25 2017, 08:30
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Прошу прощения, что нечаянно набросил про int. Боюсь, снова начнётся хождение между трёх сосен, как это здесь часто бывает crying.gif

Цитата(Jenya7 @ Jul 25 2017, 11:07) *
кстати. VREFINT_DATA он ведь общий для ADC1 и ADC2. то есть мне достаточно померять на ADC1?

Так точно.
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Jul 25 2017, 08:45
Сообщение #12


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(scifi @ Jul 25 2017, 13:30) *
Прошу прощения, что нечаянно набросил про int. Боюсь, снова начнётся хождение между трёх сосен, как это здесь часто бывает crying.gif
Так точно.

и еще нужно включить канал
ADC1_2->CCR |= ADC12_CCR_VREFEN;

фигня получается однако
Код
vref_data = ADC_Read(ADC1, ADC_Channel_Vrefint);  //получаем 2838
vref_cal = (uint32_t)ADC1->CALFACT;      //получаем 58
    
vref = (3300 * vref_cal) / vref_data;           //получаем 67


vref = 67 ???

Сообщение отредактировал Jenya7 - Jul 25 2017, 09:07
Go to the top of the page
 
+Quote Post
scifi
сообщение Jul 25 2017, 09:55
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Здрассте, приехали.
ADC1->CALFACT - это совсем не то.
Заводская калибровка - это *(uint16_t*)0x1FF80078, если эта штука вообще присутствует в вашем МК.
Go to the top of the page
 
+Quote Post
Эдди
сообщение Jul 25 2017, 09:55
Сообщение #14


Знающий
****

Группа: Участник
Сообщений: 825
Регистрация: 16-04-15
Из: КЧР, Нижний Архыз
Пользователь №: 86 250



Цитата(Jenya7 @ Jul 25 2017, 11:45) *
ADC1->CALFACT; //получаем 58

Мне с выражением за вас даташит читать? Этот регистр не имеет никакого отношения к "заводскому" измерению напряжения на vref, это — внутреннее значение калибровок, которое вы можете изменять!
Кстати, насчет STM32F0 я был не прав: в них этот регистр есть (0x1FFF F7BA - 0x1FFF F7BB). А вот в F103 — нет.

Сообщение отредактировал Эдди - Jul 25 2017, 10:00
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Jul 25 2017, 10:16
Сообщение #15


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(scifi @ Jul 25 2017, 14:55) *
Здрассте, приехали.
ADC1->CALFACT - это совсем не то.
Заводская калибровка - это *(uint16_t*)0x1FF80078, если эта штука вообще присутствует в вашем МК.

ой. что то я в даташит не нашел даже упоминания о регистре с заводской калибровкой. поиск по адресу 0x1FF80078 тоже не дал результатов. у STM32F303VCT6 такой навороченный ADC не может быть чтоб у него не было этой опции.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 13:03
Рейтинг@Mail.ru


Страница сгенерированна за 0.01497 секунд с 7
ELECTRONIX ©2004-2016