Friday, October 22, 2021

DAC library for MCP4706, MCP4716, MCP4726 and AVR microcontrollers

This library is intended for the MCP47x6 series of DAC devices that includes MCP4706 (8-bit DAC), MCP4716 (10-bit DAC) and MCP4726 (12-bit DAC).

DAC library for MCP4706, MCP4716, MCP4726 and AVR microcontrollers

Table of Contents

MCP47x6 DAC pinout

MCP47x6 DAC pinout

1 - VOUT: this is the DAC analog output voltage. In Normal mode, the DC impedance of the output pin is about 1Ω. In Power-Down mode, the output pin is internally connected to a known pull-down resistor of 1 kΩ, 125 kΩ, or 640 kΩ. The VOUT pin can drive up to 100 pF of capacitive load in parallel with a 5 kΩ resistive load. It is recommended to use a load with RL greater than 5 kΩ. Driving large capacitive loads can cause stability problems for voltage feedback op amps.

2 - VSS: ground reference. The user must connect the VSS pin to a ground plane through a low-impedance connection. If an analog ground path is available it is highly recommended that the VSS pin be tied to the analog ground path or isolated within an analog ground plane of the circuit board.

3 - VDD: positive power supply (2.7V to 5.5V)

4 - SDA: I2C serial data pin. The SDA pin is an open-drain N-channel driver. Therefore, it needs a pull-up resistor from the VDD line to the SDA pin.

5 - SCL: I2C serial clock pin. The MCP47X6 devices act only as a slave and the SCL pin accepts only external serial clocks. The SCL pin is an open-drain N-channel driver. Therefore, it needs a pull-up resistor from the VDD line to the SCL pin.

6 - VREF: voltage reference input pin. This pin is used for the external voltage reference input. The user can select VDD voltage or the VREF pin voltage as the reference resistor ladder’s voltage reference. When the VREF pin signal is selected, there is an option for this voltage to be buffered or unbuffered. This is offered in cases where the reference voltage does not have the current capability not to drop its voltage when connected to the internal resistor ladder circuit. When the VDD is selected as reference voltage, this pin is disconnected from the internal circuit.

7* - Exposed Pad (EP): This pad is conductively connected to the device's substrate. This pad should be tied to the same potential as the VSS pin (or left unconnected). This pad could be used to assist as a heat sink for the device when connected to a PCB heat sink.

*only for the DFN package


MCP47x6 DAC schematic

MCP47x6 DAC schematic and pinout

The power supply at the VDD pin should be as clean as possible for a good DAC performance. It is recommended to use an appropriate ceramic bypass capacitor of about 100n to ground. An additional 10µF capacitor in parallel is also recommended to further attenuate high-frequency noise present in application boards. The 10uF has a DNM (Do Not Mount) because I was testing it in a battery charger and it seems to be working without it if the voltage regulator is closer to the DAC. The datasheet recommends a tantalum type but I think a ceramic will also do.

If an external voltage reference is used on VREF pin, it is recommended to have a 100n decoupling capacitor to ground. Any variation or noises on the reference source can directly affect the DAC output. The reference voltage needs to be as clean as possible for accurate DAC performance.

In Unbuffered mode, the VREF pin voltage may be from VSS to VDD. In Unbuffered mode, the voltage source should have a low output impedance. If the voltage source has a high output impedance, then the voltage on the VREF’s pin would be lower than expected. The resistor ladder has a typical impedance of 210 kΩ and a typical capacitance of 29 pF.

In Buffered mode, the VREF pin voltage may be from 0.01V to VDD-0.04V. The input buffer (amplifier) provides low offset voltage, low noise, and a very high input impedance, with only minor limitations on the input range and frequency response.

The I2C bus pull-up resistor values for SCL and SDA pins depend on the operating speed (standard, fast, and high speed) and loading capacitance of the I2C bus line. A higher value of the pull-up resistor consumes less power, but increases the signal transition time (higher RC time constant) on the bus line. Therefore, it can limit the bus operating speed. The lower resistor value, on the other hand, consumes higher power, but allows higher operating speed. If the bus line has higher capacitance due to long metal traces or multiple device connections to the bus line, a smaller pull-up resistor is needed to compensate the long RC time constant. The pull-up resistor is typically chosen between 1 kΩ and 10 kΩ ranges for Standard and Fast modes, and less than 1 kΩ for High-Speed mode.

As a rule of thumb the bus resistors can be between 4.7k to 10k for 100kHz to 400kHz, and ~700 ohm for 3.4MHz. Only two resistors are needed regardless of the number of DACs connected to the same I2C Bus.


MCP47x6 General Description

Output Buffer

The DAC output is buffered with a low power and precision output amplifier (op amp). This amplifier provides a rail-to-rail output with low offset voltage and low noise. The user can select the output gain of the output amplifier. Gain options are:

  1. Gain of 1, with either VDD or VREF pin used as reference voltage
  2. Gain of 2, only when VREF pin is used as reference voltage. The VREF pin voltage should be limited to VDD/2. When the VRL reference selection is the device’s VDD voltage, the G bit is ignored and a gain of 1 is used.

Calculating the DAC output voltage


MCP47x6  DAC output voltage formula

VRL is the reference voltage.

Resolution/Step Voltage

The Step voltage is dependent on the device resolution and the output voltage range. One LSb is defined as the ideal voltage difference between two successive codes. The step voltage can easily be calculated by using above equation where the DAC register value is equal to 1. Decreasing the reference voltage gives a smaller step voltage.

Power-Down Operation

To allow the application to conserve power when the DAC operation is not required, three Power-Down modes are available. All Power-Down modes do the following:

  • Turn off most of its internal circuits (op amp, resistor ladder, ...) 
  • Op amp output becomes high-impedance to the VOUT pin
  • Disconnects resistor ladder from reference voltage (VRL)
  • Retains the value of the volatile DAC register and Configuration bits, and the nonvolatile (EEPROM) DAC register and Configuration bits

In any of the Power-Down modes, where the VOUT pin is not externally connected (sinking or sourcing current), the power-down current will typically be 60 nA.

MCP47x6 Device I2C Address

Table 5-2 shows the eight I2C slave address options and their respective device order code.

MCP47x6 Device I2C Address

MCP47x6 DAC Library

Code example

#define F_CPU		16000000 // 16MHz CPU

#include <avr/io.h>
#include "MCP47x6.h"

int main(void){
    // Initiate I2C interface
    // Set DAC address and number of bits
    MCP47x6_SelectDAC(0b11000010, DAC_12bit);
    // Write to DAC's volatile memory
    MCP47x6_WriteVolatileDAC(4001, MCP47x6_PD_NORMAL_MODE, MCP47x6_NORMAL_MODE);


Selecting DAC device

void MCP47x6_SelectDAC(uint8_t dac_address, uint8_t dac_resolution)

Sets the DAC's address and resolution. Must be used before accessing the DAC or when switching to another DAC.

dac_address: The address of the DAC in 8 bit format like so 0b11000010. The first 7 most significant bits (MSB) corresponds to the DAC address while the 1'st bit represents R/W and it must be 0 because the software will set this bit to 0 or 1 depending if it reads or writes.

dac_resolution: DAC's resolution - 8, 10 or 12 or one of the following flags: DAC_8bit, DAC_10bit and DAC_12bit.

The I2C communication speed is set by the "twi.h" at 400kHz, the maximum bit rate supported by the ATmega328 or 324 AVR microcontrollers.

Writing the volatile DAC register

uint8_t MCP47x6_WriteVolatileDAC(dac_value, power_bits, write_mode)

This command is used to update the volatile DAC register value and the two power-down configuration bits (PD1:PD0). This command is typically used for a quick update of the analog output by modifying the minimum parameters.

uint16_t dac_value: A number from 0 to the 2^N-1 with N representing the number of bits. For example for an 8-bit DAC 2^8-1 = 255, that is the maximum DAC voltage.

uint8_t power_bits: Power down bits PD1:PD0. Can be one of the following flags:

  • MCP47x6_PD_NORMAL_MODE - Not Powered Down (Normal operation)
  • MCP47x6_PD_1K_TO_GND - VOUT is loaded with 1 k resistor to ground
  • MCP47x6_PD_125K_TO_GND - VOUT is loaded with 100 k resistor to ground
  • MCP47x6_PD_640K_TO_GND - VOUT is loaded with 500 k resistor to ground

uint8_t write_mode: Normal mode or fast mode. In fast mode the START bit and SLA+W (Slave Address) will be transmitted only once and so the DAC value can be sent multiple times with different values faster. At the end the STOP bit will terminate the transmission. Can be one of the following flags:



MCP47x6_WriteVolatileDAC(dac_value, power_bits, MCP47x6_START_FAST_MODE)
MCP47x6_WriteVolatileDAC(dac_value, power_bits, MCP47x6_FAST_MODE) - dac_value can change
MCP47x6_WriteVolatileDAC(dac_value, power_bits, MCP47x6_FAST_MODE)
MCP47x6_WriteVolatileDAC(dac_value, power_bits, MCP47x6_FAST_MODE)
MCP47x6_WriteVolatileDAC(dac_value, power_bits, MCP47x6_END_FAST_MODE)

Returns 1 if no error occurred, 0 if an error occurred.

Write volatile configuration register

uint8_t MCP47x6_VolatileConfig(uint8_t vref, uint8_t power_bits, uint8_t gain)

This Write command is used to update the volatile configuration register bits only. This command is a quick method to modify the configuration of the DAC, such as the selection of the resistor ladder reference voltage, the op amp gain, and the power-down state.

vref: Reference voltage selection bits. Can be one of the following flags:

  • MCP47x6_VREF_VDD - VDD (Unbuffered)
  • MCP47x6_VREF_PIN_UNBUFF - VREF pin (Unbuffered)
  • MCP47x6_VREF_PIN_BUFF - VREF pin (Buffered)

power_bits: see MCP47x6_WriteVolatileDAC()

gain: Gain selection bit. Can be one of the following flags:

  • MCP47x6_GAIN_1x - 1x (gain of 1)
  • MCP47x6_GAIN_2x - 2x (gain of 2). Not applicable when VDD is used as VREF

Returns 1 if no error occurred, 0 if an error occurred.

Write volatile and nonvolatile (EEPROM) memory

uint8_t MCP47x6_WriteMemory(memory_type, vref, power_bits, gain, dac_value)

This write command is used to update the volatile and nonvolatile (EEPROM) DAC register value and configuration bits. The type of memory to be written depends of the 'memory_type' parameter.

uint8_t memory_type: Select which memory to be updated: volatile or nonvolatile (EEPROM). Can be one of the following flags:

  • MCP47x6_COM_WRITE_VOL_MEMORY - volatile memory only
  • MCP47x6_COM_WRITE_ALL_MEMORY - volatile and EEPROM

uint8_t vref: see MCP47x6_VolatileConfig()

uint8_t power_bits:  see MCP47x6_WriteVolatileDAC()

uint8_t gain:  see MCP47x6_VolatileConfig()

uint16_t dac_value:  see MCP47x6_WriteVolatileDAC()

Returns 1 if no error occurred, 0 if an error occurred.

Read volatile and nonvolatile memory

uint8_t MCP47x6_Read_8bit(uint16_t bits_to_read)

Read data from volatile and nonvolatile DAC memory. Return the bit(s) specified by the "bits_to_read" parameter. This is for 8-bits devices.

bits_to_read: What bit(s) to return. Can be one of the following flags:

Volatile memory (RAM)

  • MCP47x6_VOL_RDY_BIT - ready bit: 0 if an EEPROM write is in progress, 1 otherwise
  • MCP47x6_VOL_POR_BIT - 1 if voltage is above minimum
  • MCP47x6_VOL_VREF_BITS - reference voltage
  • MsCP47x6_VOL_PD_BITS - power bits (normal or power down modes)

Nonvolatile memory (EEPROM)

  • MCP47x6_NV_RDY_BIT
  • MCP47x6_NV_POR_BIT
  • MCP47x6_NV_PD_BITS

Returns the required bit or bits. If you need to compare for their meaning, there is a list of defines inside the library file.

uint16_t MCP47x6_Read_10_12bit(uint16_t bits_to_read)

This is the same as MCP47x6_Read_8bit() but made for 10 and 12-bit devices. Note that this function is not tested because I only have an 8-bit DAC. If you can test it please confirm in the comments below if it works and that will help other users.

Convert voltage to DAC value

uint16_t MCP47x6_VoltageToValue(float voltage, float vref, uint8_t gain)

The returned value can be used as an argument to the other functions.

voltage: desired voltage

vref: voltage reference

gain: DAC op-amp gain

General call

uint8_t MCP47x6_GeneralCall(uint8_t command)

A general call transmits a command to all devices on the I2C bus. This commands allows multiple MCP47X6 devices to be reset or wake-up synchronously.

command: The command to transmit can be one of the following flags:


Resets all devices. Is similar to a Power-on Reset (POR). The contents of the EEPROM are loaded into the DAC registers and analog output is available immediately.


The device forces the volatile power-down bits to ‘00’. The nonvolatile (EEPROM) power-down bit values are not affected by this command.

Returns 1 if no error occurred, 0 if an error occurred.


Resetting the I2C interface

void TWI_ResetTWIInterface(void)

The MCP47x6 datasheet explains at page 70 how the I2C interface can be reset in case there is an error on the serial bus. This function is located inside the "twi.h" library. Resets the TWI interface by sending a START, 9 of 1's another START and a STOP.

For this function to work, the USE_INTERFACE_RESET define inside the "twi.h" must be set to 1 and then below it set the port and pins that correspond to the TWI module (0 or 1).




twi.h - to know more about the I2C library visit I2C and TWI library for AVR

No comments:

Post a Comment