Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: LPC2103 и АЦП
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
XWoo
Появилась у меня недавно платка, чем-то напоминающая Olimex LPC-H2103. В платке я задействовал таймер, spi, uart, подключил два 7-мисегментных индикатора. PLL выключил (Cclk=Pclk=Fosc=14.7456 МГц). Теперь взялся за АЦП. Примеры скачал. Запустил АЦП в Burst режиме (с прерыванием):

PINSEL0 |= 0x00F00000; // AD3,4
PINSEL1 |= 0x0003F000; // AD0,1,2

ADCR = 0x0020921F;
ADCR |= 0x00010000; // start burst mode

CLKDIV = 147-1 = 146, т.е. АЦП работает на ~100 КГц.
Задействованы аналоговые входы AD0..AD4.

В прерывании опрашиваю входы и результат загоняю в массив:

unsigned int r, ch;

r = ADGDR;
ch = (r >> 24) & 0x00000007;
ADCresult[ch] = (unsigned short)((r>>6) & 0x03FF);

Потом данные из массива отправляю по uart'у и вывожу целую и десятичную часть на 2 индикатора.

Всё работает, но есть одно "НО". У меня не соответствуют значения напряжения в АЦП (10-битный код из регистра ADGDR) и напряжения на аналоговом входе. Я подаю на вход AD4 (вывод 36) напряжение от 0 до 3,3 В. При этом показания напряжения АЦП отличаются от входного на несколько сот милливольт: вместо 3,0В АЦП выдаёт 2,9В; вместо 1,8В - 1,6В; вместо 0,5В - 0,4В - т.е. само отличие непостоянно: чем ближе к нулю, тем оно меньше.

10-битный код я преобразовываю в напряжение следующим образом: [код]*Vref, где Vref=3.3B - образцовое напряжение АЦП (вывод Vdda). Например, если код равен 0x02F6, то это соответствует напряжению 2501 милливольт, однако на вход AD4 подано напряжение 2.9 вольт! Разница в 400 мВ!

Может я неверно расчитываю показания АЦП? Как убрать такое несоответствие?

Ещё у меня младшие 8 бит постоянно меняются, т.е. в коде 0x02F6 число 0xF6 после следующего
измерения АЦП будет уже другим, например: 0x02E5, 0x02FE.
Это наверное нестабильность по питанию? Или какие-то помехи?
KRS
А вы пробовали только 1 канал и полингом опрашивать?
XWoo
да, пробовал. И AD0 и др каналы. И в single режиме опрашивал (в этом режиме я сперва и опробовал АЦП). Результат один и тот же!

Даже пробовал менять частоту АЦП (clkdiv): выставлял 57.6 КГц, 100 КГц, 1.05 МГц - всё работает без изменений. а вот на 2 МГц и выше (вплоть до 4.5 МГц) моя плата то ли тормозит, то ли вообще не запускается.
карабас
Vref=3.3B, а какое оно в реальности?
XWoo
Замерил Vref. Оно равно 3.48 В. И питание ядра также завышено, там 2.12 В.
Неужели данная проблема заключена в повышенном напряжении питания проца?
Займусь регулировкой двух стабилизаторов на 3.3 В и 1.8 В.
fmdost
Цитата(XWoo @ Jul 23 2010, 17:28) *
Займусь регулировкой двух стабилизаторов на 3.3 В и 1.8 В.


Да, но сначала надо заменьть батарейку в тестере wink.gif
XWoo
да дело тут не в батарейках (3 различных мультиметра показывали одно и тоже), а в том что компилятор кейл строку "#define Vref (33/10)" воспринимает не как 3.3, а как 3, поэтому и произведение показаний ацп (10 бит) на Vref было занижено. а вот когда я поставил "#define Vref (3.3)", тогда всё встало на свои места.

оба напряжения я уменьшил до 1.90В и 3.35В (соответственно и Vref поставил равным 3.35).

если сделать эти напряжения равными 1.80/1.85 и 3.30, то моя платка не работала.


эту строку "#define Vref (33/10)" я увидел в примерах (исходники на си и pdf). видимо тому, кто писал тот код, не требовалась десятичная часть показаний АЦП, нужна была только целая часть.
rezident
Цитата(XWoo @ Jul 29 2010, 16:21) *
эту строку "#define Vref (33/10)" я увидел в примерах (исходники на си и pdf). видимо тому, кто писал тот код, не требовалась десятичная часть показаний АЦП, нужна была только целая часть.

Это просто ваш компилятор оптимизировал вычисление константы. Причем целочисленное вычисление. Поскольку константы без явного указания типа все целочисленные (тип int).
А вообще вычислять напряжение АЦП с применением плавающей арифметики как-то неразумно. Тем более когда точность и диапазон изменения величин небольшой. По крайней мере уж на 32-х битных ARM проблем с целочисленным вычислением напряжения, измеряемого встроенным АЦП быть не должно.
Кстати, если уж совсем придираться biggrin.gif, то дефайн нужно было привести к виду
Код
#define VREF 3.3f

Во-первых, суффикс f явно приводит константу к типу float. Во-вторых, в макросах общепринято использовать только заглавные символы, чтобы отличать их (макросы) от переменных и функций.
sonycman
Попробуйте вычислять так:

voltage = adc_value * VREF / RES где VFEF - опорное напряжение в милливольтах (например, 3300 для 3.3в) и RES - разрешение АЦП (для 10 бит - 1023).
Получится так:
Код
unsigned int voltage = adc_value * 3300 / 1023;

где voltage - в милливольтах.

Все вычисления целочисленные, а желаемого разрешения можно добиться, меняя VREF в большую сторону - 33000, 330000 и т.д.
rezident
Цитата(sonycman @ Jul 29 2010, 17:13) *
Получится так:
Код
unsigned int voltage = adc_value * 3300 / 1023;

где voltage - в милливольтах.

Лучше будет так
Код
unsigned int voltage = ((unsigned long) adc_value * 3300UL) / 1023UL;

без скобок компилятор опять может оптимизировать вычисление константы и умножение будет снова на число 3.
XWoo
rezident и sonycman, спасибо вам за советы. Завтра попробую.

И спасибо всем за участие. smile.gif

Думаю эту тему можно закрыть.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.