Аналоговые мультиплексоры, ADC

Однажды понадобилось 16-ть каналов АЦП, при 8-ми имеющихся у MSP430G2553 ...

И это могло бы стать проблемой, не будь аналоговых мультиплексоров (коммутаторов, ключей)
Для примера приведена структурная схема TS5A3157 от TI

Так как он является одноканальным, то имеет всего два мультиплексируемых входа (Vnc и Vno).
Вывод Vcom — общий и всегда соединен с одним из аналоговых входов.
Вывод Vi определяет в каком состоянии будет находится «переключатель».
Мультиплексоры пропускают ток в обоих направлениях и в идеале должны вести себя как выключатель, но реальность вносит своих коррективы.
Основным элементом является MOSFET транзистор.

Благодаря низкому сопротивлению в замкнутом состоянии, высокому сопротивлению в режиме отсечки, низким токам утечки и малым паразитным емкостям, MOSFET-транзисторы с успехом используются в качестве аналоговых ключей. В портативных устройствах аналоговые мультиплексоры используются для коммутации входных и выходных сигналов. С помощью аналогового мультиплексора можно из одноканального АЦП сделать многоканальный и т.д.

Так как одноканального мультиплексора для решения возникшей проблемы мне бы не хватило, выбор пал на 74HC4052

74HC4052 — это высокоскоростная CMOS микросхема, с двумя 4-х канальными аналоговыми мультиплексируемыми-демультиплексируемыми входами.
Каждый мультиплексер имеет 4-е независимых входа/выхода (выводы nY0-nY3) и общие Common входы/выходы (выводы nZ).
Логику переключения задают выводы S0-S1 и вход управления состоянием — E.
Когда вывод E находится в LOW состоянии — один из четырех переключателей (определяют S0 и S1)приходит в активное состояние.
Когда вывод E в высоком состоянии — все переключатели находятся в высокоимпедансном состоянии, независимо от выводов S0 и S1
(на схеме в зеленных блоках — делители и стабилитроны).

В даташите представлена таблица функционального состояния выводов:

Для подключения 16-ти входов потребовалось две 74HC4052 (существует более поздняя ревизия — HEF4052B). Стоят они совсем не дорого (8-15 рублей).
К микроконтроллеру подключил следующим образом:

Контроллер как уже указал выше — MSP430G2553, недорогой (не жирный как stm32 конечно, для своих задач более чем годится), легкодоступный.
Да к тому же поддреживает Spy by wire, что имеется на большинстве современных Launchpad-ов.

Дефайны портов

// Analog MUX1 inputs-outputs
#define ANALOG_MUX1_S0_PORT	P2OUT
#define ANALOG_MUX1_S0_DIR	P2DIR
#define ANALOG_MUX1_S0_PIN	BIT3
//
#define ANALOG_MUX1_S1_PORT	P3OUT
#define ANALOG_MUX1_S1_DIR	P3DIR
#define ANALOG_MUX1_S1_PIN	BIT4
//
#define ANALOG_MUX1_E_PORT	P2OUT
#define ANALOG_MUX1_E_DIR	P2DIR
#define ANALOG_MUX1_E_PIN	BIT4
//
#define ANALOG_MUX1_OUT1_PORT	P1OUT
#define ANALOG_MUX1_OUT1_DIR	P1DIR
#define ANALOG_MUX1_OUT1_PIN	BIT6
//
#define ANALOG_MUX1_OUT2_PORT	P1OUT
#define ANALOG_MUX1_OUT2_DIR	P1DIR
#define ANALOG_MUX1_OUT2_PIN	BIT7
// Analog MUX 2 inputs-outputs
#define ANALOG_MUX2_S0_PORT	P3OUT
#define ANALOG_MUX2_S0_DIR	P3DIR
#define ANALOG_MUX2_S0_PIN	BIT3
//
#define ANALOG_MUX2_S1_PORT	P3OUT
#define ANALOG_MUX2_S1_DIR	P3DIR
#define ANALOG_MUX2_S1_PIN	BIT2
//
#define ANALOG_MUX2_E_PORT	P2OUT
#define ANALOG_MUX2_E_DIR	P2DIR
#define ANALOG_MUX2_E_PIN	BIT2
//
#define ANALOG_MUX2_OUT1_PORT	P1OUT
#define ANALOG_MUX2_OUT1_DIR	P1DIR
#define ANALOG_MUX2_OUT1_PIN	BIT4
//
#define ANALOG_MUX2_OUT2_PORT	P1OUT
#define ANALOG_MUX2_OUT2_DIR	P1DIR
#define ANALOG_MUX2_OUT2_PIN	BIT3

Настройка

void ADC_init(void)
{
    ANALOG_MUX1_S0_DIR 		|= ANALOG_MUX1_S0_PIN;		// SO out
    ANALOG_MUX1_S1_DIR 		|= ANALOG_MUX1_S1_PIN;		// S1 out
    ANALOG_MUX1_E_DIR 		|= ANALOG_MUX1_E_PIN;		// E out
    ANALOG_MUX1_OUT1_DIR	&=~ ANALOG_MUX1_OUT1_PIN;	// OUT1 input
    ANALOG_MUX1_OUT2_DIR 	&=~ ANALOG_MUX1_OUT2_PIN;	// OUT2 input
    ANALOG_MUX2_S0_DIR 		|= ANALOG_MUX2_S0_PIN;		// SO out
    ANALOG_MUX2_S1_DIR 		|= ANALOG_MUX2_S1_PIN;		// S1 out
    ANALOG_MUX2_E_DIR 		|= ANALOG_MUX2_E_PIN;		// E out
    ANALOG_MUX2_OUT1_DIR	&=~ ANALOG_MUX2_OUT1_PIN;	// OUT1 input
    ANALOG_MUX2_OUT2_DIR 	&=~ ANALOG_MUX2_OUT2_PIN;	// OUT2 input

    ADC10CTL0 = SREF_0 + ADC10SHT_3 + ADC10ON + ADC10IE;  // Vcc & Vss as reference, Sample and hold for 64 Clock cycles, ADC on, ADC interrupt enable
}

Дальше из основного цикла, по прерыванию от таймера — вызываю функцию переключения каналов
void ADC_Select_AnalogInput(uint8_t NumChannel)
{
    uint8_t RetNumADC_Input;
    uint8_t RetNumADC_MUX;

    if(NumChannel <=8)
    {
    	// MUX 0
    	RetNumADC_MUX = MUX1;
	switch(NumChannel)
	{
    	    case ANALOG_INPUT_CH1	:	RetNumADC_Input = 1; ANALOG_MUX1_E_PORT &=~ ANALOG_MUX1_E_PIN; ANALOG_MUX1_S1_PORT &=~ ANALOG_MUX1_S1_PIN; ANALOG_MUX1_S0_PORT |=  ANALOG_MUX1_S0_PIN;  break;
            case ANALOG_INPUT_CH2	:	RetNumADC_Input = 1; ANALOG_MUX1_E_PORT &=~ ANALOG_MUX1_E_PIN; ANALOG_MUX1_S1_PORT |= ANALOG_MUX1_S1_PIN;  ANALOG_MUX1_S0_PORT |=  ANALOG_MUX1_S0_PIN;  break;
	    case ANALOG_INPUT_CH3	:	RetNumADC_Input = 1; ANALOG_MUX1_E_PORT &=~ ANALOG_MUX1_E_PIN; ANALOG_MUX1_S1_PORT |= ANALOG_MUX1_S1_PIN;  ANALOG_MUX1_S0_PORT &=~ ANALOG_MUX1_S0_PIN;  break;
	    case ANALOG_INPUT_CH4	:	RetNumADC_Input = 1; ANALOG_MUX1_E_PORT &=~ ANALOG_MUX1_E_PIN; ANALOG_MUX1_S1_PORT &=~ ANALOG_MUX1_S1_PIN; ANALOG_MUX1_S0_PORT &=~ ANALOG_MUX1_S0_PIN;  break;
	    case ANALOG_INPUT_CH5	:	RetNumADC_Input = 0; ANALOG_MUX1_E_PORT &=~ ANALOG_MUX1_E_PIN; ANALOG_MUX1_S1_PORT |= ANALOG_MUX1_S1_PIN;  ANALOG_MUX1_S0_PORT &=~ ANALOG_MUX1_S0_PIN;  break;
	    case ANALOG_INPUT_CH6	:	RetNumADC_Input = 0; ANALOG_MUX1_E_PORT &=~ ANALOG_MUX1_E_PIN; ANALOG_MUX1_S1_PORT &=~ ANALOG_MUX1_S1_PIN; ANALOG_MUX1_S0_PORT |=  ANALOG_MUX1_S0_PIN;  break;
	    case ANALOG_INPUT_CH7	:	RetNumADC_Input = 0; ANALOG_MUX1_E_PORT &=~ ANALOG_MUX1_E_PIN; ANALOG_MUX1_S1_PORT &=~ ANALOG_MUX1_S1_PIN; ANALOG_MUX1_S0_PORT &=~ ANALOG_MUX1_S0_PIN;  break;
	    case ANALOG_INPUT_CH8	:	RetNumADC_Input = 0; ANALOG_MUX1_E_PORT &=~ ANALOG_MUX1_E_PIN; ANALOG_MUX1_S1_PORT |= ANALOG_MUX1_S1_PIN;  ANALOG_MUX1_S0_PORT |=  ANALOG_MUX1_S0_PIN;  break;
	}
         ADC_StartConvert(RetNumADC_MUX, RetNumADC_Input);
    }
    else
    {
    	// MUX 1
    	RetNumADC_MUX = MUX2;
	switch(NumChannel)
	{
            case ANALOG_INPUT_CH9	:	RetNumADC_Input = 1; ANALOG_MUX2_E_PORT &=~ ANALOG_MUX2_E_PIN; ANALOG_MUX2_S1_PORT &=~ ANALOG_MUX2_S1_PIN; ANALOG_MUX2_S0_PORT |=  ANALOG_MUX2_S0_PIN; 	break;
	    case ANALOG_INPUT_CH10	:	RetNumADC_Input = 1; ANALOG_MUX2_E_PORT &=~ ANALOG_MUX2_E_PIN; ANALOG_MUX2_S1_PORT |=  ANALOG_MUX2_S1_PIN; ANALOG_MUX2_S0_PORT |=  ANALOG_MUX2_S0_PIN; 	break;
	    case ANALOG_INPUT_CH11	:	RetNumADC_Input = 1; ANALOG_MUX2_E_PORT &=~ ANALOG_MUX2_E_PIN; ANALOG_MUX2_S1_PORT |=  ANALOG_MUX2_S1_PIN; ANALOG_MUX2_S0_PORT &=~ ANALOG_MUX2_S0_PIN; 	break;
	    case ANALOG_INPUT_CH12	:	RetNumADC_Input = 1; ANALOG_MUX2_E_PORT &=~ ANALOG_MUX2_E_PIN; ANALOG_MUX2_S1_PORT &=~ ANALOG_MUX2_S1_PIN; ANALOG_MUX2_S0_PORT &=~ ANALOG_MUX2_S0_PIN;	break;
	    case ANALOG_INPUT_CH13	:	RetNumADC_Input = 0; ANALOG_MUX2_E_PORT &=~ ANALOG_MUX2_E_PIN; ANALOG_MUX2_S1_PORT |=  ANALOG_MUX2_S1_PIN; ANALOG_MUX2_S0_PORT &=~ ANALOG_MUX2_S0_PIN; 	break;
	    case ANALOG_INPUT_CH14	:	RetNumADC_Input = 0; ANALOG_MUX2_E_PORT &=~ ANALOG_MUX2_E_PIN; ANALOG_MUX2_S1_PORT &=~ ANALOG_MUX2_S1_PIN; ANALOG_MUX2_S0_PORT |=  ANALOG_MUX2_S0_PIN; 	break;
	    case ANALOG_INPUT_CH15	:	RetNumADC_Input = 0; ANALOG_MUX2_E_PORT &=~ ANALOG_MUX2_E_PIN; ANALOG_MUX2_S1_PORT &=~ ANALOG_MUX2_S1_PIN; ANALOG_MUX2_S0_PORT &=~ ANALOG_MUX2_S0_PIN;	break;
	    case ANALOG_INPUT_CH16	:	RetNumADC_Input = 0; ANALOG_MUX2_E_PORT &=~ ANALOG_MUX2_E_PIN; ANALOG_MUX2_S1_PORT |=  ANALOG_MUX2_S1_PIN; ANALOG_MUX2_S0_PORT |=  ANALOG_MUX2_S0_PIN; 	break;
	}
	ADC_StartConvert(RetNumADC_MUX, RetNumADC_Input);
    }
}
// Начало преобразования
void ADC_StartConvert(uint8_t NumMUX, uint8_t NumChannel)
{
    while (ADC10CTL1 & BUSY);
    // reset ADC channel
    ADC10CTL0 &=~ (ENC | ADC10ON | ADC10SC);
    if(NumMUX == 0)
    {
	switch(NumChannel)
	{
    	case 0:
            ADC10AE0 = BIT6;
	    ADC10CTL1 = INCH_6 + ADC10DIV_3 ;         // Channel 3, ADC10CLK/3
	    break;
	case 1:
	    ADC10AE0 = BIT7;
	    ADC10CTL1 = INCH_7 + ADC10DIV_3 ;
	break;
	}
    }
    else
    {
    	switch(NumChannel)
	{
    	case 0:
            ADC10AE0 = BIT4;
	    ADC10CTL1 = INCH_4 + ADC10DIV_3 ;
	break;
	case 1:
	    ADC10AE0 = BIT3;
	    ADC10CTL1 = INCH_3 + ADC10DIV_3 ;
	break;
	case ANALOG_EXTERN_5V:
            ADC10AE0 = BIT0;
	    ADC10CTL1 = INCH_0 + ADC10DIV_3 ;
	break;
	case ANALOG_EXTERN_9V:
	    ADC10AE0 = BIT5;
	    ADC10CTL1 = INCH_5 + ADC10DIV_3 ;
	break;
	}
    }

    ADC10CTL0 |= ENC | ADC10ON;
    while (ADC10CTL1 & BUSY);               // Wait if ADC10 core is active
    ADC10CTL0 |= ENC + ADC10SC;             // Sampling and conversion start
}

И само прерывания от ADC

#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR(void)
{
    TransporterStruct.ADC_Status = S_ANALOG_CONVERT_END;
    TransporterStruct.ADC_in_Value[TransporterStruct.ADC_CurChannel] = ADC10MEM;
    TransporterStruct.ADC_CurChannel ++;//increment channel
    if(TransporterStruct.ADC_CurChannel >= (ALL_ANALOG_INPUTS))
    {
	TransporterStruct.ADC_CurChannel =0;
    }
    ANALOG_MUX1_E_PORT |= ANALOG_MUX1_E_PIN;
    ANALOG_MUX2_E_PORT |= ANALOG_MUX2_E_PIN;
}

Получилось так:

Чтобы перевести полученный результат в вольты — применим:
VREF 2.5
АЦП 10 битное (1023)
Один отсчет — VREF/1023 = 0.0024437 V
т.е. например 114 * 0.0024437 = 0,2785818 вольта.

Аналоговые мультиплесоры в настоящее время предлагет большое количество фирм (Maxim, Analog Device, TI и пр. пр.), у каждого есть преимущества и недостатки.
Если это высокая цена — значит прибор обладает низким уровнем шума или высоким быстродействием на переключение (с низким шумом), и наоборот.
74HC4052 в этом отношении — достаточно бюджетное решение.

Полезные материалы:
Аналоговые мультиплексоры — gaw.ru
Аналоговые мультиплексоры — Compel
Аналоговые ключи и мультиплексоры VISHAY
MSP430 ADC Tutorial
  • +2
  • 06 декабря 2014, 21:28
  • khomin

Комментарии (52)

RSS свернуть / развернуть
Что дополнить, подправить, я весь внимание…
0
Один отсчет — VREF/1023 = 0.0024437 V
ЕМНИП, на 1024 делить надо, а не 1023.
+1
самый большой код именно 1023, при VREF на входе, соответственно и делить надо на него а не на 1024.
0
Обычно формула для АЦП именно V=N*REF/2^BITS, хотя это и выглядит несколько странно, и, например, у AVR так и есть. Но действительно, мануал на MSP430G2553 указывает формулу V=N*REF/1023.
0
делить на степень 2 гораздо проще, то что при этом будет ошибка масштаба 1-1023/1024 =0.1% AVRам без разницы там у АЦП куда больше проблемы есть.
для наглядности можно взять 2х битный АЦП с четырьмя состояниями, и при опоре например 3В,
00 — 0V, 01 -> 1V, 10 -> 2V, 11 -> 3V.
соответственно напряжение будет Vref * D / (2^2-1).
0
Нет, обычно АЦП при ((2^N-1)/(2^N))*Vref выдают максимальный код, а при Vref уже уходят в перегрузку. Не знаю, правда, с чем это связано.
0
P.S. То есть в приведенном примере будут 0V -> 00, 0.75V -> 01, 1.5V -> 10, 2.25V -> 11, 3V — за пределом измерения.
-1
Указанный пример верен для:
AVR (проверял по даташиту на ATMEGA8)
STM32F1 (согласно AN2834)
STM8S (AN2719)
PIC (на примере даташита на PIC10F220)
C8051F300
Да и вики считает так же.

Так что как раз расчет V=N*Vref/1023 — это нетипичная формула.

В плане примера, правда, стоит уточнить, что обычно ступенька, соответствующая коду N, имеет границы от N*LSB до (N+1)*LSB, где LSB=Vref/2^Bits.
0
нарисуйте график, по горизонтали входное напряжение, по вертикали — выходной код.
потом если через середины получившихся ступенек провести прямую линию, у идеального АЦП она должна пройти через точки 0,0 и Vref, MAX_CODE.
у того что Вы привели выше — так не получается, во-первых смещение, во-вторых почему опорное напряжение вдруг стало за пределом измерения. Давайте тогда и снизу от нуля тоже для симметрии один LSB откусим.

если atmel сделал так что эта прямая проходит через Vref, MAX_CODE+1 чтобы считать удобней было — молодцы конечно, но их АЦП даже с калибровкой это не особо поможет.
atmel и AD считают что полная шкала это Vref — 1LSB, a TI и maxim что просто Vref.
а у lineara еще часто дополнительный overflow бит есть.
+2
у идеального АЦП она должна пройти через точки 0,0 и Vref, MAX_CODE.
А то я их не рисовал — еще в институте. И проходит эта линия не через (Vref, MAX_CODE), а через (Vref, 2^BITS). Но, поскольку выдать код 2^BITS АЦП не способен, на Vref у него будет переполнение.
Алсо, не у всех АЦП эта линия прозодит через середины ступенек. Так, у приведенной в одном из аппнотов характеристики она проходила через верхние углы ступенек (т.е. АЦП округляет вниз, это естественное поведение для SAR, который сравнивает со значениями Vref/2, Vref/4, etc).
+1

Вы правы. Это передаточная характеристика АЦП в dsPIC33. А я то думал почему это у него сдвиг и наклон по результатам эксперимента. Спасибо Вам за указания правильного направления копания :)))) Посыпаю голову пеплом :)))
0
Это, кстати, как раз характеристика АЦП, у которого линия (0,0)-(Vref,2^n) проходит через середину ступенек (т.е. АЦП с round-округлением, а я упоминал АЦП с floor-округлением).
0
Да, но в формуле указано делить на 1024 а не на 1023.
0
А это зависит не от типа округления, а от наклона характеристики.
Ну и какя уже сказал, меня удивило, что у МК и топика (MSP430G2553) указано делить на 1023. Это нетипично, скажем так.
0
Картинка верная, и пояснения верные.
Но в пояснениях для некоторых кодов указано начало интервала, для других — конец интервала, для третьих — середина. Это сбивает с толку.
Было бы дидактически ;-) и методически правильнее указать:

10-битный код даёт 1024 значения.
Одна ступенька по напряжению или цена 1 МЗР
 = (V ref hi−V ref lo)/1024.
Коды центрированы (round) относительно истинного входного напряжения.
Поэтому:
код 0000000000:
 начало интервала = −0,5 МЗР
  = −1024/2048(V ref hi−V ref lo),
 центр интервала = 0 МЗР
  = 0 (V ref hi−V ref lo),
 конец интервала = +0,5 МЗР
  = +1024/2048(V ref hi−V ref lo);

код 1000000000:
 начало интервала = 512 МЗР−0,5 МЗР
  = 511,5 МЗР
  = 1023/2048(V ref hi−V ref lo),
 центр интервала = 512 МЗР
  = 1/2 (V ref hi−V ref lo)
  = 512/1024 (V ref hi−V ref lo)
  = 1024/2048 (V ref hi−V ref lo),
 конец интервала = 512+0,5 МЗР
  = 512,5 МЗР
  = 1025/2048(V ref hi−V ref lo);

код 1111111111:
 начало интервала = 1023 МЗР−0,5 МЗР
  = 1022,5 МЗР
  = 2045/2048(V ref hi−V ref lo),
 центр интервала = 1023 МЗР
  = 0 (V ref hi−V ref lo),
 конец интервала = 1023+0,5 МЗР
  = 1023,5 МЗР
  = 2047/2048(V ref hi−V ref lo);

Итак, для центрированной передаточной функции мы имеем ошибку квантования ±0,5 МЗР и рабочий интервал ]−0,5 МЗР; 1023,5 МЗР[.
Если бы мы рассматривали АЦП с округлением вниз (floor), то ошибка квантования была бы ]0; +0,5 МЗР[, график входного напряжения проходил бы по вершинам ступенек, а полный легальный рабочий интервал входных напряжений был бы ]0 МЗР; 1024 МЗР[. Разница с предыдущим, центрированным АЦП только в сдвиге на 0,5 МЗР.
В любом случае, какой бы ни был сдвиг, весь диапазон включает все 1024 ступеньки напряжения.
Откуда возникла формула с делением на 1023, мне неясно.
Ещё должен добавить, что не всегда АЦП имеют 2^Nbit ступенек. Например возможны варианты 3½ или 4¾ декады и другие десятичные варианты.
+1
Ну, это уже и не с двоичным выходом АЦП. Интересно, кстати, что для 3.5-разрядного АЦП рабочий диапазон — -1.999Vref...1.999Vref.
0
а при Vref уже уходят в перегрузку
Каким образом можно отличить перегрузку от легального состояния «все единицы»? Вводятся некие дополнительные цепи? Добавляется время интегрирования?
+1
Только тем, что АЦП выдает не соответствующий напряжению код — зашкаливает.
0
Ну в общем да
The ADC converts an analog input voltage to a 10-bit digital value through successive approximation.
The minimum value represents GND and the maximum value represents the voltage on the AREF pin minus 1LSB.
0
— А пацаки и чатлане это национальность?
— Нет.
— Биологический фактор?
— Нет.
— Каста?
— Нет.
— Лица с других планет?
— Нет.
— А чем они друг от друга отличаются?
— Ты что, дальтоник, Скрипач? Зелёный цвет от оранжевого отличить не можешь?
-2
И в чем смысл этой цитаты? Что, если при напряжении на входе 2*Vref АЦП выдает код 1023 означает, что надо считать напряжение как N*2*Vref/1023?
-1
А в чём был смысл вашего ответа?
0
Я уточню: каким образом АЦП может отличить перегрузку от легального состояния «все единицы»?
0
Никак. И программа тоже никак это не определит. Но вопрос-то ведь не об этом, а о том, как пересчитывать код АЦП в напряжение на его входе.
0
Ну есть же индикация перегрузки в интегрирующих АЦП в мультиметрах. Во многих, по крайней мере.
Я даже приблизительно представляю реализацию.
Я надеялся, вы знаете примеры других типов АЦП с индикацией перегрузки.
0
Ну, вопросы надо понятней формулировать. Я-то подразумевал совсем не это. И вопрос понял совсем не так.
Не, таких АЦП я в МК не припомню.
0
как пересчитывать код АЦП в напряжение на его входе.
Каждому выходному коду АЦП соответствует интервал напряжения на его входе. И коду «все единицы» тоже соответствует интервал. И этот интервал доходит до Vref (но не включает его, если строго).
Если вы хотите пересчитать любой код обратно в напряжение, то вы вправе говорить об интервале «от… до...», но не сможете указать точное значение. Погрешность квантования — следствие квантования по уровню (внезапно!).

Если коротко, то я согласен с вашим мнением.
+1
Гм. В общем, да. Плюс, помнится мне, у разных АЦП еще и разные характеристики квантования бывают. Что тоже может добавить радости. Но, ковыряя даташиты для этого коммента — я даже формулы пересчета кода в напряжение не всегда находил, а характеристику и вовсе только один раз и, кажется, где-то в аппноте)
0
не соответствующий напряжению код — зашкаливает.
«Зашкаливает» — это какой код?
0
Максимальный. 2^bits-1. Незавсимо от того, какое напряжение на входе — если оно выше, чем Vref*(2^bits-1)/2^bits.
+1
Я выше даташит процитировал. Да, они в нем явно об этом и говорят.
0
делить на степень 2 гораздо проще, то что при этом будет ошибка масштаба 1-1023/1024 =0.1% AVRам без разницы там у АЦП куда больше проблемы есть.
Это не повод считать, что атмел умышленно дает некорректную (округленную) формулу. Особенно учитывая, что про ее округленность ни слова, а вот про расчет ошибок АЦП — целая простыня.
+1
В классическом CMOS коммутаторе 2 MOSFET'а
0
А зачем разделять управление мультиплексорами? Раз уж они занимают 4 аналоговых пина МК, то входы управления обоих микросхем можно было смело объединять.
Кроме того, если соединить и выходы мультиплексоров — можно обойтись двумя аналоговыми пинами на МК. Управление выводами Е микросхем при этом придется разделить, разумеется (и делать логику так, чтобы оба мультиплексора не были включены одновременно — т.е. вырубили один, врубили второй, а не наоборот).
Вместо свитча завести массив, индексируемый номером канала и содержащий состояния S0, S1, E (E1, E2 в случае объединения выходов) и ADC_CHANNEL.
0
  • avatar
  • Vga
  • 06 декабря 2014, 22:21
это понятно, хотелось увеличить быстродействие.
Тогда получится — сконфигурировать один мультиплексор->начать преобразования->сконфигурировать второй и т.д…
0
А в твоем варианте?
И сдается мне, мультиплексоры переключаются куда быстрее, чем АЦП работает.
0
ну так то хотелось )
Выводы оставались незадействоваными, решил не оставлять их пустыми.
Конечно можно было посадить S0-S1 параллельно и разделить мультиплексоры по E
0
Не, а за счет чего быстродействие-то выше? Насколько я вижу, ты все равно в каждой ветке свитча конфигурируешь все линии.
0
А не проще было взять что-то типа ADG1208 или CD4051?
0
Однажды понадобилось 16-ть каналов АЦП, при 8-ми имеющихся у MSP430G2553
Контроллер как уже указал выше — MSP430G2553, недорогой (не жирный как stm32 конечно, для своих задач более чем годится), легкодоступный.

Для данной задачи явно не годится. :) Налицо несоответствие контроллера — задаче.
Достаточно взять STM32F051R или другой MSP430 как сразу пляски вокруг мультиплексора прекратятся.
0
ну тогда цена возрастет почти в двое )
А главное зачем? Если и 2553 достаточно, тем более что 16-ть каналов АЦП в одном кристале — не так часто встречаются…
0
www.compel.ru/infosheet/TI/MSP430G2553IN20/ 2.4371 $
www.compel.ru/infosheet/ST/STM32F051R8T6/ 3.1752 $
Это из того, что есть сию на складе. Разница в цене 1,3 раза. Но это без учета цены мультиплексора, его пайки, цены за площадь платы. Это не считая ухудшения качества АЦП за счет большого внутреннего сопротивления открытого ключа. Обрати внимание, что производители нормируют сопротивление в открытом состоянии при 5 Вольтах питания. При более низких напряжениях — скромно умалчивают, хотя остальные характеристи приводят аж до 2 Вольт питалова.
16-ть каналов АЦП в одном кристале — не так часто встречаются…
Про MSP430 не скажу — давно с ними не работаю, но во всех STM32FxxxR — 16 ти канальный мультиплексор АЦП.
0
Г-ы-ы, STM32F051R8T6 за $3.175, дешевле будет взять МиландрЪ MDR32F9Q за 165 рэ.
0
Ну, ну. Даффай, даффай! Ты когда микросхемы покупал в последний раз? Я тебе привел СЕГОДНЯШНИЕ цены а ты тычешь заметкой ПОЛУТОРАГОДОВАЛОЙ давности.
А этот обрубок MSP430 за 2,5$ тебя совсем не смущает?
0
Что-то обидно стало за STM32.
ну тогда цена возрастет почти в двое )
А если присмотреться, то получается так:
www.compel.ru/infosheet/TI/MSP430G2553IN20/ 2.4371 $
www.compel.ru/infosheet/ST/STM32F100R6T6B/ 2.0854 $

Соотношение цены 0,86, экономия 16%. :) И это только на микроконтроллере.

зато у MSP430 потребление низкое
Ага. Когда спит, зубами к стенке. В реальной работе разница нивелируется практически до нуля.

гибкость и продуманость на таком уровне — что и не снилось STM
Эти сказки рассказывай где-нибудь на непрофильном сайте. :) Объясни-ка нам, как в продуманном и гибком MSP430G2553 задействовать SPI и USART, желательно одновременно.
Типичная задача — собрали данные с 16-ти каналов АЦП, запомнили лог в SPI EEPROM, передали данные в РС, при подключении к оной.

PS. Холивар предлагаю не разводить, но и огульно хаять Cortex не позволю. :)

PSPS. Я не утверждаю, что MSP430 — плохо. Самому нравится, например, MSP430AFE253. Но, в данном конкретном случае, MSP430G2553 плохо ложится на задачу.
+1
Выбранный камушек и правда не жирный. STM'ка тут сама напрашивается: недорога, доступна, удовлетворяет поставленной задаче из коробки, без доп. корпусов. К тому же разрядность АЦП выше, а режим «сканирования» каналов позволит добиться максимального быстродействия.
0
зато у MSP430 потребление низкое, а гибкость и продуманость на таком уровне — что и не снилось STM )
Начиная внутренними конденсаторами (программно выбираемыми) на кварцевый резонатор, заканчивая 4-мя независимыми источниками тактирования переферии.
Плюс Code Composer Studio очень понравился )
0
А мне весьма интересна инфа про эти CMOS-аналоговые коммутаторы, раньше их юзали из CMOS-мультиплексоров серии 74HC40(51/52/53/67), т.е. изначально цифровых чипов, как бэ не предназначенных по прямому назначению для прецизионной коммутации именно аналоговых сигналов. Сейчас новые и похожие по схемотехнике чипы уже идут под названием Analog Switch.

Какие из новых таких Hi-End чипов можно конкретно заюзать, например, в осциллографе или другой измерительной технике заместо кирзового 74HC4052 и т.п.?
0
Что-то типа ADG1208 или CD4051. Заточены под аналоговую коммутацию.
0
В измерительной технике зачастую стоят сложные входные тракты, состоящие из нескольких настраиваемых фильтров, согласующих цепей, схем самоконтроля и т.д. В подобных случаях количество аналоговых ключей может перевалить за 20 на канал. А если больше каналов? Использование коммутаторов, подобных указанным выше, потребует немалого количества ног МК. Когда то это возможно, когда то нет. Во вторых случаях целесообразно использовать ключи с SPI интерфейсом, например ADG1414. Они к тому же поддерживают подключение цепочкой, т.е. для конфигурирования тракта необходим только один SPI (3 линии).
0
Среди недорогих мультиплексоров а-ля 4052 есть 16-и-канальный 4067 (well-man2000 выше уже упомянул). И даже 74HC4067. Но соглашусь с коллегами — обычно правильнее было бы взять камень с бОльшим количеством аналоговых входов на борту. Правда бывают фичи типа встроенного обслуживания емкостных кнопок, чего может не быть в «более подходящих» чипах.
0
Кстати, есть куда более распространенный 74LVC1G3157 с аналогичной функциональностью.
0
  • avatar
  • evsi
  • 09 декабря 2014, 01:55
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.