Апр 262013
 

Когда-то, еще совсем недавно, я частенько заказывал бесплатные образцы (сэмплы) у известной американской компании Analog Devices. И регулярно курьер привозил заказанные микросхемы, даже не все еще пришлось пустить в дело, а накопил уже достаточно. Одно время по необходимости заказывал различные операционные усилители, здесь и rail-to-rail, и различные малошумящие и прецизионные усилители. Всяческие DC преобразователи с изолированными цепями управления по разным интерфейсам, USB интерфейсы с гальванической развязкой и т.д. Все это лежит в фирменных коробочках и ждет своего часа. А недавно, перебирая эти запасы, наткнулся на микросхему AD5242 и подумал, а почему бы не внедрить в одно из устройств эти цифровые потенциометры, чтобы управление и цифровыми и аналоговыми цепями шло от одного микроконтроллера. Для начала решил подключить AD5242 к STM32, сделать пробную заготовку программы управления цифровым потенциометром, “пощупать” эту связку осциллографом и мультиметром, а затем уже внедрить эту микросхему в цепь обратной связи операционного усилителя для регулировки коэффициента усиления с помощью цифровых посылок от микроконтроллера. Ниже изложу описание устройства микросхем AD5241 и AD5242, принципов их работы в моем понимании, а также поделюсь результатами эксперимента.

Самый обычный переменный резистор имеет подвижный контакт, при перемещении которого изменяется сопротивление. В цифровом потенциометре нет механических частей, а изменение сопротивления среднего вывода резистора относительно крайних задается цифровым способом, потенциометр принимает байт данных, содержимое которого и определяет “положение” среднего контакта этого переменного резистора. К примеру, у моего резистора сопротивление 10кОм, с помощью одного байта данных можно “перемещать” средний вывод этого резистора от одного крайнего вывода к другому, меняя содержимое байта данных от 0 до 255.

Digital Potentiometer

 
Устройство и параметры микросхем AD5241 и AD5242.

Разница между этими двумя микросхемами только в количестве цифровых потенциометров: у AD5241 он один, а в составе AD5242 их два.

Функциональная схема

Обе микросхемы принимают данные по интерфейсу I2C. В данной статье не будет описания этого распространенного интерфейса, поскольку в интернете можно найти множество подробных инструкций и разобраться с основными принципами его работы несложно.

В документации приведены различные варианты возможного применения этих цифровых потенциометров. Вот, к примеру, две схемы с операционными усилителями, где цифровой потенциометр используется в цепи обратной связи. Таким образом, коэффициент усиления можно изменять посылкой кодовых слов от микроконтроллера.

Инвертирующий усилитель:

Инвертирующий усилитель

Неинвертирующий усилитель:

Неинвертирующий усилитель

Для тех, кто имеет представление об интерфейсе I2C, разобраться с форматом управляющих посылок не составит особого труда. К моему удивлению, когда была собрана схема и написана небольшая тестовая программа управления для микроконтроллера STM32, все заработало как надо сразу же после включения питания. Нечасто так бывает, даже неинтересно без поиска собственных ошибок, опечаток и вдумчивого чтения документации.

Вот какой формат управляющих посылок должен быть у этих потенциометров:

Формат посылки

S – старт

Байт адреса:

01011 – неизменная часть адреса для устройств данного типа

AD1:AD0 – переменная часть адреса. Служит для выбора конкретной микросхемы при адресации от устройства “мастера”. Эта часть адреса задается подключением выводов микросхемы AD1, AD0 к нужным логическим уровням 0 или 1. Можно подключать напрямую к GND или VDD без всяких резисторов. У меня оба этих вывода подключены к GND.

R/W – направление передачи данных. 0 – запись данных в микросхему, 1 – чтение данных из микросхемы.

A – подтверждение. Микросхема цифрового потенциометра подтверждает устройству-“мастеру”, что она опознала свой адрес и готова к приему/передаче данных.

Байт инструкции:

A/B – выбор цифрового резистора. 0 – RDAC1, 1 – RDAC2 (см. схему выше)

RS – установка положения потенциометра в середине шкалы. Для такого случая бит должен быть установлен – “1”.

SD – “спящий” режим, устанавливается, когда бит равен “0”

O1, O2 – управление логическими уровнями на одноименных выводах

X – не используется, состояние этого бита может быть любым

A – подтверждение. Микросхема цифрового потенциометра подтверждает устройству-“мастеру”, что она приняла байт инструкции

Байт данных:

D7:D0 – значения этого байта от 0 до 255 и задают положение “среднего контакта” цифрового потенциометра

A – подтверждение. Микросхема цифрового потенциометра подтверждает устройству-“мастеру”, что она приняла байт данных

P – стоп

На рисунке изображена временная диаграмма сигналов шины I2C для случая записи данных в регистр RDAC

Запись данных

 

и последующего чтения данных из этого же регистра

Чтение данных

Для точного расчета сопротивления, соответствующего определенной величине байта данных служит следующая формула

Формула сопротивления

Rwb – сопротивление между выводом “подвижного контакта” W и конечным выводом цифрового потенциометра B.

D – данные, записанные в регистр RDAC, могут быть от 0 до 255.

Rab – полное сопротивление цифрового резистора между выводами A и B.

Rw – сопротивление “подвижного контакта”. Фактически это сопротивление внутренних ключей схемы (см. рисунок ниже)

Схема подключений внутренних резисторов

В моем случае (Rab = 10кОм) зависимость сопротивления от данных, записанных в регистр, выглядит так:

Код_сопротивление

Сопротивление ключей Rw или “сопротивление подвижного контакта” равно 60 Ом.

Итак, запитав микросхему AD5242 непосредственно от платы STM32-DISCOVERY и подключив шину I2C, набросал код управления и запустил проект. Здесь важный нюанс в том, что напряжение на выводах выходного резистора должно быть не больше напряжения питания. Меньше можно, а больше нет. Поэтому выводы резистора A1 и B1 также подключил к VDD и GND соответственно. Далее, меняя значение передаваемого байта данных, наблюдал за изменением напряжения на выводе W1 относительно GND.

0x00:

0x80:

0xFF:

Осциллограмма в линиях SDA (канал 1 — желтый) и  SCL (канал 2 — синий)

All

Код программы для микроконтроллера приведен ниже. В данном случае был использован микроконтроллер STM32F103, но и для платы STM32VL-DISCOVERY код должен подойти без изменений. Для серии STM32L придется немного “допилить” в части инициализации выводов порта и альтернативных функций.

#include "stm32f10x.h"

#define slave_address   0x58 //Адрес микросхемы
#define control_word    0x07 //Байт инструкции

uint8_t resistance = 0x80; //Сопротивление 0x00..0xFF - 0Ом..10кОм

GPIO_InitTypeDef    GPIO_InitStructure;
I2C_InitTypeDef     I2C_InitStructure;

int main()
{
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
	
  GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_6 | GPIO_Pin_7);//PB6 - I2C1_SCL, PB7 - I2C1_SDA
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
	
  I2C_Cmd(I2C1, ENABLE);
  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
  I2C_InitStructure.I2C_OwnAddress1 = slave_address;
  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
  I2C_InitStructure.I2C_ClockSpeed = 15000;
  I2C_Init(I2C1, &I2C_InitStructure);
  I2C_Cmd(I2C1, ENABLE);
	
  I2C_GenerateSTART(I2C1,ENABLE);
  while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));
  I2C_Send7bitAddress(I2C1, slave_address, I2C_Direction_Transmitter);
  while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
  I2C_SendData(I2C1, control_word);
  while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));	
  I2C_SendData(I2C1, resistance);
  while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));	
  I2C_GenerateSTOP(I2C1, ENABLE);
	
  while(1);
}

  6 Responses to “Цифровой потенциометр AD5241/AD5242”

  1. Скажите AD5242 сдвоенный резистор — два одновременно изменяются или можно программно задать разные величины, или ставить две AD5241 на разные ноги МК? из того что я понял можно посылать команды шине I2S А В 1/0 выбор резистора.

    SHDN что это вход или выход что он делает?
    O1 O2 для чего
    AD0 AD1 подключая к 1 или 0 что прописать в шине I2S 1й или 2й биты?

    Хочу управлять (МК АТмега 8 — AD5242), задача изменять напряжение 0-10v в двух каналах независимо.

    • Здравствуйте, Николай! У AD5242 нельзя управлять одновременно двумя резисторами, нужно выбирать в командах инструкции к какому именно обращаться. Выше в статье это указано, там где рассматривается формат посылок.
      SHDN — это вход. Низкий уровень на этом входе моментально соединяет «подвижный» контакт W с выводом B. Рекомендуется подключать этот вывод к плюсовому выводу питания Vdd, если не предусмотрено его использование.
      AD0, AD1 — это выбор адреса микросхемы, их может быть несколько на одной шине.
      На выводах O1 и O2 вроде бы должны быть цифровые значения, переданные в регистры соответствующих сопротивлений, я сейчас уже точно не помню.
      Выкладываю у себя datasheet на данную микросхему, вот ссылка http://chipspace.ru/archives/AD5241_5242.pdf

      • Здравствуйте.
        А можно ли подключить не 4, а больше, цифровых потенциометров AD5280 на одной I2C и управлять ими по отдельности. Там я смотрю 2 контакта AD0 и AD1 означает ли это что больше 4 независимых подключить нельзя?

        • И каково быстродействие цифровых потенциометров? Т.е после отправки в него значения с микроконтроллера сколько времени должно пройти чтобы на выходе установилось требуемое сопротивление? Микросекунд:…?

        • Только 4 возможных адреса, совершенно верно.
          Точных данных о величине задержки между окончанием приема посылки и установкой сопротивления, к сожалению, в документации не увидел. Может быть пропустил, посмотрите datasheet.

  2. Все также делаю, все те же настройки, только на ассемблере. Да вот только не получается у меня, SCL дает такты, а вот SDA не в какую не хочет передавать данные. Может кто разбирается, помогите пожалуйста
    ;———-настройка I2C—
    SETUP_I2C BCF STATUS, RP1
    BSF STATUS, RP0 ;переходим в 1 банк
    BSF SSPSTAT, SMP ;скрость i2c 100кгц
    MOVLW 0X00
    MOVWF SSPCON2 ;чистим управл регистр
    MOVLW 0X09 ;заносим коэф деления
    MOVWF SSPADD ;заносим коэф деления
    BCF STATUS, RP0 ;переходим в 0 банк
    BSF SSPCON, SSPM3
    BSF SSPCON, SSPEN ;включение mssp
    BSF STATUS, RP0 ;переходим в 1 банк
    BCF PIE1, SSPIE
    BCF PIE2, BCLIE
    BCF STATUS, RP0 ;переходим в 0 банк
    BCF PIR1, SSPIF
    BCF PIR2, BCLIF
    RETURN
    ;————проверяем свободна ли шина—
    I2C_FREE BSF STATUS, RP0 ;переходим в 1 банк
    BCF STATUS, RP1 ;переходим в 1 банк
    BCF STATUS, Z
    BTFSC SSPSTAT, R_W ;проверяем не идет ли передача данных по шине
    GOTO I2C_FREE
    MOVLW 0X1F
    ANDWF SSPCON2, 0
    BTFSS STATUS, Z
    GOTO I2C_FREE
    RETURN
    ;———-START—
    START_I2C CALL I2C_FREE
    BCF STATUS, RP1 ;переходим в 1 банк
    BSF STATUS, RP0 ;переходим в 1 банк
    BSF SSPCON2, SEN ;формируем бит START
    BCF STATUS, RP0 ;переходим в 0 банк
    START_I2C_RETURN
    BTFSS PIR1, SSPIF ;прпустить если SSPIF=1
    GOTO START_I2C_RETURN
    BCF PIR1, SSPIF
    RETURN
    ;———-STOP—
    STOP_I2C CALL I2C_FREE
    BCF STATUS, RP1 ;переходим в 1 банк
    BSF STATUS, RP0 ;переходим в 1 банк
    BSF SSPCON2, PEN ;формируем бит STOP
    BCF STATUS, RP0
    STOP_I2C_RETURN
    BTFSS PIR1, SSPIF ;прпустить если SSPIF=1
    GOTO STOP_I2C_RETURN
    BCF PIR1, SSPIF
    RETURN
    ;———-посылаем байт—
    SEND_BAIT
    CALL I2C_FREE
    BCF STATUS, RP0 ;переходим в 0 банк
    BCF STATUS, RP1 ;переходим в 0 банк
    MOVF 0X70, 0
    MOVWF SSPBUF
    BCF PIR1, SSPIF
    SEND_BAIT_WAIT_SSPIF
    BTFSS PIR1, SSPIF ;прпустить если SSPIF=1
    GOTO SEND_BAIT_WAIT_SSPIF
    BCF PIR1, SSPIF
    BSF STATUS, RP0 ;переходим в 1 банк
    SEND_BAIT_WAIT_ACKSTAT
    BTFSC SSPCON2, ACKSTAT ;прпустить если ACKSTAT=0
    GOTO SEND_BAIT_WAIT_ACKSTAT
    RETURN
    ;———-модуль I2C—
    SEND_I2C_RESULT
    CALL SETUP_I2C
    CALL START_I2C
    MOVLW 0X5E
    MOVWF 0X70
    CALL SEND_BAIT
    MOVLW 0X07
    MOVWF 0X70
    CALL SEND_BAIT
    CALL STOP_I2C