LT_SPI

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LT_SPI.cpp Source File

LT_SPI.cpp

Go to the documentation of this file.
00001 //! @todo Review this document.
00002 /*!
00003 LT_SPI: Routines to communicate with ATmega328P's hardware SPI port.
00004 
00005 @verbatim
00006 
00007 LT_SPI implements the low level master SPI bus routines using
00008 the hardware SPI port.
00009 
00010 SPI Frequency = (CPU Clock frequency)/(16+2(TWBR)*Prescaler)
00011 SPCR = SPI Control Register (SPIE SPE DORD MSTR CPOL CPHA SPR1 SPR0)
00012 SPSR = SPI Status Register (SPIF WCOL - - - - - SPI2X)
00013 
00014 Data Modes:
00015 CPOL  CPHA  Leading Edge    Trailing Edge
00016 0      0    sample rising   setup falling
00017 0      1    setup rising    sample falling
00018 1      0    sample falling  setup rising
00019 1      1    sample rising   setup rising
00020 
00021 CPU Frequency = 16MHz on Arduino Uno
00022 SCK Frequency
00023 SPI2X  SPR1  SPR0  Frequency  Uno_Frequency
00024   0      0     0     fosc/4     4 MHz
00025   0      0     1     fosc/16    1 MHz
00026   0      1     0     fosc/64    250 kHz
00027   0      1     1     fosc/128   125 kHz
00028   0      0     0     fosc/2     8 MHz
00029   0      0     1     fosc/8     2 MHz
00030   0      1     0     fosc/32    500 kHz
00031 
00032 @endverbatim
00033 
00034 REVISION HISTORY
00035 $Revision: 6237 $
00036 $Date: 2016-12-20 15:09:16 -0800 (Tue, 20 Dec 2016) $
00037 
00038 Copyright (c) 2013, Linear Technology Corp.(LTC)
00039 All rights reserved.
00040 
00041 Redistribution and use in source and binary forms, with or without
00042 modification, are permitted provided that the following conditions are met:
00043 
00044 1. Redistributions of source code must retain the above copyright notice, this
00045    list of conditions and the following disclaimer.
00046 2. Redistributions in binary form must reproduce the above copyright notice,
00047    this list of conditions and the following disclaimer in the documentation
00048    and/or other materials provided with the distribution.
00049 
00050 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00051 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00052 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00053 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
00054 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00055 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00056 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00057 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00058 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00059 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00060 
00061 The views and conclusions contained in the software and documentation are those
00062 of the authors and should not be interpreted as representing official policies,
00063 either expressed or implied, of Linear Technology Corp.
00064 
00065 The Linear Technology Linduino is not affiliated with the official Arduino team.
00066 However, the Linduino is only possible because of the Arduino team's commitment
00067 to the open-source community.  Please, visit http://www.arduino.cc and
00068 http://store.arduino.cc , and consider a purchase that will help fund their
00069 ongoing work.
00070 */
00071 
00072 //! @ingroup Linduino
00073 //! @{
00074 //! @defgroup LT_SPI LT_SPI: Routines to communicate with ATmega328P's hardware SPI port.
00075 //! @}
00076 
00077 /*! @file
00078     @ingroup LT_SPI
00079     Library for LT_SPI: Routines to communicate with ATmega328P's hardware SPI port.
00080 */
00081 #include <stdint.h>
00082 #include "LT_SPI.h "
00083 
00084 //DigitalOut QUIKEVAL_GPIO D9;          //!< Linduino QuikEval GPIO pin (QuikEval connector pin 14) connects to Arduino pin 9
00085 //DigitalOut QUIKEVAL_CS A3;        //!< QuikEval CS pin (SPI chip select on QuikEval connector pin 6) connects to Arduino SS pin.
00086 //DigitalInOut QUIKEVAL_MUX_MODE_PIN(8,output);  /*!< QUIKEVAL_MUX_MODE_PIN defines the control pin for the QuikEval MUX.
00087 //The I2C port's SCL and the SPI port's SCK signals share the same pin on the Linduino's QuikEval connector.
00088 //Additionally, the I2C port's SDA and the SPI port's MOSI signals share the same pin on the Linduino's QuikEval connector.
00089 //The pair of pins connected to the QuikEval connector is switched using a MUX on the Linduino board.
00090 //The control pin to switch the MUX is defined as QUIKEVAL_MUX_MODE_PIN (Arduino pin 8). */
00091 
00092 void output_low(uint8_t pin)
00093 {
00094     pin = 0;
00095 }
00096 void output_high(uint8_t pin)
00097 {
00098     pin = 1;
00099 }
00100 
00101 
00102 // Reads and sends a byte
00103 // Return 0 if successful, 1 if failed
00104 void spi_transfer_byte(uint8_t cs_pin, uint8_t tx, uint8_t *rx)
00105 {
00106   output_low(cs_pin);                 //! 1) Pull CS low
00107 
00108   *rx = spi.write(tx);             //! 2) Read byte and send byte
00109 
00110   output_high(cs_pin);                //! 3) Pull CS high
00111 }
00112 
00113 // Reads and sends a word
00114 // Return 0 if successful, 1 if failed
00115 void spi_transfer_word(uint8_t cs_pin, uint16_t tx, uint16_t *rx)
00116 {
00117   union
00118   {
00119     uint8_t b[2];
00120     uint16_t w;
00121   } data_tx;
00122 
00123   union
00124   {
00125     uint8_t b[2];
00126     uint16_t w;
00127   } data_rx;
00128 
00129   data_tx.w = tx;
00130 
00131   output_low(cs_pin);                         //! 1) Pull CS low
00132 
00133   data_rx.b[1] = spi.write(data_tx.b[1]);  //! 2) Read MSB and send MSB
00134   data_rx.b[0] = spi.write(data_tx.b[0]);  //! 3) Read LSB and send LSB
00135 
00136   *rx = data_rx.w;
00137 
00138   output_high(cs_pin);                        //! 4) Pull CS high
00139 }
00140 
00141 // Reads and sends a byte array
00142 void spi_transfer_block(uint8_t cs_pin, uint8_t *tx, uint8_t *rx, uint8_t length)
00143 {
00144   int8_t i;
00145 
00146   output_low(cs_pin);                 //! 1) Pull CS low
00147 
00148   for (i=(length-1);  i >= 0; i--)
00149     rx[i] = spi.write(tx[i]);    //! 2) Read and send byte array
00150 
00151   output_high(cs_pin);                //! 3) Pull CS high
00152 }
00153 
00154 // Connect SPI pins to QuikEval connector through the Linduino MUX. This will disconnect I2C.
00155 //void quikeval_SPI_connect()
00156 //{
00157 //  output_high(QUIKEVAL_CS); //! 1) Pull Chip Select High
00158 //
00159 //  //! 2) Enable Main SPI
00160 //  pinMode(QUIKEVAL_MUX_MODE_PIN, OUTPUT);
00161 //  QUIKEVAL_MUX_MODE_PIN = 0;
00162 //}
00163 
00164 // Configure the SPI port for 4MHz SCK.
00165 // This function or spi_enable() must be called
00166 // before using the other SPI routines.
00167 //void quikeval_SPI_init(void)  // Initializes SPI
00168 //{
00169 //  spi_enable(SPI_CLOCK_DIV16);  //! 1) Configure the spi port for 4MHz SCK
00170 //}
00171 
00172 // Setup the processor for hardware SPI communication.
00173 // Must be called before using the other SPI routines.
00174 // Alternatively, call quikeval_SPI_connect(), which automatically
00175 // calls this function.
00176 void spi_enable(void) // Configures SCK frequency. Use constant defined in header file.
00177 {
00178   //pinMode(SCK, OUTPUT);             //! 1) Setup SCK as output
00179   //pinMode(MOSI, OUTPUT);            //! 2) Setup MOSI as output
00180   //pinMode(QUIKEVAL_CS, OUTPUT);     //! 3) Setup CS as output
00181   spi.format(16,3);
00182   spi.frequency(1000000);
00183 }
00184 
00185 // Disable the SPI hardware port
00186 //void spi_disable()
00187 //{
00188 //  spi.end();
00189 //}
00190 
00191 // Write a data byte using the SPI hardware
00192 //void spi_write(int8_t  data)  // Byte to be written to SPI port
00193 //{
00194 //  SPDR = data;                  //! 1) Start the SPI transfer
00195 //  while (!(SPSR & _BV(SPIF)));  //! 2) Wait until transfer complete
00196 //}
00197 
00198 // Read and write a data byte using the SPI hardware
00199 // Returns the data byte read
00200 //int8_t spi_read(int8_t  data) //!The data byte to be written
00201 //{
00202 //  SPDR = data;                  //! 1) Start the SPI transfer
00203 //  while (!(SPSR & _BV(SPIF)));  //! 2) Wait until transfer complete
00204 //  return SPDR;                  //! 3) Return the data read
00205 //}
00206 
00207 // Below are implementations of spi_read, etc. that do not use the
00208 // Arduino SPI library.  To use these functions, uncomment them and comment out
00209 // the correcsponding function above.
00210 //
00211 // // Reads and sends a byte
00212 // // Return 0 if successful, 1 if failed
00213 // uint8_t spi_transfer_byte(uint8_t cs_pin, uint8_t tx, uint8_t *rx)
00214 // {
00215 //     output_low(cs_pin);                 //! 1) Pull CS low
00216 //
00217 //     *rx = spi_read(tx);                 //! 2) Read byte and send byte
00218 //
00219 //     output_high(cs_pin);                //! 3) Pull CS high
00220 //
00221 //     return(0);
00222 // }
00223 //
00224 // // Reads and sends a word
00225 // // Return 0 if successful, 1 if failed
00226 // uint8_t spi_transfer_word(uint8_t cs_pin, uint16_t tx, uint16_t *rx)
00227 // {
00228 //     union
00229 //     {
00230 //         uint8_t b[2];
00231 //         uint16_t w;
00232 //     } data_tx;
00233 //
00234 //     union
00235 //     {
00236 //         uint8_t b[2];
00237 //         uint16_t w;
00238 //     } data_rx;
00239 //
00240 //     data_tx.w = tx;
00241 //
00242 //     output_low(cs_pin);                     //! 1) Pull CS low
00243 //
00244 //     data_rx.b[1] = spi_read(data_tx.b[1]);  //! 2) Read MSB and send MSB
00245 //     data_rx.b[0] = spi_read(data_tx.b[0]);  //! 3) Read LSB and send LSB
00246 //     *rx = data_rx.w;
00247 //
00248 //     output_high(cs_pin);                    //! 4) Pull CS high
00249 //
00250 //     return(0);
00251 // }
00252 //
00253 // // Reads and sends a byte array
00254 // // Return 0 if successful, 1 if failed
00255 // uint8_t spi_transfer_block(uint8_t cs_pin, uint8_t *tx, uint8_t *rx, uint8_t length)
00256 // {
00257 //     int8_t i;
00258 //
00259 //     output_low(cs_pin);                 //! 1) Pull CS low
00260 //
00261 //     for(i=0;  i < length; i++)
00262 //         rx[i] = spi_read(tx[i]);        //! 2) Read and send byte array
00263 //
00264 //     output_high(cs_pin);                //! 3) Pull CS high
00265 //
00266 //     return(0);
00267 // }
00268 //
00269 // // Connect SPI pins to QuikEval connector through the Linduino MUX. This will disconnect I2C.
00270 // void quikeval_SPI_connect()
00271 // {
00272 //   output_high(QUIKEVAL_CS); //! 1) Pull Chip Select High
00273 //
00274 //   //! 2) Enable Main SPI
00275 //   pinMode(QUIKEVAL_MUX_MODE_PIN, OUTPUT);
00276 //   digitalWrite(QUIKEVAL_MUX_MODE_PIN, LOW);
00277 // }
00278 //
00279 // // Configure the SPI port for 4MHz SCK.
00280 // // This function or spi_enable() must be called
00281 // // before using the other SPI routines.
00282 // void quikeval_SPI_init(void)  // Initializes SPI
00283 // {
00284 //   spi_enable(SPI_CLOCK_DIV32);  //! 2) Configure the spi port for 4MHz SCK
00285 // }
00286 //
00287 // // Setup the processor for hardware SPI communication.
00288 // // Must be called before using the other SPI routines.
00289 // // Alternatively, call quikeval_SPI_connect(), which automatically
00290 // // calls this function.
00291 // void spi_enable(uint8_t spi_clock_divider) // Configures SCK frequency. Use constant defined in header file.
00292 // {
00293 //   pinMode(SCK, OUTPUT);             //! 1) Setup SCK as output
00294 //   pinMode(MOSI, OUTPUT);            //! 2) Setup MOSI as output
00295 //   pinMode(QUIKEVAL_CS, OUTPUT);     //! 3) Setup CS as output
00296 //   output_low(SCK);
00297 //   output_low(MOSI);
00298 //   output_high(QUIKEVAL_CS);
00299 //   SPCR |= _BV(MSTR);                //! 4) Set the SPI port to master mode
00300 //   //! 5) Set the SPI hardware rate
00301 //   SPCR = (SPCR & ~SPI_CLOCK_MASK) | (spi_clock_divider & SPI_CLOCK_MASK);
00302 //   SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((spi_clock_divider >> 2) & SPI_2XCLOCK_MASK);
00303 //   SPCR |= _BV(SPE);                 //! 5) Enable the SPI port
00304 // }
00305 //
00306 // // Disable the SPI hardware port
00307 // void spi_disable()
00308 // {
00309 //   SPCR &= ~_BV(SPE);
00310 // }