| #SPI Library for Teensy# | |||||
| http://www.pjrc.com/teensy/teensyduino.html |
| /* | |||||
| * Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st> | |||||
| * SPI Master library for arduino. | |||||
| * | |||||
| * This file is free software; you can redistribute it and/or modify | |||||
| * it under the terms of either the GNU General Public License version 2 | |||||
| * or the GNU Lesser General Public License version 2.1, both as | |||||
| * published by the Free Software Foundation. | |||||
| */ | |||||
| #include "pins_arduino.h" | |||||
| #include "SPI.h" | |||||
| SPIClass SPI; | |||||
| void SPIClass::begin() { | |||||
| // Set SS to high so a connected chip will be "deselected" by default | |||||
| digitalWrite(SS, HIGH); | |||||
| // When the SS pin is set as OUTPUT, it can be used as | |||||
| // a general purpose output port (it doesn't influence | |||||
| // SPI operations). | |||||
| pinMode(SS, OUTPUT); | |||||
| // Warning: if the SS pin ever becomes a LOW INPUT then SPI | |||||
| // automatically switches to Slave, so the data direction of | |||||
| // the SS pin MUST be kept as OUTPUT. | |||||
| SPCR |= _BV(MSTR); | |||||
| SPCR |= _BV(SPE); | |||||
| // Set direction register for SCK and MOSI pin. | |||||
| // MISO pin automatically overrides to INPUT. | |||||
| // By doing this AFTER enabling SPI, we avoid accidentally | |||||
| // clocking in a single bit since the lines go directly | |||||
| // from "input" to SPI control. | |||||
| // http://code.google.com/p/arduino/issues/detail?id=888 | |||||
| #ifdef __AVR__ | |||||
| pinMode(SCK, OUTPUT); | |||||
| pinMode(MOSI, OUTPUT); | |||||
| #endif | |||||
| } | |||||
| void SPIClass::end() { | |||||
| SPCR &= ~_BV(SPE); | |||||
| } | |||||
| void SPIClass::setBitOrder(uint8_t bitOrder) | |||||
| { | |||||
| if(bitOrder == LSBFIRST) { | |||||
| SPCR |= _BV(DORD); | |||||
| } else { | |||||
| SPCR &= ~(_BV(DORD)); | |||||
| } | |||||
| } | |||||
| void SPIClass::setDataMode(uint8_t mode) | |||||
| { | |||||
| SPCR = (SPCR & ~SPI_MODE_MASK) | mode; | |||||
| } | |||||
| void SPIClass::setClockDivider(uint8_t rate) | |||||
| { | |||||
| SPCR = (SPCR & ~SPI_CLOCK_MASK) | (rate & SPI_CLOCK_MASK); | |||||
| SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((rate >> 2) & SPI_2XCLOCK_MASK); | |||||
| } | |||||
| /* | |||||
| * Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st> | |||||
| * SPI Master library for arduino. | |||||
| * | |||||
| * This file is free software; you can redistribute it and/or modify | |||||
| * it under the terms of either the GNU General Public License version 2 | |||||
| * or the GNU Lesser General Public License version 2.1, both as | |||||
| * published by the Free Software Foundation. | |||||
| */ | |||||
| #ifndef _SPI_H_INCLUDED | |||||
| #define _SPI_H_INCLUDED | |||||
| #include <stdio.h> | |||||
| #include <Arduino.h> | |||||
| #include <avr/pgmspace.h> | |||||
| #define SPI_CLOCK_DIV4 0x00 | |||||
| #define SPI_CLOCK_DIV16 0x01 | |||||
| #define SPI_CLOCK_DIV64 0x02 | |||||
| #define SPI_CLOCK_DIV128 0x03 | |||||
| #define SPI_CLOCK_DIV2 0x04 | |||||
| #define SPI_CLOCK_DIV8 0x05 | |||||
| #define SPI_CLOCK_DIV32 0x06 | |||||
| //#define SPI_CLOCK_DIV64 0x07 | |||||
| #define SPI_MODE0 0x00 | |||||
| #define SPI_MODE1 0x04 | |||||
| #define SPI_MODE2 0x08 | |||||
| #define SPI_MODE3 0x0C | |||||
| #define SPI_MODE_MASK 0x0C // CPOL = bit 3, CPHA = bit 2 on SPCR | |||||
| #define SPI_CLOCK_MASK 0x03 // SPR1 = bit 1, SPR0 = bit 0 on SPCR | |||||
| #define SPI_2XCLOCK_MASK 0x01 // SPI2X = bit 0 on SPSR | |||||
| class SPIClass { | |||||
| public: | |||||
| inline static byte transfer(byte _data); | |||||
| // SPI Configuration methods | |||||
| inline static void attachInterrupt(); | |||||
| inline static void detachInterrupt(); // Default | |||||
| static void begin(); // Default | |||||
| static void end(); | |||||
| static void setBitOrder(uint8_t); | |||||
| static void setDataMode(uint8_t); | |||||
| static void setClockDivider(uint8_t); | |||||
| #if defined(__arm__) && defined(CORE_TEENSY) | |||||
| inline void setMOSI(uint8_t pin) __attribute__((always_inline)) { SPCR.setMOSI(pin); } | |||||
| inline void setMISO(uint8_t pin) __attribute__((always_inline)) { SPCR.setMISO(pin); } | |||||
| inline void setSCK(uint8_t pin) __attribute__((always_inline)) { SPCR.setSCK(pin); } | |||||
| #endif | |||||
| }; | |||||
| extern SPIClass SPI; | |||||
| byte SPIClass::transfer(byte _data) { | |||||
| SPDR = _data; | |||||
| while (!(SPSR & _BV(SPIF))) | |||||
| ; | |||||
| return SPDR; | |||||
| } | |||||
| void SPIClass::attachInterrupt() { | |||||
| SPCR |= _BV(SPIE); | |||||
| } | |||||
| void SPIClass::detachInterrupt() { | |||||
| SPCR &= ~_BV(SPIE); | |||||
| } | |||||
| #endif |
| /* | |||||
| SCP1000 Barometric Pressure Sensor Display | |||||
| Shows the output of a Barometric Pressure Sensor on a | |||||
| Uses the SPI library. For details on the sensor, see: | |||||
| http://www.sparkfun.com/commerce/product_info.php?products_id=8161 | |||||
| http://www.vti.fi/en/support/obsolete_products/pressure_sensors/ | |||||
| This sketch adapted from Nathan Seidle's SCP1000 example for PIC: | |||||
| http://www.sparkfun.com/datasheets/Sensors/SCP1000-Testing.zip | |||||
| Circuit: | |||||
| SCP1000 sensor attached to pins 6, 7, 10 - 13: | |||||
| DRDY: pin 6 | |||||
| CSB: pin 7 | |||||
| MOSI: pin 11 | |||||
| MISO: pin 12 | |||||
| SCK: pin 13 | |||||
| created 31 July 2010 | |||||
| modified 14 August 2010 | |||||
| by Tom Igoe | |||||
| */ | |||||
| // the sensor communicates using SPI, so include the library: | |||||
| #include <SPI.h> | |||||
| //Sensor's memory register addresses: | |||||
| const int PRESSURE = 0x1F; //3 most significant bits of pressure | |||||
| const int PRESSURE_LSB = 0x20; //16 least significant bits of pressure | |||||
| const int TEMPERATURE = 0x21; //16 bit temperature reading | |||||
| const byte READ = 0b11111100; // SCP1000's read command | |||||
| const byte WRITE = 0b00000010; // SCP1000's write command | |||||
| // pins used for the connection with the sensor | |||||
| // the other you need are controlled by the SPI library): | |||||
| const int dataReadyPin = 6; | |||||
| const int chipSelectPin = 7; | |||||
| void setup() { | |||||
| Serial.begin(9600); | |||||
| // start the SPI library: | |||||
| SPI.begin(); | |||||
| // initalize the data ready and chip select pins: | |||||
| pinMode(dataReadyPin, INPUT); | |||||
| pinMode(chipSelectPin, OUTPUT); | |||||
| //Configure SCP1000 for low noise configuration: | |||||
| writeRegister(0x02, 0x2D); | |||||
| writeRegister(0x01, 0x03); | |||||
| writeRegister(0x03, 0x02); | |||||
| // give the sensor time to set up: | |||||
| delay(100); | |||||
| } | |||||
| void loop() { | |||||
| //Select High Resolution Mode | |||||
| writeRegister(0x03, 0x0A); | |||||
| // don't do anything until the data ready pin is high: | |||||
| if (digitalRead(dataReadyPin) == HIGH) { | |||||
| //Read the temperature data | |||||
| int tempData = readRegister(0x21, 2); | |||||
| // convert the temperature to celsius and display it: | |||||
| float realTemp = (float)tempData / 20.0; | |||||
| Serial.print("Temp[C]="); | |||||
| Serial.print(realTemp); | |||||
| //Read the pressure data highest 3 bits: | |||||
| byte pressure_data_high = readRegister(0x1F, 1); | |||||
| pressure_data_high &= 0b00000111; //you only needs bits 2 to 0 | |||||
| //Read the pressure data lower 16 bits: | |||||
| unsigned int pressure_data_low = readRegister(0x20, 2); | |||||
| //combine the two parts into one 19-bit number: | |||||
| long pressure = ((pressure_data_high << 16) | pressure_data_low)/4; | |||||
| // display the temperature: | |||||
| Serial.println("\tPressure [Pa]=" + String(pressure)); | |||||
| } | |||||
| } | |||||
| //Read from or write to register from the SCP1000: | |||||
| unsigned int readRegister(byte thisRegister, int bytesToRead ) { | |||||
| byte inByte = 0; // incoming byte from the SPI | |||||
| unsigned int result = 0; // result to return | |||||
| Serial.print(thisRegister, BIN); | |||||
| Serial.print("\t"); | |||||
| // SCP1000 expects the register name in the upper 6 bits | |||||
| // of the byte. So shift the bits left by two bits: | |||||
| thisRegister = thisRegister << 2; | |||||
| // now combine the address and the command into one byte | |||||
| byte dataToSend = thisRegister & READ; | |||||
| Serial.println(thisRegister, BIN); | |||||
| // take the chip select low to select the device: | |||||
| digitalWrite(chipSelectPin, LOW); | |||||
| // send the device the register you want to read: | |||||
| SPI.transfer(dataToSend); | |||||
| // send a value of 0 to read the first byte returned: | |||||
| result = SPI.transfer(0x00); | |||||
| // decrement the number of bytes left to read: | |||||
| bytesToRead--; | |||||
| // if you still have another byte to read: | |||||
| if (bytesToRead > 0) { | |||||
| // shift the first byte left, then get the second byte: | |||||
| result = result << 8; | |||||
| inByte = SPI.transfer(0x00); | |||||
| // combine the byte you just got with the previous one: | |||||
| result = result | inByte; | |||||
| // decrement the number of bytes left to read: | |||||
| bytesToRead--; | |||||
| } | |||||
| // take the chip select high to de-select: | |||||
| digitalWrite(chipSelectPin, HIGH); | |||||
| // return the result: | |||||
| return(result); | |||||
| } | |||||
| //Sends a write command to SCP1000 | |||||
| void writeRegister(byte thisRegister, byte thisValue) { | |||||
| // SCP1000 expects the register address in the upper 6 bits | |||||
| // of the byte. So shift the bits left by two bits: | |||||
| thisRegister = thisRegister << 2; | |||||
| // now combine the register address and the command into one byte: | |||||
| byte dataToSend = thisRegister | WRITE; | |||||
| // take the chip select low to select the device: | |||||
| digitalWrite(chipSelectPin, LOW); | |||||
| SPI.transfer(dataToSend); //Send register location | |||||
| SPI.transfer(thisValue); //Send value to record into register | |||||
| // take the chip select high to de-select: | |||||
| digitalWrite(chipSelectPin, HIGH); | |||||
| } | |||||
| /* | |||||
| SCP1000 Barometric Pressure Sensor Display | |||||
| Shows the output of a Barometric Pressure Sensor on a | |||||
| Uses the SPI library. For details on the sensor, see: | |||||
| http://www.sparkfun.com/commerce/product_info.php?products_id=8161 | |||||
| http://www.vti.fi/en/support/obsolete_products/pressure_sensors/ | |||||
| This sketch adapted from Nathan Seidle's SCP1000 example for PIC: | |||||
| http://www.sparkfun.com/datasheets/Sensors/SCP1000-Testing.zip | |||||
| Circuit: | |||||
| SCP1000 sensor attached to pins 6, 7, 10 - 13: | |||||
| DRDY: pin 6 | |||||
| CSB: pin 7 | |||||
| MOSI: pin 11 | |||||
| MISO: pin 12 | |||||
| SCK: pin 13 | |||||
| created 31 July 2010 | |||||
| modified 14 August 2010 | |||||
| by Tom Igoe | |||||
| */ | |||||
| // the sensor communicates using SPI, so include the library: | |||||
| #include <SPI.h> | |||||
| //Sensor's memory register addresses: | |||||
| const int PRESSURE = 0x1F; //3 most significant bits of pressure | |||||
| const int PRESSURE_LSB = 0x20; //16 least significant bits of pressure | |||||
| const int TEMPERATURE = 0x21; //16 bit temperature reading | |||||
| cont byte READ = 0b00000000; // SCP1000's read command | |||||
| const byte WRITE = 0b00000010; // SCP1000's write command | |||||
| // pins used for the connection with the sensor | |||||
| // the other you need are controlled by the SPI library): | |||||
| const int dataReadyPin = 6; | |||||
| const int chipSelectPin = 7; | |||||
| void setup() { | |||||
| Serial.begin(9600); | |||||
| // start the SPI library: | |||||
| SPI.begin(); | |||||
| // initalize the data ready and chip select pins: | |||||
| pinMode(dataReadyPin, INPUT); | |||||
| pinMode(chipSelectPin, OUTPUT); | |||||
| //Configure SCP1000 for low noise configuration: | |||||
| writeRegister(0x02, 0x2D); | |||||
| writeRegister(0x01, 0x03); | |||||
| writeRegister(0x03, 0x02); | |||||
| // give the sensor time to set up: | |||||
| delay(100); | |||||
| } | |||||
| void loop() { | |||||
| //Select High Resolution Mode | |||||
| writeRegister(0x03, 0x0A); | |||||
| // don't do anything until the data ready pin is high: | |||||
| if (digitalRead(dataReadyPin) == HIGH) { | |||||
| //Read the temperature data | |||||
| int tempData = readRegister(0x21, 2); | |||||
| // convert the temperature to celsius and display it: | |||||
| float realTemp = (float)tempData / 20.0; | |||||
| Serial.print("Temp[C]="); | |||||
| Serial.print(realTemp); | |||||
| //Read the pressure data highest 3 bits: | |||||
| byte pressure_data_high = readRegister(0x1F, 1); | |||||
| pressure_data_high &= 0b00000111; //you only needs bits 2 to 0 | |||||
| //Read the pressure data lower 16 bits: | |||||
| unsigned int pressure_data_low = readRegister(0x20, 2); | |||||
| //combine the two parts into one 19-bit number: | |||||
| long pressure = ((pressure_data_high << 16) | pressure_data_low)/4; | |||||
| // display the temperature: | |||||
| Serial.println("\tPressure [Pa]=" + String(pressure)); | |||||
| } | |||||
| } | |||||
| //Read from or write to register from the SCP1000: | |||||
| unsigned int readRegister(byte thisRegister, int bytesToRead ) { | |||||
| byte inByte = 0; // incoming byte from the SPI | |||||
| unsigned int result = 0; // result to return | |||||
| // SCP1000 expects the register name in the upper 6 bits | |||||
| // of the byte. So shift the bits left by two bits: | |||||
| thisRegister = thisRegister << 2; | |||||
| // now combine the address and the command into one byte | |||||
| dataToSend = thisRegister & READ; | |||||
| // take the chip select low to select the device: | |||||
| digitalWrite(chipSelectPin, LOW); | |||||
| // send the device the register you want to read: | |||||
| SPI.transfer(dataToSend); | |||||
| // send a value of 0 to read the first byte returned: | |||||
| result = SPI.transfer(0x00); | |||||
| // decrement the number of bytes left to read: | |||||
| bytesToRead--; | |||||
| // if you still have another byte to read: | |||||
| if (bytesToRead > 0) { | |||||
| // shift the first byte left, then get the second byte: | |||||
| result = result << 8; | |||||
| inByte = SPI.transfer(0x00); | |||||
| // combine the byte you just got with the previous one: | |||||
| result = result | inByte; | |||||
| // decrement the number of bytes left to read: | |||||
| bytesToRead--; | |||||
| } | |||||
| // take the chip select high to de-select: | |||||
| digitalWrite(chipSelectPin, HIGH); | |||||
| // return the result: | |||||
| return(result); | |||||
| } | |||||
| //Sends a write command to SCP1000 | |||||
| void writeRegister(byte thisRegister, byte thisValue) { | |||||
| // SCP1000 expects the register address in the upper 6 bits | |||||
| // of the byte. So shift the bits left by two bits: | |||||
| thisRegister = thisRegister << 2; | |||||
| // now combine the register address and the command into one byte: | |||||
| dataToSend = thisRegister | WRITE; | |||||
| // take the chip select low to select the device: | |||||
| digitalWrite(chipSelectPin, LOW); | |||||
| SPI.transfer(dataToSend); //Send register location | |||||
| SPI.transfer(thisValue); //Send value to record into register | |||||
| // take the chip select high to de-select: | |||||
| digitalWrite(chipSelectPin, HIGH); | |||||
| } | |||||
| /* | |||||
| Digital Pot Control | |||||
| This example controls an Analog Devices AD5206 digital potentiometer. | |||||
| The AD5206 has 6 potentiometer channels. Each channel's pins are labeled | |||||
| A - connect this to voltage | |||||
| W - this is the pot's wiper, which changes when you set it | |||||
| B - connect this to ground. | |||||
| The AD5206 is SPI-compatible,and to command it, you send two bytes, | |||||
| one with the channel number (0 - 5) and one with the resistance value for the | |||||
| channel (0 - 255). | |||||
| The circuit: | |||||
| * All A pins of AD5206 connected to +5V | |||||
| * All B pins of AD5206 connected to ground | |||||
| * An LED and a 220-ohm resisor in series connected from each W pin to ground | |||||
| * CS - to digital pin 10 (SS pin) | |||||
| * SDI - to digital pin 11 (MOSI pin) | |||||
| * CLK - to digital pin 13 (SCK pin) | |||||
| created 10 Aug 2010 | |||||
| by Tom Igoe | |||||
| Thanks to Heather Dewey-Hagborg for the original tutorial, 2005 | |||||
| */ | |||||
| // inslude the SPI library: | |||||
| #include <SPI.h> | |||||
| // set pin 10 as the slave select for the digital pot: | |||||
| const int slaveSelectPin = 10; | |||||
| void setup() { | |||||
| // set the slaveSelectPin as an output: | |||||
| pinMode (slaveSelectPin, OUTPUT); | |||||
| // initialize SPI: | |||||
| SPI.begin(); | |||||
| } | |||||
| void loop() { | |||||
| // go through the six channels of the digital pot: | |||||
| for (int channel = 0; channel < 6; channel++) { | |||||
| // change the resistance on this channel from min to max: | |||||
| for (int level = 0; level < 255; level++) { | |||||
| digitalPotWrite(channel, level); | |||||
| delay(10); | |||||
| } | |||||
| // wait a second at the top: | |||||
| delay(100); | |||||
| // change the resistance on this channel from max to min: | |||||
| for (int level = 0; level < 255; level++) { | |||||
| digitalPotWrite(channel, 255 - level); | |||||
| delay(10); | |||||
| } | |||||
| } | |||||
| } | |||||
| void digitalPotWrite(int address, int value) { | |||||
| // take the SS pin low to select the chip: | |||||
| digitalWrite(slaveSelectPin,LOW); | |||||
| // send in the address and value via SPI: | |||||
| SPI.transfer(address); | |||||
| SPI.transfer(value); | |||||
| // take the SS pin high to de-select the chip: | |||||
| digitalWrite(slaveSelectPin,HIGH); | |||||
| } |
| ####################################### | |||||
| # Syntax Coloring Map SPI | |||||
| ####################################### | |||||
| ####################################### | |||||
| # Datatypes (KEYWORD1) | |||||
| ####################################### | |||||
| SPI KEYWORD1 | |||||
| ####################################### | |||||
| # Methods and Functions (KEYWORD2) | |||||
| ####################################### | |||||
| begin KEYWORD2 | |||||
| end KEYWORD2 | |||||
| transfer KEYWORD2 | |||||
| setBitOrder KEYWORD2 | |||||
| setDataMode KEYWORD2 | |||||
| setClockDivider KEYWORD2 | |||||
| setMOSI KEYWORD2 | |||||
| setMISO KEYWORD2 | |||||
| setSCK KEYWORD2 | |||||
| ####################################### | |||||
| # Constants (LITERAL1) | |||||
| ####################################### | |||||
| SPI_CLOCK_DIV4 LITERAL1 | |||||
| SPI_CLOCK_DIV16 LITERAL1 | |||||
| SPI_CLOCK_DIV64 LITERAL1 | |||||
| SPI_CLOCK_DIV128 LITERAL1 | |||||
| SPI_CLOCK_DIV2 LITERAL1 | |||||
| SPI_CLOCK_DIV8 LITERAL1 | |||||
| SPI_CLOCK_DIV32 LITERAL1 | |||||
| SPI_CLOCK_DIV64 LITERAL1 | |||||
| SPI_MODE0 LITERAL1 | |||||
| SPI_MODE1 LITERAL1 | |||||
| SPI_MODE2 LITERAL1 | |||||
| SPI_MODE3 LITERAL1 |