AD7840 14 bit DAC with Arduino

 Today I decided to test the AD7840 14 bit DAC that I had bought long time ago for telephone project. I wanted to learn, utilize it and perhaps incoporate to build independent communication system with Arduino AM transmitter and Arduino AM receiver. This DAC IC could be used to generate carrier signal but I am not sure and today I am testing this. Also one question is whether there is any real benefit to use external DAC because Arduino can generate sine wave in PWM mode or CTC mode by using external filter.

The AD7840 DAC IC pinout and internal block diagram is shown below.

AD7840 14 bit DAC

This DAC supports both serial and parallel data transfer from the microcontroller or microprocessor. But the parallel interface is troublesome to make on breadboard and also takes lot of Arduino pins. Luckily it supports the serial data transfer using the SPI protocol also called the 3 wire interface. 

Pin Connections between Arduino Nano and AD7840 DAC:

Here’s how to connect the AD7840 to the Arduino Nano using SPI:

  1. AD7840 Pins:

    • VDD: Connect to 5V (or 3.3V, depending on the DAC version).

    • GND: Connect to Ground (GND).

    • SCLK (Serial Clock): Connect to Pin 13 (Arduino Nano, SCK).

    • SDI (Serial Data Input): Connect to Pin 11 (Arduino Nano, MOSI).

    • CS (Chip Select): Connect to Pin 10 (Arduino Nano).

    • LDAC (Load DAC): Connect to Ground (Optional, can be controlled to update DAC data manually).

    • VOUT: Connect to the analog output where you want the analog signal.

  2. Arduino Nano Pins:

    • Pin 13: SCK (Serial Clock) – Connect to AD7840 SCLK.

    • Pin 11: MOSI (Master Out Slave In) – Connect to AD7840 SDI.

    • Pin 10: CS (Chip Select) – Connect to AD7840 CS.

    • Pin A0: (Optional) You can use an analog input pin to control the DAC output, for example, reading from a potentiometer.

I liked to draw and do circuit simulation in Proteus whenever possible, but there was no AD7840 part in Proteus and I didn't find any it's spice model on the internet. So I used the AD5640 DAC IC which is also 14-bit DAC and supports SPI interface and was the closet part to AD7840. 
Below is the circuit diagram of SPI interfacing of Arduino with the external DAC SPI.

Arduino External DAC SPI Interfacing Circuit Diagram

Arduino Nano Code to Generate a Sine Wave (using SPI to interface with AD7840):

 The following Arduino code generates sine wave data and sends to external DAC.

#include <SPI.h>

// Pin for DAC Chip Select (CS)
const int dacCS = 10;  // Pin 10 as chip select for DAC (e.g., AD7840)

// Sine wave lookup table (values between 0 and max DAC value, depending on resolution)
const uint16_t sineTable[] = {
  2047, 2286, 2502, 2685, 2837, 2953, 3032, 3073,
  3073, 3032, 2953, 2837, 2685, 2502, 2286, 2047
};

const int dacBits = 14;          // Set your DAC resolution here (12, 14, 16, etc.)
const int sineFrequency = 1000;  // Target sine wave frequency in Hz
const int samplesPerCycle = sizeof(sineTable) / sizeof(sineTable[0]);

unsigned long previousMicros = 0;   // Time of previous sample
unsigned long intervalMicros = 0;   // Microsecond interval between samples
int sampleIndex = 0;

void setup() {
  SPI.begin();
  pinMode(dacCS, OUTPUT);
  digitalWrite(dacCS, HIGH); // Deactivate DAC

  // Optional: adjust SPI settings here if needed
  SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));

  Serial.begin(9600);
  
  intervalMicros = 1000000UL / (sineFrequency * samplesPerCycle); // microseconds between samples
}

void loop() {
  unsigned long now = micros();
  if (now - previousMicros >= intervalMicros) {
    previousMicros = now;

    writeDAC(sineTable[sampleIndex], dacBits);

    sampleIndex++;
    if (sampleIndex >= samplesPerCycle) sampleIndex = 0;
  }
}

// Send data to DAC (with adjustable resolution)
void writeDAC(uint32_t value, uint8_t bits) {
  uint8_t msb_width = 8;
  uint8_t lsb_width = bits - msb_width;
  uint8_t msb = value >> lsb_width;
  uint8_t lsb = value & ((1 << lsb_width) - 1);

  digitalWrite(dacCS, LOW);
    SPI.transfer(msb);
    SPI.transfer(lsb << (8 - lsb_width));  // Left-justify LSB
  digitalWrite(dacCS, HIGH);
}

How to use the program:

  • Just change dacBits to match your DAC (e.g., 12, 14, or 16).

  • Ensure your sineTable[] values are scaled to match the maximum value for that DAC:

    • 12-bit DAC → max = 4095

    • 14-bit DAC → max = 16383

    • 16-bit DAC → max = 65535

Simulation Video

See the simulation video of how the AD7840 14 bit DAC works with Arduino.

You now have a diy Arduino based flexible sine wave generator with SPI support for any common N-bit DAC which you can use for communication projects. I want to make Arduino AM transmitter and receiver.

Post a Comment

Previous Post Next Post