Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

# spi.c

Go to the documentation of this file.

    00001 /*! \file spi.c \brief SPI interface driver. */
    00002 //*****************************************************************************
    00003 //
    00004 // File Name    : 'spi.c'
    00005 // Title        : SPI interface driver
    00006 // Author       : Pascal Stang - Copyright (C) 2000-2002
    00007 // Created      : 11/22/2000
    00008 // Revised      : 06/06/2002
    00009 // Version      : 0.6
    00010 // Target MCU   : Atmel AVR series
    00011 // Editor Tabs  : 4
    00012 //
    00013 // NOTE: This code is currently below version 1.0, and therefore is considered
    00014 // to be lacking in some functionality or documentation, or may not be fully
    00015 // tested.  Nonetheless, you can expect most functions to work.
    00016 //
    00017 // This code is distributed under the GNU Public License
    00018 //      which can be found at http://www.gnu.org/licenses/gpl.txt
    00019 //
    00020 //*****************************************************************************
    00021
    00022 #include <avr/io.h>
    00023 #include <avr/interrupt.h>
    00024
    00025 #include "spi.h"
    00026
    00027 // Define the SPI_USEINT key if you want SPI bus operation to be
    00028 // interrupt-driven.  The primary reason for not using SPI in
    00029 // interrupt-driven mode is if the SPI send/transfer commands
    00030 // will be used from within some other interrupt service routine
    00031 // or if interrupts might be globally turned off due to of other
    00032 // aspects of your program
    00033 //
    00034 // Comment-out or uncomment this line as necessary
    00035 //#define SPI_USEINT
    00036
    00037 // global variables
    00038 volatile u08 spiTransferComplete;
    00039
    00040 // SPI interrupt service handler
    00041 #ifdef SPI_USEINT
    00042 SIGNAL(SIG_SPI)
    00043 {
    00044     spiTransferComplete = TRUE;
    00045 }
    00046 #endif
    00047
    00048 // access routines
    00049 void spiInit()
    00050 {
    00051 #ifdef __AVR_ATmega128__
    00052     // setup SPI I/O pins
    00053     sbi(PORTB, 1);  // set SCK hi
    00054     sbi(DDRB, 1);   // set SCK as output
    00055     cbi(DDRB, 3);   // set MISO as input
    00056     sbi(DDRB, 2);   // set MOSI as output
    00057     sbi(DDRB, 0);   // SS must be output for Master mode to work
    00058 #elif __AVR_ATmega8__
    00059     // setup SPI I/O pins
    00060     sbi(PORTB, 5);  // set SCK hi
    00061     sbi(DDRB, 5);   // set SCK as output
    00062     cbi(DDRB, 4);   // set MISO as input
    00063     sbi(DDRB, 3);   // set MOSI as output
    00064     sbi(DDRB, 2);   // SS must be output for Master mode to work
    00065 #else
    00066     // setup SPI I/O pins
    00067     sbi(PORTB, 7);  // set SCK hi
    00068     sbi(DDRB, 7);   // set SCK as output
    00069     cbi(DDRB, 6);   // set MISO as input
    00070     sbi(DDRB, 5);   // set MOSI as output
    00071     sbi(DDRB, 4);   // SS must be output for Master mode to work
    00072 #endif
    00073
    00074     // setup SPI interface :
    00075     // master mode
    00076     sbi(SPCR, MSTR);
    00077     // clock = f/4
    00078 //  cbi(SPCR, SPR0);
    00079 //  cbi(SPCR, SPR1);
    00080     // clock = f/16
    00081     cbi(SPCR, SPR0);
    00082     sbi(SPCR, SPR1);
    00083     // select clock phase positive-going in middle of data
    00084     cbi(SPCR, CPOL);
    00085     // Data order MSB first
    00086     cbi(SPCR,DORD);
    00087     // enable SPI
    00088     sbi(SPCR, SPE);
    00089
    00090
    00091     // some other possible configs
    00092     //outp((1<<MSTR)|(1<<SPE)|(1<<SPR0), SPCR );
    00093     //outp((1<<CPHA)|(1<<CPOL)|(1<<MSTR)|(1<<SPE)|(1<<SPR0)|(1<<SPR1), SPCR );
    00094     //outp((1<<CPHA)|(1<<MSTR)|(1<<SPE)|(1<<SPR0), SPCR );
    00095
    00096     // clear status
    00097     inb(SPSR);
    00098     spiTransferComplete = TRUE;
    00099
    00100     // enable SPI interrupt
    00101     #ifdef SPI_USEINT
    00102     sbi(SPCR, SPIE);
    00103     #endif
    00104 }
    00105 /*
    00106 void spiSetBitrate(u08 spr)
    00107 {
    00108     outb(SPCR, (inb(SPCR) & ((1<<SPR0)|(1<<SPR1))) | (spr&((1<<SPR0)|(1<<SPR1)))));
    00109 }
    00110 */
    00111 void spiSendByte(u08 data)
    00112 {
    00113     // send a byte over SPI and ignore reply
    00114     #ifdef SPI_USEINT
    00115         while(!spiTransferComplete);
    00116         spiTransferComplete = FALSE;
    00117     #else
    00118         while(!(inb(SPSR) & (1<<SPIF)));
    00119     #endif
    00120
    00121     outb(SPDR, data);
    00122 }
    00123
    00124 u08 spiTransferByte(u08 data)
    00125 {
    00126     #ifdef SPI_USEINT
    00127     // send the given data
    00128     spiTransferComplete = FALSE;
    00129     outb(SPDR, data);
    00130     // wait for transfer to complete
    00131     while(!spiTransferComplete);
    00132     #else
    00133     // send the given data
    00134     outb(SPDR, data);
    00135     // wait for transfer to complete
    00136     while(!(inb(SPSR) & (1<<SPIF)));
    00137     #endif
    00138     // return the received data
    00139     return inb(SPDR);
    00140 }
    00141
    00142 u16 spiTransferWord(u16 data)
    00143 {
    00144     u16 rxData = 0;
    00145
    00146     // send MS byte of given data
    00147     rxData = (spiTransferByte((data>>8) & 0x00FF))<<8;
    00148     // send LS byte of given data
    00149     rxData |= (spiTransferByte(data & 0x00FF));
    00150
    00151     // return the received data
    00152     return rxData;
    00153 }