Hi,
In order for this to work proper don't forget to add 2.2kOhm pull up resistors on READY and SDO pins
Connections
CLK - CLK
SDI - MOSI
SDO - MISO
CS - PB1 - pin 9
RDY - A3
Measure the resistance on terminals B1 and B2, A1 and A2 are going in the opposite way
Read the data sheet for timings and settings.
Tested on ATMega 328p @24MHz - to have a clue about the SPI speed
Code
//GROZEA Ion
//www.grozeaion.com
//Open Source, licensed under a Creative Commons Attribution-NonCommercial 3.0 License (http://creativecommons.org/licenses/by-nc/3.0/)
//License Agreement
//
//Copyright (c) 2015 GROZEA Ion (www.grozeaion.com)
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without modification,
//are permitted provided that the following conditions are met:
//
//* Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
//* Redistributions in binary form must reproduce the above copyright notice, this
// list of conditions and the following disclaimer in the documentation and/or
// other materials provided with the distribution.
//
//* The name of the copyright holder may not be used to endorse or promote
// products derived from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR
//IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
//MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
//SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
//SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
//OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
//IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
//ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//POSSIBILITY OF SUCH DAMAGE.
//Control Registers
#define CMD__NOTHING B00000000 //0 - Do nothing
#define CMD_MEM2RDAC B00010000 //1 - Restore EEMEM (A0) contents to RDAC (A0) register. See Table 16.
#define CMD_RDAC2MEM B00100000 //2 - Store wiper setting. Store RDAC (A0) setting to EEMEM (A0). See Table 15. - Use a delay of 50ms!!!
#define CMD_USER2MEM B00110000 //3 - Store contents of Serial Register Data Byte 0 and Serial Register Data Bytes 1 (total 16 bits) to EEMEM (ADDR). See Table 18.- Use a delay of 50ms!!!
#define CMD_DECRE6DB B01000000 //4 - Decrement by 6 dB. Right-shift contents of RDAC (A0) register, stop at all 0s.
#define CMD_DEALL6DB B01010000 //5 - Decrement all by 6 dB. Right-shift contents of all RDAC registers, stop at all 0s.
#define CMD_DECR1STP B01100000 //6 - Decrement contents of RDAC (A0) by 1, stop at all 0s.
#define CMD_DECA1STP B01110000 //7 - Decrement contents of all RDAC registers by 1, stop at all 0s.
#define CMD_ALL2RDAC B10000000 //8 - Reset. Refresh all RDACs with their corresponding EEMEM previously stored values. - Use a delay of 30us!!!
#define CMD_GETEMEM B10010000 //9 - Read contents of EEMEM (ADDR) from SDO output in the next frame. See Table 19. - Use a delay of 30us!!!
#define CMD_GET_RDAC B10100000 //10 - Read RDAC wiper setting from SDO output in the next frame. See Table 20. - Use a delay of 30us!!!
#define CMD_SET_RDAC B10110000 //11 - Write contents of Serial Register Data Byte 0 and Serial Register Data Byte 1 (total 10 bits) to RDAC (A0). See Table 14.
#define CMD_INCRE6DB B11000000 //12 - Increment by 6 dB: Left-shift contents of RDAC (A0),stop at all 1s. See Table 17.
#define CMD_INALL6DB B11010000 //13 - Increment all by 6 dB. Left-shift contents of all RDAC registers, stop at all 1s.
#define CMD_INCR1STP B11100000 //14 - Increment contents of RDAC (A0) by 1, stop at all 1s. See Table 15.
#define CMD_IALL1STP B11000000 //15 - Increment contents of all RDAC registers by 1, stop at all 1s.
//EEMEM No.--Address--EEMEM Content for …
//1 0000 RDAC1
//2 0001 RDAC2
//3 0010 USER1
//4 0011 USER2
//… … …
//15 1110 USER13
//16 1111 RAB1 tolerance
// Macros - Toogle this pin to repeat last command
//This is PIN9 on arduino Uno/Duemilanove
#define CS_ON PORTB |= (1<<1)
#define CSOFF PORTB &= ~(1<<1)
uint8_t myVal = 0;
void setup()
{
Serial.begin(9600);
//Setup SPI and start it
DDRB |= B0101110;//Set digital pin 10SS, 11MOSI and 13SCK as output
//See https://sites.google.com/site/qeewiki/books/avr-guide/spi for setting the SPI
SPSR = B00000000;//In my case Clock / 2 = 12Mhz is not working so i use Clock / 4
SPCR = B01010000;
DDRC &= ~(1<<0); //A3 Input - Read Status
PORTC |= B00000111;// Turn on 20K pullup on analog 0, 1, 2
CS_ON;
delay(15);
setWiper(0, 999);
setWiper(1, 333);
Serial.print("W1 Value : "); Serial.println(getWiper(0));
Serial.print("W2 Value : "); Serial.println(getWiper(1));
stepUpOne(0);
stepUpOne(1);
Serial.print("Increase W0 with 1 : "); Serial.println(getWiper(0));
Serial.print("Increase W1 with 1 : "); Serial.println(getWiper(1));
stepUpOne(0);
repeatCMD();
stepUpOne(1);
repeatCMD();
Serial.print("W1 after repeat : "); Serial.println(getWiper(0));
Serial.print("W2 after repeat : "); Serial.println(getWiper(1));
stepDownSix(0);
stepDownSix(1);
Serial.print("Decrease W0 with 6dB : "); Serial.println(getWiper(0));
Serial.print("Decrease W1 with 6dB : "); Serial.println(getWiper(1));
stepDownSix(0);
repeatCMD();
stepDownSix(1);
repeatCMD();
Serial.print("W1 after repeat -6dB: "); Serial.println(getWiper(0));
Serial.print("W2 after repeat -6dB: "); Serial.println(getWiper(1));
SPCR &= ~_BV(SPE);//End SPI
}
void loop()
{
}
void setWiper(uint8_t w, uint16_t value)
{
CSOFF;
myVal = transferData(CMD_SET_RDAC + w);
myVal = transferData(value >> 8);
myVal = transferData(value & 0xFF);
CS_ON;
}
uint16_t getWiper(uint8_t w)
{
uint16_t ret;
CSOFF;
myVal = transferData(CMD_GET_RDAC + w);
myVal = transferData(CMD__NOTHING);
myVal = transferData(CMD__NOTHING);
CS_ON;
// __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t"
// "nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t"
// "nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t"
// "nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t"
// "nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");//only 11 on this row are enought or 3.2us only for new chips at room temp
delayMicroseconds(30);
CSOFF;
myVal = transferData(CMD__NOTHING); //Discard first byte
ret = (transferData(CMD__NOTHING) << 8);
ret += transferData(CMD__NOTHING);
CS_ON;
return ret;
}
void stepUpOne(uint8_t w)
{
CSOFF;
myVal = transferData(CMD_INCR1STP + w);
myVal = transferData(CMD__NOTHING);
myVal = transferData(CMD__NOTHING);
CS_ON;
}
void stepDownSix(uint8_t w)
{
CSOFF;
myVal = transferData(CMD_DECRE6DB + w);
myVal = transferData(CMD__NOTHING);
myVal = transferData(CMD__NOTHING);
CS_ON;
}
void repeatCMD()//See page 21 in manual Another subtle feature of the AD5235 is that a subsequent CS strobe, without clock and data, repeats a previous command
{
CSOFF;
CS_ON;
}
uint8_t transferData(uint8_t data)
{
SPDR = data;// send the data
while(!(SPSR & (1<<SPIF))) // wait until transmission is complete
;
return SPDR;
}