I am currently trying to write to an LTC1660CN DAC via SPI. I have managed to get all of the code in place to send the message as I want in terms of order and detail, but am struggling when it comes to byte size. The LTC1660 needs a 16 bit message, but my SPI sends it as two 8 bit messages.
/*
DAC Control - M0 Pro edition
This example controls Linear Technology's LTC1660 DAC.
The DAC has 8 channels.
The LTC1660 is SPI-compatible and to command it you essentially send three bytes -
one with the address of the register (4-bit), one with the value for the
register (10-bit), and two 'don't care' bits (2-bit).
The circuit:
* An LED and a 220-ohm resisor in series connected from each DAC(A-H) pin to ground
* CS - to digital pin 10 (SS pin)
* Din - to outermost central ICSP pin (MOSI pin)
* SCK - to innermost central ICSP pin (SCK pin)
* Vdd - to +5V
* REF - to +5V
* CLR - to +5V
* GND - to ground
*/
//include the SPI library:
#include <SPI.h>
//set pin 10 as the slave select for the DAC:
const int slaveSelectPin = 10;
void setup() {
//set the slaveSelectPin as an output
pinMode (slaveSelectPin, OUTPUT);
//initialise SPI:
SPI.begin();
}
void loop() {
//run through all of the addresses (they are addressed from binay 1 to binary 8):
for (int address = 1; address < 9; address++){
//for each address, scale up through every value in the DAC:
for (int value = 0; value < 1024; value++){
int a = address << 4 | value >> 4;
int v = value << 2;
DACWrite(a, v);
delay(10);
}
}
}
void DACWrite(int address, int value){
SPI.beginTransaction(SPISettings(5000000, MSBFIRST, SPI_MODE0));
//take the SS pin low to select the chip:
digitalWrite(slaveSelectPin, LOW);
//send the address, value and don't care to
SPI.transfer(address);
SPI.transfer(value);
//take the SS pin high to de-select the chip:
digitalWrite(slaveSelectPin, HIGH);
SPI.endTransaction();
}
The aim of this is just to test the DAC and get used to operating it/how to interact with it, so that I might use it in more advance situations later in my work. For now it should control the LEDs so that they scale up from 0-5V in 1024 equal steps.
Also, here is an image of the logic analyser results, which lets me know it is almost there:
(it's the word attachment to this post)
Is there any way to take out this gap in the messages sent so that it appears like it should in the datasheet?
BJHenry:
I guess that you haven't seen before, but you can use SPI.transfer16() to send 16 bits.
Unfortunately, I have. I tried to send it as that, but got a very similar result on the logic analyser - it sent as 2 bytes. Sorry for forgetting to mention!
To double check I was doing it correctly, this is what I wrote for that:
void DACWrite(int address, int value){
SPI.beginTransaction(SPISettings(5000000, MSBFIRST, SPI_MODE0));
//take the SS pin low to select the chip:
digitalWrite(slaveSelectPin, LOW);
//send the address, value and don't care to
//SPI.transfer(address);
//SPI.transfer(value);
SPI.transfer16(address|value);
//take the SS pin high to de-select the chip:
digitalWrite(slaveSelectPin, HIGH);
SPI.endTransaction();
}
Is this incorrect? I am extremely new to Arduino, let alone SPI, so wouldn't be too surprised if it is wrong. I am just combining the bytes, as was in "int a" (my code above).
I guess that you haven't seen before, but you can use SPI.transfer16() to send 16 bits.
Which is doing exactly the same, sending two 8bit values one after the other.
Is there any way to take out this gap in the messages sent so that it appears like it should in the datasheet?
Does the datasheet state that there must be no gap in the timing? I doubt. That's a correct 16bit transfer and I'm sure the chip is happy with it.
BTW: Never, never post a picture inside a MS Word file, otherwise we have to assume you're trying to infect us with malware. There are standardized graphic formats (JPEG, PNG) everybody can read without a greater risk, so there's absolutely no need to use proprietary formats best known for their worst security record.
pylon:
Which is doing exactly the same, sending two 8bit values one after the other.
Does the datasheet state that there must be no gap in the timing? I doubt. That's a correct 16bit transfer and I'm sure the chip is happy with it.
BTW: Never, never post a picture inside a MS Word file, otherwise we have to assume you're trying to infect us with malware. There are standardized graphic formats (JPEG, PNG) everybody can read without a greater risk, so there's absolutely no need to use proprietary formats best known for their worst security record.
Thank you for the first piece of information - that's useful knowing that it essentially does the same thing. With my very limited knowledge on the topic (though I am trying to learn), can you think of anything else I might be able to try in terms of transferring the data? I've been at this for a couple of days, and have got pretty close, imo, but this doesn't quite seem to be working.
Regarding it being able to put two bytes in, you are undoubtedly correct, as it uses a shift register on the DI terminal.
Unfortunately I am on my work computer, so there is every reason to send it on a word document. Work are really strict about the software on the pcs, and I couldn't do it another way. sigh I fully appreciate where you're coming from though, so thank you for the forewarning for future posts. I did try to just copy the image into the box, but it wouldn't paste, understandably.
chamsta:
Regarding it being able to put two bytes in, you are undoubtedly correct, as it uses a shift register on the DI terminal.
Indeed. For many "input-only" SPI devices, gaps during transmission doesn't matter as long as you keep the CS line pulled low. If the clock stops, the shift register simply stops sampling bits.
Usually when you let go high the CS line is where the device actually latches the data. If it latches the data, you'll have to shift out all 16 bits again the next time.
Ah, that'd make sense, thank you. In which case, there must just be an error somewhere in how I'm sending my message to the device. I might take this post over to /programming and see if they have a solution. Thank you all for your help so far! Please, if anyone else can see an error in the programming, don't hesitate to post on here. I will be extremely grateful!
void DACWrite(int address, int value){
SPI.beginTransaction(SPISettings(5000000, MSBFIRST, SPI_MODE0));
//take the SS pin low to select the chip:
digitalWrite(slaveSelectPin, LOW);
//send the address, value and don't care to
//SPI.transfer(address);
//SPI.transfer(value);
SPI.transfer16(address|value);
WTF? Why are address and value ints? Why do you think that oring them is a good idea?
1. I would recommend just to test the functionality of only one channel (DACA) and then extend the idea for simultaneous check of all the DACs at the same time using for() loop.
2. Operate the DAC at a SCK rate less than 5 MHz as the 5 MHz (as per data sheet) spec is the design value and not a tested value. I would recommend 125 kbit/sec (125000).
3. I would recommend to use DPin-8 other than SS/-pin (DPin-10) to drive the CS/-LD pin of the DAC as the DAC requires that CS/-LD pin should be at LL during active period of SCK and LH to latch the data.
4. Look at the following diagram and form the data frame on a piece of paper before entering them in the sketch.
5. Formation of 16-bit integrated data from Step-4a/b/c so that the bits are aligned with Fig-1
int x1 = 0x0001; //address of DACA (lower 4-bit)
x1 = x1 << 12; // x1 = 0001 0000 0000 0000 (now upper 4-bit is DACA address)
int x2 = 0x01FF; //0000 0001 1111 1111 (lower 10-bit is DACA value (arbitrary)
x2 = x2 << 2; //0000 0111111111 00 (DACA value is shifted left by 2-bit to take care of X1 X0)
//--We want: A3 A2 A1 A0 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 X1 X0---------
x1 = x1 | x2; //x1 = 0001 0111111111 00 = 16-bit
6. Transfer x1 of Step-5 using SPI Bus
pinMode(8, OUTPUT); //DPIn-8 will be connected with CS/-LD pin of the DAC instead of DPin-10(SS/).
digitalWrite(8, LOW); //allow the SCK to be active in the DAC
SPI.transfer(highByte(x1));
SPI.transfer(lowByte(x1));
digitalWrite(8, HIGH); //latch 16-bit data into DACA
digitalWrite(8, LOW);
7. Execute your program for DACA only. Connect a DVM at Pin-2 of the DAC. Check that there is some DC voltage. Change the content of x2 variable of Step-5; re-run the program; check that the reading of DVM changes.