CrossRoads:
You are right CS as CS, vs LDAC.
Yes, these 2 lines use the SPI hardware to shift out two bytes:
SPI.transfer ( highByte( your_data ) );
SPI.transfer ( lowByte( your_data ) );
So in total I have 4 pins - CS, LDAC, SDI (MOSI) and SCK. I found and edited a library for a similar DAC to mine a couple of days ago, which uses SPI.transfer, so I think it could work. Originally you only had to specify the CS and LDAC pins, but because I was unsure about the remaining pins, I edited it so I could choose the MOSI and SCK pins.
I will be using a Mega with my Ethernet shield, so there will be free connections for hardware SPI. Given the relatively low rate that I will be sending data to the DAC at, would it be okay to just use the same MOSI/SCK pins?
Thanks
.cpp:
// ----------------------------------------------------------------------------
// MCP4911.cpp
//
// Provides an SPI based interface to the MCP4911 single voltage output digital
// to analog converter.
//
// Author: Will Dickson, IO Rodeo Inc., edited by plusminus_
// ----------------------------------------------------------------------------
#include "Arduino.h"
#include "SPI.h"
#include "MCP4911.h"
#define ACTIVE 0b0001000000000000
#define SHUTDOWN 0b0000000000000000
#define GAIN_1X 0b0010000000000000
#define DAC_A_WRITE 0b0000000000000000
MCP4911::MCP4911() {
}
// ----------------------------------------------------------------------------
// MCP4911::MCP4911
//
// Constructor
// ----------------------------------------------------------------------------
MCP4911::MCP4911(int csPin, int ldacPin, int clkPin, int sdiPin) {
// Configure chip select and latch pins
// I think MISO can be ignored
cs = csPin;
ldac = ldacPin;
clk = clkPin;
sdi = sdiPin;
}
// ----------------------------------------------------------------------------
// MCP4911::MCP4911
//
// initialization function
// ----------------------------------------------------------------------------
void MCP4911::begin() {
pinMode(cs,OUTPUT);
pinMode(ldac,OUTPUT);
pinMode(clk,OUTPUT);
pinMode(sdi,OUTPUT);
digitalWrite(cs,HIGH);
digitalWrite(ldac,HIGH);
digitalWrite(clk,LOW);
digitalWrite(sdi,LOW);
// Set to default configuration
setGain1X_A();
}
// ---------------------------------------------------------------------------
// MCP4911::getCmdWrd
//
// Gets command word for writing value to given channel
// ---------------------------------------------------------------------------
int MCP4911::getCmdWrd(int dac, int value) {
int cmdWrd = 0;
switch (dac) {
case MCP4911_DAC_A:
cmdWrd = DAC_A_WRITE;
break;
default:
return 0;
}
cmdWrd |= gain[dac];
cmdWrd |= ACTIVE;
cmdWrd |= (0b0000111111111111 & value);
return cmdWrd;
}
// ----------------------------------------------------------------------------
// MCP4911::setValue
//
// Set the output value of the given dac channel
// ----------------------------------------------------------------------------
void MCP4911::setValue(int dac, int value) {
int cmdWrd;
uint8_t byte0;
uint8_t byte1;
// Enable SPI communications
digitalWrite(cs,LOW);
// Send command word
cmdWrd = getCmdWrd(dac,value);
byte0 = cmdWrd >> 8;
byte1 = cmdWrd & 0b0000000011111111;
SPI.transfer(byte0);
SPI.transfer(byte1);
// Disable SPI communications
digitalWrite(cs,HIGH);
// Latch value
digitalWrite(ldac,LOW);
digitalWrite(ldac,HIGH);
}
// ---------------------------------------------------------------------------
// MCP4911::setValue_A
//
// Set the output value of dac A to the given value
// ---------------------------------------------------------------------------
void MCP4911::setValue_A(int value) {
setValue(MCP4911_DAC_A, value);
}
// ---------------------------------------------------------------------------
// MCP4911::setGain1X
//
// Set the gain of the given channel to 1X
// ----------------------------------------------------------------------------
void MCP4911::setGain1X(int dac) {
if (dac == MCP4911_DAC_A) {
gain[dac] = GAIN_1X;
}
}
// ----------------------------------------------------------------------------
// MCP4911::setGain1X_A
//
// Set the gain of dac A to 1X
// ----------------------------------------------------------------------------
void MCP4911::setGain1X_A() {
setGain1X(MCP4911_DAC_A);
}
// ----------------------------------------------------------------------------
// MCP4911::off
//
// Turn off the given dac
// ----------------------------------------------------------------------------
void MCP4911::off(int dac) {
int cmdWrd = 0;
uint8_t byte0;
uint8_t byte1;
// Create shutdown cmd word.
switch (dac) {
case MCP4911_DAC_A:
cmdWrd = DAC_A_WRITE;
break;
default:
return;
}
cmdWrd |= SHUTDOWN;
// Enable SPI communications
digitalWrite(cs,LOW);
// Send command word
byte0 = cmdWrd >> 8;
byte1 = cmdWrd & 0b0000000011111111;
SPI.transfer(byte0);
SPI.transfer(byte1);
// Disable SPI communications
digitalWrite(cs,HIGH);
}
// ----------------------------------------------------------------------------
// MCP4911::off_A
//
// Turn off dac A
// ----------------------------------------------------------------------------
void MCP4911::off_A() {
off(MCP4911_DAC_A);
}
.h:
// ----------------------------------------------------------------------------
// mcp4911.h
//
// Provides an SPI based interface to the MCP4911 single voltage output digital
// to analog to converter.
//
// Author: Will Dickson, IO Rodeo Inc., edited by plusminus_
// ----------------------------------------------------------------------------
#ifndef _MCP4911_H_
#define _MCP4911_H_
#define MCP4911_NUMCHAN 1
enum MCP4911_DAC_CHAN {MCP4911_DAC_A};
class MCP4911 {
private:
int cs;
int ldac;
int clkPin;
int sdiPin;
int gain[MCP4911_NUMCHAN];
int getCmdWrd(int dac, int value);
public:
MCP4911();
MCP4911(int csPin, int ldacPin, int clkPin, int sdiPin);
void begin();
void setValue(int dac, int value);
void setValue_A(int value);
void setGain1X(int dac);
void setGain1X_A();
void off_A();
void off(int dac);
};
#endif
example sketch:
#include <SPI.h>
#include "MCP4911.h"
#define AOUT_CS 5
#define AOUT_LDAC 6
#define AOUT_CLK 7
#define AOUT_SDI 8
// For example, these will change
MCP4911 analogOut = MCP4911(AOUT_CS, AOUT_LDAC, AOUT_CLK, AOUT_SDI);
void setup() {
// Setup serial and SPI communications
Serial.begin(115200);
analogOut.begin();
// SPI.setDataMode(SPI_MODE0); - default
// SPI.setBitOrder(MSBFIRST); - default
// SPI.setClockDivider(SPI_CLOCK_DIV8); - half default speed
SPI.begin();
// Configure analog outputs
analogOut.setGain1X_A();
}
void loop() {
static int cnt=0;
analogOut.setValue_A(cnt);
cnt += 20;
if (cnt > 1023) {
cnt = 0;
}
}