MCP4726の使い方

MCP4726はI2Cで通信制御するD/A変換です。 MCP4726のコマンド覚書▽マニュアルはこちら を参照して下さい。秋月電子の該当ページはこちらにあります。

わかりにくいですが、下の写真の赤矢印で示した白丸が1番ピンです。



回路図は以下の通りです。D/A変換は、VSSからVDDの範囲で行われます。VREFは使いませんでした。 VREFを使う場合は、VSSからVREFの範囲でD/A変換が行われます。ただし、VREF <= VDD でなければなりません。



揮発性 DAC レジスタ書き込み

基本的にはこのモードで書き込めば欲しい電圧を得る事ができます。 出力電圧は12ビット0から4095 (0x000 - 0xFFF)で指定します。 最小限のパラメータ変更によってアナログ出力を手早く更新する時に使います

1:01100000
2:00PD1PD0B11B10B9B8
3:B7B6B5B4B3B2B1B0

下のプログラムの場合、書き込んだ2byteで0x800を表しています。
5v × (0x800/0xFFF) ≒ 2.5v が出力されます。

PD0, PD1についてはのコンフィグレーションを参照して下さい。

Wire.setClockは、I2C通信のクロックスピードを設定しています。 このデバイスはファーストモード400kHzにも対応しています。この行がない場合は100kHzの標準モードで動作します。

// include the I2C library:
#include <Wire.h>
    
void setup() {
  // デバイスアドレス(スレーブ)
  uint8_t DEVICE_ADDRESS=0x60;

  // マスタとしてI2Cバスに接続する
  Wire.begin();
  Wire.setClock(400000);  // I2C First Mode
  delay(100);
  
  Wire.beginTransmission(DEVICE_ADDRESS);
  Wire.write(B00001000);  //0x08  PD==0/PD1=0
  Wire.write(B00000000);  //0x00
  Wire.endTransmission();
}
揮発性メモリ書き込み

揮発性の DAC レジスタの値とコンフィグレーション ビットの更新に使います。EEPROM はこのコマンドの影響を受けません。

1:01100000
2:010VREF1VREF0PD1PD0G
3:B11B10B9B8B7B6B5B4
4:B3B2B1B0

全メモリ書き込み

揮発性と不揮発性(EEPROM)のDACレジスタの値とコンフィグレーションビットの更新に使います。 不揮発性レジスタは、電源を入れた瞬間に所定の電圧を出したい時に使います。

1:01100000
2:011VREF1VREF0PD1PD0G
3:B11B10B9B8B7B6B5B4
4:B3B2B1B0

以下のプログラムは電源投入時にVDDと同じ電圧を出力する設定です。

// include the I2C library:
#include <Wire.h>

void setup() {
  // デバイスアドレス(スレーブ)
  uint8_t DEVICE_ADDRESS = 0x60;  // B01100000

  // マスタとしてI2Cバスに接続する
  Wire.begin();
  Wire.setClock(400000);  // I2C First Mode
  delay(100);

  Wire.beginTransmission(DEVICE_ADDRESS);
  Wire.write(B01100000); //全メモリ書き込み, VREF1/0=0 PD1/0=0 G=0
  Wire.write(B11111111); //FFH
  Wire.write(B11110000); //F0H
  Wire.endTransmission();
}

揮発性コンフィギュレーションの書き込み

揮発性コンフィグレーションレジスタビットだけを更新する場合に使います。

1:01100000
2:100VREF1VREF0PD1PD0G

読み出しコマンド

このコマンドは、デバイスの全メモリを読み出します。読み出されるデータは、揮発性と不揮発性 (EEPROM)のDACレジスタの値とコンフィグレーション ビット、揮発性のステータスビットです。

1:01100000

  Wire.requestFrom(DEVICE_ADDRESS, 8);
  while(Wire.available())  {
    unsigned char c = Wire.read();      // 1バイトを受信
    Serial.print(c,HEX);
    Serial.print(" ");
  }
  Serial.println(" ");

受信結果

1:110VREF1VREF0PD1PD0G
2:RAM B11-B08
3:RAM B7-B000
4:E0H
5:ROM B11-B08
6:ROM B7-B000

コンフィギュレーションビット

パワーダウン・ビットと出力抵抗性負荷

PD1PD0動作
00通常動作
011kΩ抵抗を介してグランドに接続
10125kΩ抵抗を介してグランドに接続
11640kΩ抵抗を介してグランドに接続

ゲイン選択ビット

G動作
0x1 ( ゲイン 1)
12x ( ゲイン 2)。VRL として VDD を使う場合は適用されません。
VREF = VDD とした場合、デバイスはゲイン選択ビット (G) の設定に関係なくゲイン =x1 のみを使用します。




抵抗ラダー参照電圧 (VRL) 選択ビット

VREF0VREF1動作
0xVDD ( バッファなし )
01VREF ピン ( バッファなし )
10


サンプルプログラム

ノコギリ波を発生するサンプルプログラムです。 loopが回る度にregの値をインクリメントしD/A変換に設定しています。

#include <Wire.h>   // include the I2C library:
uint8_t DEVICE_ADDRESS = 0x60;  // B01100000

void setup() {
  Wire.begin();           //Connect I2C bus
  Wire.setClock(400000);  // I2C First Mode
  delay(100);
}

uint16_t reg=0;

void loop() {
  Wire.beginTransmission(DEVICE_ADDRESS);
  Wire.write((reg>>8)&0x0F);
  Wire.write(reg&0xFF);
  Wire.endTransmission();
  reg++;
  reg&=0xFFF;
}

出力波形は以下のようになりました。だいたい0.47secが1周期になります。 0.47secで4096点インクリメントしていますので、だいたい100usecごとにloopが処理されていることがわかります。 ただし、この結果は16MHzで動作しているArduino Microでの結果です。



Arduino Due(84MHz)で同じプログラムを動作させてみました。1周期は0.3secでした。思ったほどは早くなりませんでした。 I2Cという通信方法が遅いためと思われます。