Hi,
I am trying to communicate with an AD9174 DAC evaluation board (AD9174-FMC-EBZ) using an Arduino Mega as an SPI master.
Hardware Setup
Arduino Mega 2560
AD9174-FMC-EBZ
Board powered from external 12 V supply
Onboard PIC disabled according to Analog Devices instructions
SPI connected through header P3
Connections:
D53 -> CS
D52 -> SCK
D51 -> MOSI
D50 -> MISO
Common ground between Arduino and board
Arduino outputs are level-shifted from 5 V to approximately 3.3 V using resistor dividers.
SPI Settings
SPI.beginTransaction(
SPISettings(1000000, MSBFIRST, SPI_MODE0));
I also tested MODE1, MODE2, and MODE3 with identical results.
Verification Already Performed
Arduino SPI loopback test works correctly:
D51 connected to D50
TX=0xA5, RX=0xA5
Analog Devices confirmed that the P3 header can be used for direct SPI access.
Read/Write Functions
void ad9174_write(uint16_t reg, uint8_t data)
{
uint16_t cmd = reg & 0x7FFF;
digitalWrite(DAC_CS, LOW);
SPI.transfer((cmd >> 8) & 0xFF);
SPI.transfer(cmd & 0xFF);
SPI.transfer(data);
digitalWrite(DAC_CS, HIGH);
delayMicroseconds(10);
}
uint8_t ad9174_read(uint16_t reg)
{
uint16_t cmd = 0x8000 | reg;
digitalWrite(DAC_CS, LOW);
SPI.transfer((cmd >> 8) & 0xFF);
SPI.transfer(cmd & 0xFF);
uint8_t value = SPI.transfer(0x00);
digitalWrite(DAC_CS, HIGH);
return value;
}
Issue
Every register read returns:
0x00
including after executing the vendor-recommended initialization sequence.
Does the Arduino SPI implementation above look correct for a device using a 16-bit register address plus 8-bit data?
Any suggestions would be appreciated.
ec2021
June 9, 2026, 10:49am
2
Hi @pjfrwieonv !
There are two issues the AI (I know ... but it's the quickest possibility to search for hints) points out:
Check SPI voltage level at MEGA and the board (level shifter required?)
The board starts SPI in 3 wire mode and must be switched to 4 wire mode
On request the AI produced a code that it claims to be useful ... I cannot evaluate it.
To my experience AI output usually lacks without corrections but it may contain hints where to look ...
I do not overestimate its usefulness so feel free to have a look ... or directly throw it into the electronic garbage bin ...
#include <SPI.h>
// --- Hardware Pin Definitions ---
const int dac_cs = 10; // Chip Select pin
const int dac_reset = 9; // Hardware Reset Pin (optional but highly recommended)
// --- SPI Settings ---
// The AD9174 SPI interface supports clock speeds up to 80 MHz.
// Uses MSB First and SPI Mode 0 (or Mode 3 depending on clock edge preferences).
SPISettings dacSpiSettings(10000000, MSBFIRST, SPI_MODE0);
// --- Low-Level SPI Functions ---
void ad9174_write(uint16_t reg, uint8_t data) {
uint16_t cmd = reg & 0x7FFF; // Bit 15 = 0 for Write operation
SPI.beginTransaction(dacSpiSettings);
digitalWrite(dac_cs, LOW);
SPI.transfer((cmd >> 8) & 0xFF); // Address MSB
SPI.transfer(cmd & 0xFF); // Address LSB
SPI.transfer(data); // Data payload
digitalWrite(dac_cs, HIGH);
SPI.endTransaction();
delayMicroseconds(1);
}
uint8_t ad9174_read(uint16_t reg) {
uint16_t cmd = 0x8000 | reg; // Bit 15 = 1 for Read operation
uint8_t value = 0;
SPI.beginTransaction(dacSpiSettings);
digitalWrite(dac_cs, LOW);
SPI.transfer((cmd >> 8) & 0xFF); // Address MSB
SPI.transfer(cmd & 0xFF); // Address LSB
value = SPI.transfer(0x00); // Read incoming data via dummy byte
digitalWrite(dac_cs, HIGH);
SPI.endTransaction();
return value;
}
// --- Full Step-by-Step Initialization Sequence ---
bool ad9174_init() {
pinMode(dac_cs, OUTPUT);
digitalWrite(dac_cs, HIGH);
// Step 1: Hardware Reset (Ensures clean register state)
if (dac_reset >= 0) {
pinMode(dac_reset, OUTPUT);
digitalWrite(dac_reset, LOW);
delay(10); // Hold reset low for 10ms
digitalWrite(dac_reset, HIGH);
delay(20); // Wait for boot-up stabilization
}
// Step 2: SPI Interface Configuration (Force 4-Wire Mode)
// Write 0x3C to Reg 0x000 establishes a software reset and enables
// independent MOSI/MISO paths (4-wire SPI communication).
ad9174_write(0x000, 0x3C);
delay(5);
// Step 3: Verify SPI Communication (Read Product ID Check)
// The AD9174 contains a static silicon ID across registers 0x004 to 0x006.
uint8_t chip_id_l = ad9174_read(0x004);
uint8_t chip_id_h = ad9174_read(0x005);
if (chip_id_l == 0x00 && chip_id_h == 0x00) {
// SPI communication failed or device is not responding
return false;
}
// Step 4: Power up Clock Receiver Circuitry
ad9174_write(0x091, 0x00); // Powers up the internal analog clock receiver
// Step 5: Power down Unused JESD Circuits & Configure Data Links
// Depending on whether single link or dual link modes are required:
ad9174_write(0x300, 0x01); // Enable Link 0 (Change to 0x03 if using Dual Links)
// Step 6: JESD204B Mode Setup (Example: Configure Interpolation & Modulator)
// These configurations vary depending on required lane rates and interpolation.
ad9174_write(0x110, 0x12); // Example: 2x Channel Interpolation, 4x Main Interpolation
ad9174_write(0x596, 0x0C); // Enable TXEN (Transmit Enable) digital data pipelines
// Step 7: Execute Internal Calibration Routines
// The AD9174 requires triggering internal state machine calibrations
// to align internal clock paths and analog current mirrors safely.
ad9174_write(0x0dd, 0x00); // Initialize delay line calibrations
ad9174_write(0x0de, 0x7c);
ad9174_write(0x1a0, 0x80); // Enable numeric processing clocks
ad9174_write(0x1a0, 0xc0); // Toggle calibration tracking execution
delay(10); // Allow calibration loop to stabilize
return true; // Initialization completely successful
}
void setup() {
Serial.begin(115200);
SPI.begin();
if (ad9174_init()) {
Serial.println("AD9174 Initialized Successfully in 4-Wire Mode.");
} else {
Serial.println("Hardware Error: AD9174 Communication Failed!");
}
}
void loop() {
// Dynamic runtime tasks go here (e.g. updating NCO frequencies)
}
Good luck!
ec2021
Please post the picture of the board.
Post signal signatures of header P3 of your dev board.
Have you tried another CS pin? D53 on a Mega sets whether the device is a master or slave.
jim-p
June 9, 2026, 2:03pm
5
No it does not.
DAC_CS is never defined.
Where is SPI.begin() ?
Arduino outputs are level-shifted from 5 V to approximately 3.3 V using resistor dividers.
Not the best way to do it for a 1MHz clock, the resistors will affect rise/fall times.
Can you post an annotated schematic showing how you wired this project. Include links to technical information on the hardware devices. Be sure to show power sources.
As someone (I'm assuming it's you) has already asked the same question on the Analog site I'm sure you'll get the correct answer right from the horse's mouth, so to speak.
https://ez.analog.com/data_converters/high-speed_dacs/f/q-a/604653/how-to-use-the-p3-port-on-ad9174-to-perform-register-read-write
@pjfrwieonv
Follow the works of the following link. There are few advices.
Have you read the datasheet?
https://www.analog.com/media/en/technical-documentation/data-sheets/ad9174.pdf
(165 pages so quite a thick one).
Page 32 ++ describes the communication protocol.
How it works depends on bits set (or not) in register 0x000
If those bits are not set correctly the command / register selection etc might be invalid.
No time to study the datasheet myself, sorry.