Taking data in from sensor and sending to 18-bit DAC over SPI

Hello,

Ive got a MAX 5318 18 bit DAC. im trying to take data from a digital sensor and send it to the DAC. I have it to where i can send a fixed number and i see a change in the output of the DAC. The DAC requires 24 bits (4 register address bits | 18 data bits | 2 "dont care" bits) [3 bytes sent]. The data coming in is 8 bits for one sensor and 16 bits for the other sensor (2 different applications) and needs to be converted to an 18 bit number to be sent to the DAC. I thought the map function would take care of this but it doesnt seem to work. how would i accomplish this?

Please post your code! And use code tags!

Cleaned it up here it is

#define RESET 8

#define RDY 9

#define MZ 5

#define BUSY 6

#define LDAC 7

#define MOSI 12

#define MISO 11

#define SS 10

#define SCLK 13

#define TCSB 4

#define PD 3

#define DGND 2

 

#include <SPI.h>

#include <avr/io.h>

 



byte SensorData;

String binnum;

byte wordnum;

byte address;

unsigned int Wdata;

String DataString;

uint32_t DACOut_val;

int a, n;

 

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

 

void setup() {

  Serial.begin(57600);

  pinMode(RDY , INPUT);

  pinMode(MISO , INPUT);

  pinMode(MOSI , OUTPUT);

  pinMode(RESET , OUTPUT);

  pinMode(MZ , OUTPUT);

  pinMode(BUSY , INPUT);

  pinMode(LDAC , INPUT);

  pinMode(TCSB , OUTPUT);

  pinMode(PD , OUTPUT);

  pinMode(SCLK , OUTPUT);

  pinMode(SS , OUTPUT);

  pinMode(DGND , OUTPUT);

 

  digitalWrite(SS, HIGH);

  digitalWrite(RESET, HIGH);

  digitalWrite(SS, HIGH);

  delay(10);

 

  digitalWrite(SS, LOW);

  SPI.begin();

  SPI.beginTransaction(SPISettings(16000000, MSBFIRST, SPI_MODE1));

  SPCR |= (1 << MSTR);               // Set as Master

  SPCR |= (1 << SPR0) | (1 << SPR1); // divided clock by 128

  SPCR |= (1 << SPE);                // Enable SPI

 digitalWrite(RESET, HIGH);  // Set high for normal operation

  digitalWrite(MZ, LOW);      // Set output Voltage to midscale

  digitalWrite(TCSB, LOW);    // Set low for Straight Binary format or high for Two's Complement

  digitalWrite(PD, LOW);      // Set low for normal operation or high for Power Down mode

  digitalWrite(DGND, LOW);    // Set low for digital ground

 

 //  General Configuration Write Register (0x4)

  digitalWrite(SS, LOW);      // Set Slave Select LOW to begin data transfer

  SPI.transfer(0b01000111);   // Write first data byte

  SPI.transfer(0b10000000);   // Write second data byte

  SPI.transfer(0b00000000);   // Write third data byte

  digitalWrite(SS, HIGH);     // Set Slave Select HIGH to end data transfer

 

  //  GAIN Write Register (0x3)

  digitalWrite(SS, LOW);      // Set Slave Select LOW to begin data transfer

  SPI.transfer(0b00111111);   // Write first data byte

  SPI.transfer(0b11111111);   // Write second data byte

  SPI.transfer(0b11111100);   // Write third data byte

  digitalWrite(SS, HIGH);     // Set Slave Select HIGH to end data transfer

 

  //  OFFSET Register Write in Two's Complement (0x2)

  digitalWrite(SS, LOW);      // Set Slave Select LOW to begin data transfer

  SPI.transfer(0b00100000);   // Write first data byte

  SPI.transfer(0b00000000);   // Write second data byte

  SPI.transfer(0b00000000);   // Write third data byte

  digitalWrite(SS, HIGH);     // Set Slave Select HIGH to end data transfer

 

  //  Straight Binary DIN Write Register (TCSB = 0) (0x1)

  digitalWrite(SS, LOW);      // Set Slave Select LOW to begin data transfer

  SPI.transfer(0b00010000);   // Write first data byte

  SPI.transfer(0b00000000);   // Write second data byte

  SPI.transfer(0b00000000);   // Write third data byte

  digitalWrite(SS, HIGH);     // Set Slave Select HIGH to end data transfer

 

  // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

}

 

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

 

void loop() {


 

  while (1) {

    address = (0b0001);  // Write Register Address

    address = address * 16;

    SensorData = n;


    n++;

    if (n > 255) {

      n = 0;

    } 

    DACOut_val = map(SensorData, 0, 255, 0, 0x3FFFC); // Convert 8 bit to 18 bit

    byte First4bits = DACOut_val & 245760; // Grab first 4 bits

    byte Second8bits = DACOut_val & 16320; // Grab the following 8 bits

    byte Third6bits = DACOut_val & 63;     // Grab the last 6 bits

 

    Serial.print("DAC Out "); Serial.print(DACOut_val, BIN);

    Serial.print(",First4bits,"); Serial.print(First4bits, BIN);

    Serial.print(",Second8bits,"); Serial.print(Second8bits, BIN);

    Serial.print(",Third6bits,"); Serial.print(Third6bits, BIN);

    Serial.print(",n,"); Serial.println(n);

 

    byte FirstPart = highByte(DACOut_val >> 2);

    byte nib = FirstPart;     //the byte to split

    byte niblow = nib & 15;   //bitwise AND of nib and 0000 1111

    byte nibhigh = nib & 240; //bitwise AND of nib and 1111 0000

    byte FirstByte = (address | nibhigh);

    byte SecondPart = highByte(DACOut_val >> 2);

    byte ThirdPart =  lowByte(DACOut_val);

 

    byte Data1 = FirstByte;

    byte Data2 = SecondPart;

    byte Data3 = ThirdPart;

 

    digitalWrite(SS, LOW);  // Set Slave Select LOW to begin data transfer

    SPI.transfer(Data1);    // Write first data byte

    SPI.transfer(Data2);    // Write second data byte

    SPI.transfer(Data3);    // Write third data byte

    digitalWrite(SS, HIGH); // Set Slave Select HIGH to end data transfer

  }

}
  SPI.begin();
  SPI.beginTransaction(SPISettings(16000000, MSBFIRST, SPI_MODE1));
  SPCR |= (1 << MSTR);               // Set as Master
  SPCR |= (1 << SPR0) | (1 << SPR1); // divided clock by 128
  SPCR |= (1 << SPE);                // Enable SPI

Either use the SPI library or do direct register manipulations but doing both in a wild mix ends in disaster.

On which type of Arduino are you running that sketch? For AVR processors you’ll never reach 16MHz with SPI, 8MHZ is the max you can reach.

  pinMode(DGND , OUTPUT);

Connecting DGND to a GPIO is quite dangerous. If for any reason you put that to HIGH even for a short time may destroy that chip because any LOW on any of the other pins will be a negative signal (-5V) for the chip which is way outside it’s specification. Just connect that pin to GND.

void loop() {
 
  while (1) {

You definitely don’t need the while(1) loop.

    DACOut_val = map(SensorData, 0, 255, 0, 0x3FFFC); // Convert 8 bit to 18 bit
    byte First4bits = DACOut_val & 245760; // Grab first 4 bits
    byte Second8bits = DACOut_val & 16320; // Grab the following 8 bits
    byte Third6bits = DACOut_val & 63;     // Grab the last 6 bits

That won’t work as a byte variable cannot hold the output of a boolean and operation with longs.

Write this code as:

    byte First4bits = SensorData >> 4;
    byte Second8bits = SensorData << 4;
    byte Third6bits = 0;
    byte FirstByte = address | First4bits;
    byte SecondByte = Second8bits;
    byte ThirdByte = Third6bits;

This can be written with code more compact but this way you probably see how it works.

    SensorData = n;
    n++;
    if (n > 255) {
      n = 0;
    }

A remark that you fake sensor data should be in a comment here.

THANK YOU! It works as expected now. Output gradually steps from 0V to 5V. Again thank you for taking the time to go through my code and help me out. You are awesome.