MCP4725 and MBed LPC1768 example

In this example we will connect an MCP4725 Digital-to-Analog Converter to a MBed LPC1768

MCP4725 is a single channel, 12-bit, voltage output Digital-to-Analog Converter with integrated EEPROM and an I2C Compatible Serial Interface.

The MCP4725 DAC offers integrated non-volatile memory (EEPROM) which allows DAC register and configuration bit values to be saves at powered off. The VREF pin or the device VDD can be selected as the DAC’s reference voltage. Power-Down modes enable system current reduction when the DAC output voltage is not required. These devices are available in small 6-pin SOT-23 packages.

Features

12-Bit Resolution
On-Board Non-Volatile Memory (EEPROM)
±0.2 LSB DNL (typ)
External A0 Address Pin
Normal or Power-Down Mode
Fast Settling Time of 6µs (typ)
External Voltage Reference (VDD)
Low Power Consumption
Single-Supply Operation: 2.7V to 5.5V
Standard (100 kbps), Fast (400 kbps) and High Speed (3.4 Mbps) Modes
Extended Temperature Range: -40°C to +125°C

Parts List

Label Part Type
MBED1 mbed
Part1 Adafruit MCP4725 Breakout Board – 12-Bit DAC

Layout

 

Code

This example uses the MBed compiler, you will need to imprt the library and example from https://os.mbed.com/components/MCP4725-12-Bit-Digital-to-Analog-Convert/

#include <stdbool.h>
#include "mbed.h"
#include "mcp4725.h"
 
/**
 * A test suite for the MCP4725 DAC Library. This Test Application requires the following:
 *  * An MCP4725 connected to the IC2 bus of the mbed LPC1768.
 *  * The analog out of the MCP1768 connected to Pin15 (analog in) of the mbed LPC1768.
 *  * An optional LED & resistor connected to analog output for visual feedback of the running tests.
 *
 * This application tests the MCP4725 library's setting of the MCP4725's internal registers (inclusing eeprom storage), 
 * it's analog output and power modes.
 *
 */
 
Serial pc(USBTX, USBRX);
AnalogIn analogIn(p15);
 
void test_mcp4725_library(PinName sda, PinName scl, MCP4725::BusFrequency bus_frequency, int device_address_bits, char* testName);
int  test_init(MCP4725* interface, char* testName);
int  test_simple_read_write_no_eeprom(MCP4725* interface, enum MCP4725::PowerMode mode, float output_voltage);
int  test_simple_read_write_with_eeprom(MCP4725* interface, enum MCP4725::PowerMode mode, float output_voltage);
int  test_eeprom_write_status(MCP4725* interface);
 
int main()
{
    pc.printf("Application for testing the MCP4725 interface library\r\n");
 
    test_mcp4725_library(p9, p10, MCP4725::Standard100kHz,  0, "p9, p10, MCP4725::Standard100kHz");
    test_mcp4725_library(p9, p10, MCP4725::Fast400kHz,      0, "p9, p10, MCP4725::Fast400kHz");
    test_mcp4725_library(p9, p10, MCP4725::HighSpeed3_4Mhz, 0, "p9, p10, MCP4725::HighSpeed3_4Mhz");
 
}
 
 
 
/** Run a set of simple tests on the mcp4725 driver.
     * 
     * @param sda I2C data line pin
     * @param scl I2C clock line pin
     * @param bus_frequency the frequency at which the I2C bus is running.
     * @param device_address_bits The 3bit address bits of the device.
     */
void test_mcp4725_library(PinName sda, PinName scl, MCP4725::BusFrequency bus_frequency, int device_address_bits, char* testName)
{
    //Create our instance of the interface for test
    MCP4725 mcp4725_interface(sda, scl, bus_frequency, device_address_bits);
 
    if(test_init(&mcp4725_interface, testName) == 0)
    {
        test_simple_read_write_no_eeprom(&mcp4725_interface, MCP4725::Normal, 3.0);
        test_simple_read_write_no_eeprom(&mcp4725_interface, MCP4725::PowerDown1k, 1.3);
        test_simple_read_write_no_eeprom(&mcp4725_interface, MCP4725::PowerDown100k, 1.8);
        test_simple_read_write_no_eeprom(&mcp4725_interface, MCP4725::PowerDown500k, 0.5);
        test_simple_read_write_no_eeprom(&mcp4725_interface, MCP4725::Normal, 2.5);
 
        test_simple_read_write_with_eeprom(&mcp4725_interface, MCP4725::Normal, 3.0);
        test_simple_read_write_with_eeprom(&mcp4725_interface, MCP4725::PowerDown1k, 1.3);
        test_simple_read_write_with_eeprom(&mcp4725_interface, MCP4725::PowerDown100k, 1.8);
        test_simple_read_write_with_eeprom(&mcp4725_interface, MCP4725::PowerDown500k, 0.5);
        test_simple_read_write_with_eeprom(&mcp4725_interface, MCP4725::Normal, 2.5);
 
        test_eeprom_write_status(&mcp4725_interface);
    }
 
 
}
 
/** Initialise the device registers & eeprom. */
int test_init(MCP4725* interface, char* testName)
{
    int result;
    pc.printf("Initialising test '%s': ", testName);
 
    //Prime the device, including its eeprom.
    result = interface->write(MCP4725::Normal, 0, true);
    if(result == 0)
    {
        wait(0.5);
        pc.printf("OK\r\n");
    }
    else
    {
        pc.printf("FAILED: %d\r\n", result);
    }
 
    return result;
}
 
/* Run a simple read/write test that does not write to eeprom. */
int test_simple_read_write_no_eeprom(MCP4725* interface, enum MCP4725::PowerMode mode, float output_voltage)
{
    enum MCP4725::PowerMode read_mode;
    enum MCP4725::PowerMode read_mode_eeprom;//, write_mode_eeprom;
    int  read_dac_value;
    int  read_dac_value_eeprom;//, write_dac_value_eeprom;
    bool read_eeprom_write_in_progress;
 
    int dac_value = (int) (0xFFF * (output_voltage/3.3) );
 
    pc.printf("\tRead/write test without write to eeprom: ");
 
    interface->write(mode, dac_value, false);
    interface->read(&read_mode, &read_mode_eeprom, &read_dac_value, &read_dac_value_eeprom, &read_eeprom_write_in_progress);
    if( (mode != read_mode) || (dac_value != read_dac_value) || (read_eeprom_write_in_progress == true) || (read_dac_value == read_dac_value_eeprom) )
    {
        pc.printf("Failed - mode=%d, read_mode=%d, dac_value=%d, read_dac_value=%d, eeprom_write_state:%d\r\n", (int)mode, (int)read_mode, dac_value, read_dac_value, read_eeprom_write_in_progress);
        return 1;
    }
    else
    {
        // We need to wait a short period for the output to stabalise.
        wait(0.2);
 
        /* We check at mV resolution. 
         * Resolution of 12bit DAC is 0.8mV
         * Resolution of 16bit ADC is 0.05mV
         */
        int read_value_mv = (analogIn.read() * 3.3) * 100;
        int set_value_mv = ((int)(output_voltage*100));
 
        if( (mode == MCP4725::Normal) && (read_value_mv !=  set_value_mv) )
        {
            pc.printf("Failed: set_value=%dmV, read_value=%dmV\r\n", read_value_mv, set_value_mv);
            return 1;
        }
        else if ( (mode != MCP4725::Normal) && (read_value_mv != 0) )
        {
            pc.printf("Failed: read_value=%dmV, but DAC in PowerDown!\r\n", read_value_mv);
            return 1;
        }
        else
        {
            pc.printf("Passed\r\n");
            return 0;
        }
    }
}
 
 
/* Run a simple read/write test that does write to eeprom. */
int test_simple_read_write_with_eeprom(MCP4725* interface, enum MCP4725::PowerMode mode, float output_voltage)
{
    enum MCP4725::PowerMode read_mode;
    enum MCP4725::PowerMode read_mode_eeprom;//, write_mode_eeprom;
    int  read_dac_value;
    int  read_dac_value_eeprom;//, write_dac_value_eeprom;
    bool read_eeprom_write_in_progress;
    int dac_value = (int) (0xFFF * (output_voltage/3.3) );
 
    pc.printf("\tRead/write test with write to eeprom: ");
 
    interface->write(mode, dac_value, true);
 
    wait(0.5); //Wait a short period for the eeprom write to complete.
    interface->read(&read_mode, &read_mode_eeprom, &read_dac_value, &read_dac_value_eeprom, &read_eeprom_write_in_progress);
 
    if( (mode != read_mode) || (dac_value != read_dac_value) || (read_eeprom_write_in_progress == true) || (read_dac_value != read_dac_value_eeprom) || (read_mode != read_mode_eeprom) )
    {
        pc.printf("Failed - mode=%d, read_mode=%d, dac_value=%d, read_dac_value=%d, eeprom_write_state:%d\r\n", (int)mode, (int)read_mode, dac_value, read_dac_value, read_eeprom_write_in_progress);
        return 1;
    }
    else
    {
        pc.printf("Passed\r\n");
        return 0;
    }
}
 
/** Test to see if the eeprom write status bit is reported correctly. */
int test_eeprom_write_status(MCP4725* interface)
{
    enum MCP4725::PowerMode read_mode;
    enum MCP4725::PowerMode read_mode_eeprom;//, write_mode_eeprom;
    int  read_dac_value;
    int  read_dac_value_eeprom;//, write_dac_value_eeprom;
    bool read_eeprom_write_in_progress;
 
    pc.printf("\tTest eeprom write status: ");
 
    interface->write(MCP4725::Normal, 4095, true);
 
    //Immediately read the device
    interface->read(&read_mode, &read_mode_eeprom, &read_dac_value, &read_dac_value_eeprom, &read_eeprom_write_in_progress);
 
    if( read_eeprom_write_in_progress == false )
    {
        pc.printf("Failed - EEPROM Write not reported as in progress.\r\n");
        return 1;
    }
    else
    {
        wait(0.5); //Wait a short period for the eeprom write to complete.
        interface->read(&read_mode, &read_mode_eeprom, &read_dac_value, &read_dac_value_eeprom, &read_eeprom_write_in_progress);
 
        if( read_eeprom_write_in_progress == false )
        {
            pc.printf("Passed\r\n");
            return 0;
        }
        else
        {
            pc.printf("Failed - EEPROM Write reported as still in progress.\r\n");
            return 1;
        }
    }
}

Testing

Using a terminal program such as TeraTerm you will see something like this

Application for testing the MCP4725 interface library
Initialising test ‘p9, p10, MCP4725::Standard100kHz’: OK
Read/write test without write to eeprom: Failed: set_value=298mV, read_value=300mV
Read/write test without write to eeprom: Passed
Read/write test without write to eeprom: Passed
Read/write test without write to eeprom: Failed: read_value=1mV, but DAC in PowerDown!
Read/write test without write to eeprom: Failed: set_value=249mV, read_value=250mV
Read/write test with write to eeprom: Passed
Read/write test with write to eeprom: Passed
Read/write test with write to eeprom: Passed
Read/write test with write to eeprom: Passed
Read/write test with write to eeprom: Passed
Test eeprom write status: Passed
Initialising test ‘p9, p10, MCP4725::Fast400kHz’: OK
Read/write test without write to eeprom: Failed: set_value=299mV, read_value=300mV
Read/write test without write to eeprom: Passed
Read/write test without write to eeprom: Passed
Read/write test without write to eeprom: Passed
Read/write test without write to eeprom: Failed: set_value=248mV, read_value=250mV
Read/write test with write to eeprom: Passed
Read/write test with write to eeprom: Passed
Read/write test with write to eeprom: Passed
Read/write test with write to eeprom: Passed
Read/write test with write to eeprom: Passed
Test eeprom write status: Passed
Initialising test ‘p9, p10, MCP4725::HighSpeed3_4Mhz’: FAILED: 1

 

Links

MCP4725 I2C DAC Breakout Boards