Code.SpiWithoutInterrupts History

Hide minor edits - Show changes to output

Added lines 1-138:
By [[~Jeff|Jeff Gray]], February 2008

This code, adapted from code written by John Schimmel, allows you to use SPI on any digital pins on the Arduino, and does utilize AVR SPI interrupts. These functions will work in a simple SPI communication scheme, but may not be appropriate if you are trying to utilize the SPI protocol at its fastest speeds.

If speed and efficiency is critical, you should explore the SPI examples on the Arduino website:

[[http://www.arduino.cc/en/Tutorial/SPIEEPROM|Arduino SPI and EEPROM]]

[[http://www.arduino.cc/en/Tutorial/SPIDigitalPot|Arduino SPI and a Digital Potentiometer]]

'''Arduino Code'''

[@
// define pin mapping
byte s_clk = 12;
byte s_miso = 11;
byte s_mosi = 10;
byte s_ss = 9;
byte s_drdy = 8;

// place them in an array so they can be easily shared with the functions
byte mainSensor[] = {s_clk, s_miso, s_mosi, s_ss, s_drdy};

void setup() {
spi_init(mainSensor);

// if you simply need to send a byte to set up the device
// but don't need a response byte, setSensor is your friend
setSensor(mainSensor, 0x03);

// for debugging
Serial.begin(38400);
Serial.println("Starting");
}

void loop() {

// readSensor will send a byte, and then wait for acknowledgement
// at which point, it will make contact again and grab the byte
byte result = readSensor(mainSensor, 0x1F);

// output the result to the viewing computer
Serial.print(0x1F,HEX);
Serial.print(" <- Reg, Value -> ");
Serial.println(result);

}

void setSensor(byte currentSensor[], byte reg){
spi_transfer(currentSensor, reg);
}

byte readSensor(byte currentSensor[], byte reg) {
spi_transfer(currentSensor, reg);
spi_waitForReady(currentSensor[4]);
// sent 0x00 doesn't matter, we're collecting the byte from the transfer before
return spi_transfer(currentSensor,0x00);
}

void spi_init(byte spi_pins[]) {

delay(60);
// define pin directions
pinMode(spi_pins[0], OUTPUT);
pinMode(spi_pins[1], INPUT);
pinMode(spi_pins[2], OUTPUT);
pinMode(spi_pins[3], OUTPUT);
pinMode(spi_pins[4], INPUT);

// initialise pins
digitalWrite(spi_pins[0],HIGH);
digitalWrite(spi_pins[3], HIGH);

}

void spi_waitForReady(byte dataReady){
// wait for the data ready pin to go high
// telling you data is ready to be sent back
while(!digitalRead(dataReady)){
continue;
}
}

byte spi_transfer(byte current_sensor[], byte data_out){

byte i = 8;

byte spi_clk = current_sensor[0]; //
byte spi_miso = current_sensor[1];
byte spi_mosi = current_sensor[2]; //
byte spi_ss = current_sensor[3]; //
byte spi_drdy = current_sensor[4];

byte mask = 0;
byte data_in = 0;

digitalWrite(spi_ss,LOW); // select slave by lowering ss pin
delayMicroseconds(75); //wait for 75 microseconds

while(0 < i) {

mask = 0x01 << --i; // generate bitmask for the appropriate bit MSB first

// set out byte
if(data_out & mask){
digitalWrite(spi_mosi,HIGH); // send 1
}
else{
digitalWrite(spi_mosi,LOW); // send 0
}

// lower clock pin, this tells the sensor to read the bit we just put out
digitalWrite(spi_clk,LOW); // tick

// give the sensor time to read the data
delayMicroseconds(75);

// bring clock back up
digitalWrite(spi_clk,HIGH); // tock

// give the sensor some time to think
delayMicroseconds(20);

// now read a bit coming from the sensor
if(digitalRead(spi_miso)){
data_in |= mask;
}
// give the sensor some time to think
delayMicroseconds(20);

}

delayMicroseconds(75); // give the sensor some time to think
digitalWrite(spi_ss,HIGH); // do acquisition burst

return data_in;
}
@]