Go Down

Topic: SPI-transfer trouble Using SPIEEPROM as example (Read 6727 times) previous topic - next topic

Panteraa

Dec 14, 2010, 01:05 pm Last Edit: Dec 14, 2010, 01:06 pm by panteraa Reason: 1
Hi, I need a SPI-connection between the arduino and a DDS-chip. The DDS chip generates a signal with an adjustable frequency and phase. The frequency and phase is determined by a frequency or phase word which will be send through the SPI-connection. So I'm trying to write something easy to start, but I can't get it too work. I've read the datasheet and SPCR is OK. I thought that the compiler would recognize the function spi_transfer, which he don't. Since I absolutely have no clue, I wonder how I could send the byte DATA_H_MSB2 through the SPI connection.

Ty for reading.

My code:
Code: [Select]
#define DATAOUT 11
#define SPICLOCK 13//sck
#define FSYNC 12 //LOW=readmode for the DDS

byte DATA_H_MSB2;

void setup(){
  DATA_H_MSB2=00100011;
   
  Serial.begin(9600);
  digitalWrite(FSYNC, HIGH);
  pinMode(DATAOUT, OUTPUT);
  pinMode(SPICLOCK,OUTPUT);
  pinMode(FSYNC, OUTPUT);
 
  SPCR = (1<<SPE) |(1<<MSTR) | (1<<CPHA);  
  delay(300);
 
  digitalWrite(FSYNC, LOW);
  spi_transfer(DATA_H_MSB2);
  digitalWrite(FSYNC,HIGH);
  delay(100);
 
}

void loop(){}


Playground link for the SPIEEPROMhttp://
http://www.arduino.cc/en/Tutorial/SPIEEPROM


Here's the code:

Code: [Select]
#define DATAOUT 11//MOSI
#define DATAIN  12//MISO
#define SPICLOCK  13//sck
#define SLAVESELECT 10//ss

//opcodes
#define WREN  6
#define WRDI  4
#define RDSR  5
#define WRSR  1
#define READ  3
#define WRITE 2

byte eeprom_output_data;
byte eeprom_input_data=0;
byte clr;
int address=0;
//data buffer
char buffer [128];

void fill_buffer()
{
 for (int I=0;I<128;I++)
 {
   buffer[I]=I;
 }
}

char spi_transfer(volatile char data)
{
 SPDR = data;                    // Start the transmission
 while (!(SPSR & (1<<SPIF)))     // Wait the end of the transmission
 {
 };
 return SPDR;                    // return the received byte
}

void setup()
{
 Serial.begin(9600);

 pinMode(DATAOUT, OUTPUT);
 pinMode(DATAIN, INPUT);
 pinMode(SPICLOCK,OUTPUT);
 pinMode(SLAVESELECT,OUTPUT);
 digitalWrite(SLAVESELECT,HIGH); //disable device
 // SPCR = 01010000
 //interrupt disabled,spi enabled,msb 1st,master,clk low when idle,
 //sample on leading edge of clk,system clock/4 rate (fastest)
 SPCR = (1<<SPE)|(1<<MSTR);
 clr=SPSR;
 clr=SPDR;
 delay(10);
 //fill buffer with data
 fill_buffer();
 //fill eeprom w/ buffer
 digitalWrite(SLAVESELECT,LOW);
 spi_transfer(WREN); //write enable
 digitalWrite(SLAVESELECT,HIGH);
 delay(10);
 digitalWrite(SLAVESELECT,LOW);
 spi_transfer(WRITE); //write instruction
 address=0;
 spi_transfer((char)(address>>8));   //send MSByte address first
 spi_transfer((char)(address));      //send LSByte address
 //write 128 bytes
 for (int I=0;I<128;I++)
 {
   spi_transfer(buffer[I]); //write data byte
 }
 digitalWrite(SLAVESELECT,HIGH); //release chip
 //wait for eeprom to finish writing
 delay(3000);
 Serial.print('h',BYTE);
 Serial.print('i',BYTE);
 Serial.print('\n',BYTE);//debug
 delay(1000);
}

byte read_eeprom(int EEPROM_address)
{
 //READ EEPROM
 int data;
 digitalWrite(SLAVESELECT,LOW);
 spi_transfer(READ); //transmit read opcode
 spi_transfer((char)(EEPROM_address>>8));   //send MSByte address first
 spi_transfer((char)(EEPROM_address));      //send LSByte address
 data = spi_transfer(0xFF); //get data byte
 digitalWrite(SLAVESELECT,HIGH); //release chip, signal end transfer
 return data;
}

void loop()
{
 eeprom_output_data = read_eeprom(address);
 Serial.print(eeprom_output_data,DEC);
 Serial.print('\n',BYTE);
 address++;
 if (address == 128)
   address = 0;
 delay(500); //pause for readability
}


CrossRoads

I used SPI with another device, it seemed pretty straight forward.

You need this in the code before void setup()
#include <SPI.h>
// SPI uses hardware Chip Select (SS in this example) vs having device address

and this to actually send out data:

 digitalWrite(SS,LOW);  // take the SS pin low to select the chip
 // I was sending 2 bytes out, an address,
 SPI.transfer(SHUTDOWN_ADDRESS);    
 // and some data
 SPI.transfer(0x00);      
 digitalWrite(SS,HIGH);   // take the SS pin high to de-select the chip
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

bosley

I'm interested in this as well.  It looks like there are some SPI setups to take care of. e.g. Clock divider, bit order, etc.  Does anyone know what it defaults to if the bits in the SPCR register are not set up?

Thanks,
-Ryan

CrossRoads

#3
Jan 24, 2011, 01:17 am Last Edit: Jan 24, 2011, 01:19 am by CrossRoads Reason: 1
Here's the code for writing to a MAX7221, compare to the data sheet. Nothing was changed from whatever the defaults are.
The only pin you need to define is the SS pin to be used, the rest are taken care of by the library (and are not changeable in the ATMega hardware).

Code: [Select]

 // start up SPI to talk to the MAX7221
 SPI.begin(); // nothing in () because we are the master
 pinMode(SS, OUTPUT);  // Slave Select for SPI  <--- Need this here before any SPI writes?

 //  MAX7221: write shutdown register  
 digitalWrite(SS,LOW);  // take the SS pin low to select the chip:
 SPI.transfer(SHUTDOWN_ADDRESS);  // select the Address,
 SPI.transfer(0x00);      // select the data, 0x00 = Outputs turned off
 digitalWrite(SS,HIGH);   // take the SS pin high to de-select the chip:
 // Serial.println("shutdown register, dislays off");


http://datasheets.maxim-ic.com/en/ds/MAX7219-MAX7221.pdf
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

bosley

It looks like the MAX7219 wants to transfer data bits on the rising edge of the clock cycles.  If I'm using a AD9833, the data sheet indicates the data transfer needs to happen on the falling edges.  I guess I need to set the CPOL bit in the SPCR register.   Not sure if there is an easy way to do this other than a brute force write to the register?


bosley

After some digging... It looks like this command might do the trick:

SPI.setDataMode(SPI_MODE2);

CrossRoads

Yep, looks like there are several options you can manipulate here:

http://arduino.cc/en/Reference/SPI
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

Go Up