0

I am using a Mega 2560 and 2 x AD9833 programmable waveform generators.

The AD9833's use a SPI protocol and I have used vwlowen's code as a jumping off point (I'm not usng the display just the generators). I added a channel variable to select the slave device.

It all works fine until I try to add a second AD9833. I saw this post about more than 1 peripheral using SPI & a Mega, that says I can use any pin for slave selection (SS) but the following code only ever works if I use pin 53. The upshot if which is that I can send the same data to both i.e. both share the same SS pin as long as that pin is 53. Any other SS pin selection is ignored by the devices. I tried pin 49 for both & no change, I''ve tried 53 & 49 yet only the device on 53 changes.

So what's going on here? What's so special about pin 53 that it cant be replicated by another output pin?

/*
Amended code for AD9833 Waveform Module originally from vwlowen.co.uk
Common SPI terminology & pinout on AD9833
MOSI - DATA
SCLK - CLK
SS   - FSYNC 
MISO - not implemented i.e. ther is no MISO pin on the AS9833 
*/

#include <SPI.h>


const int SINE     = 0x2000;                // Define AD9833's waveform register value.
const int SQUARE   = 0x2028;                // When we update the frequency, we need to
const int TRIANGLE = 0x2002;                // define the waveform when we end writing.    

const float refFreq = 25000000.0;           // On-board crystal reference frequency

const int FSYNCA = 53;                       // Standard SPI pins for the AD9833 waveform generator.
//const int FSYNCB = 49;
const int CLK    = 52;                       // CLK and DATA pins.
const int DATA   = 51;

unsigned long freq = 1000;                   // Set initial frequency.


void setup() { 
  
  pinMode(FSYNCA, OUTPUT);
  // pinMode(FSYNCB, OUTPUT);

  SPI.begin();
  SPI.setDataMode(SPI_MODE2);
  delay(50); 
  
  AD9833reset();                                   // Reset AD9833 module after power-up.
  delay(50);
  AD9833setFrequency(freq, SQUARE, FSYNCA);        // Set the frequency and Sine Wave output
 // AD9833setFrequency(freq, SINE, FSYNCB);
 
}


void loop() {
  
// TODO: PC control via USB
  
}


// AD9833 documentation advises a 'Reset' on first applying power.
void AD9833reset() {
  WriteRegister(0x100, FSYNCA);   // Write '1' to AD9833 Control register bit D8.
  delay(10);
 // WriteRegister(0x100, FSYNCB);
 // delay(10);
}

// Set the frequency and waveform registers in the AD9833.
void AD9833setFrequency(long frequency, int Waveform, int channel) {

  long FreqWord = (frequency * pow(2, 28)) / refFreq;

  int MSB = (int)((FreqWord & 0xFFFC000) >> 14);    //Only lower 14 bits are used for data
  int LSB = (int)(FreqWord & 0x3FFF);
  
  //Set control bits 15 ande 14 to 0 and 1, respectively, for frequency register 0
  LSB |= 0x4000;
  MSB |= 0x4000; 
  
  WriteRegister(0x2100, channel);   
  WriteRegister(LSB, channel);                  // Write lower 16 bits to AD9833 registers
  WriteRegister(MSB, channel);                  // Write upper 16 bits to AD9833 registers.
  WriteRegister(0xC000, channel);               // Phase register
  WriteRegister(Waveform, channel);             // Exit & Reset to SINE, SQUARE or TRIANGLE

}


void WriteRegister(int dat, int channel) {      
  
  digitalWrite(channel, LOW);         // Set FSYNC low before writing to AD9833 registers
  delayMicroseconds(10);              // Give AD9833 time to get ready to receive data.
  
  SPI.transfer(highByte(dat));        // Each AD9833 register is 32 bits wide and each 16
  SPI.transfer(lowByte(dat));         // bits has to be transferred as 2 x 8-bit bytes.

  digitalWrite(channel, HIGH);        //Write done. Set FSYNC high
}
1

What's so special about pin 53

Pin 53 is the slave select pin of the SPI peripheral. As such it has a bearing on how the SPI peripheral operates.

It is intimately tied to the master/slave operation in that when it's an input SPI works in slave mode, and when it's an output it runs in master mode.

So to use SPI in master mode, whether you use pin 53 or not, it must be in OUTPUT for SPI to work at all.

There is nothing much wrong with your methodology, but one thing is missing: the initial state of the chip select pins.

You should always start with all chip select pins disabled (i.e., HIGH) rather than in an unknown (probably low - I'd have to check the datasheet) state - the exception might be pin 53 which SPI might itself set HIGH for you.

So if you add:

digitalWrite(FSYNCA, HIGH);
digitalWrite(FSYNCB, HIGH);

right after setting the pinMode for your pins and still use both pins 53 and 49 then it should work.

1
  • 1
    SPI.begin() sets the SS pin (53) as output and HIGH – Juraj Dec 9 '20 at 12:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.