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/signal.h>
00024 #include <avr/interrupt.h>
00025 
00026 #include "spi.h"
00027 
00028 // Define the SPI_USEINT key if you want SPI bus operation to be
00029 // interrupt-driven.  The primary reason for not using SPI in
00030 // interrupt-driven mode is if the SPI send/transfer commands
00031 // will be used from within some other interrupt service routine
00032 // or if interrupts might be globally turned off due to of other
00033 // aspects of your program
00034 //
00035 // Comment-out or uncomment this line as necessary
00036 //#define SPI_USEINT
00037 
00038 // global variables
00039 volatile u08 spiTransferComplete;
00040 
00041 // SPI interrupt service handler
00042 #ifdef SPI_USEINT
00043 SIGNAL(SIG_SPI)
00044 {
00045     spiTransferComplete = TRUE;
00046 }
00047 #endif
00048 
00049 // access routines
00050 void spiInit()
00051 {
00052 #ifdef __AVR_ATmega128__
00053     // setup SPI I/O pins
00054     sbi(PORTB, 1);  // set SCK hi
00055     sbi(DDRB, 1);   // set SCK as output
00056     cbi(DDRB, 3);   // set MISO as input
00057     sbi(DDRB, 2);   // set MOSI as output
00058     sbi(DDRB, 0);   // SS must be output for Master mode to work
00059 #elif __AVR_ATmega8__
00060     // setup SPI I/O pins
00061     sbi(PORTB, 5);  // set SCK hi
00062     sbi(DDRB, 5);   // set SCK as output
00063     cbi(DDRB, 4);   // set MISO as input
00064     sbi(DDRB, 3);   // set MOSI as output
00065     sbi(DDRB, 2);   // SS must be output for Master mode to work
00066 #else
00067     // setup SPI I/O pins
00068     sbi(PORTB, 7);  // set SCK hi
00069     sbi(DDRB, 7);   // set SCK as output
00070     cbi(DDRB, 6);   // set MISO as input
00071     sbi(DDRB, 5);   // set MOSI as output
00072     sbi(DDRB, 4);   // SS must be output for Master mode to work
00073 #endif
00074     
00075     // setup SPI interface :
00076     // master mode
00077     sbi(SPCR, MSTR);
00078     // clock = f/4
00079 //  cbi(SPCR, SPR0);
00080 //  cbi(SPCR, SPR1);
00081     // clock = f/16
00082     cbi(SPCR, SPR0);
00083     sbi(SPCR, SPR1);
00084     // select clock phase positive-going in middle of data
00085     cbi(SPCR, CPOL);
00086     // Data order MSB first
00087     cbi(SPCR,DORD);
00088     // enable SPI
00089     sbi(SPCR, SPE);
00090         
00091     
00092     // some other possible configs
00093     //outp((1<<MSTR)|(1<<SPE)|(1<<SPR0), SPCR );
00094     //outp((1<<CPHA)|(1<<CPOL)|(1<<MSTR)|(1<<SPE)|(1<<SPR0)|(1<<SPR1), SPCR );
00095     //outp((1<<CPHA)|(1<<MSTR)|(1<<SPE)|(1<<SPR0), SPCR );
00096     
00097     // clear status
00098     inb(SPSR);
00099     spiTransferComplete = TRUE;
00100 
00101     // enable SPI interrupt
00102     #ifdef SPI_USEINT
00103     sbi(SPCR, SPIE);
00104     #endif
00105 }
00106 /*
00107 void spiSetBitrate(u08 spr)
00108 {
00109     outb(SPCR, (inb(SPCR) & ((1<<SPR0)|(1<<SPR1))) | (spr&((1<<SPR0)|(1<<SPR1)))));
00110 }
00111 */
00112 void spiSendByte(u08 data)
00113 {
00114     // send a byte over SPI and ignore reply
00115     #ifdef SPI_USEINT
00116         while(!spiTransferComplete);
00117     #else
00118         while(!(inb(SPSR) & (1<<SPIF)));
00119     #endif
00120 
00121     spiTransferComplete = FALSE;
00122     outb(SPDR, data);
00123 }
00124 
00125 u08 spiTransferByte(u08 data)
00126 {
00127 /*  // make sure interface is idle
00128     #ifdef SPI_USEINT
00129         while(!spiTransferComplete);
00130     #else
00131         while(!(inb(SPSR) & (1<<SPIF)));
00132     #endif
00133 */
00134     // send the given data
00135     spiTransferComplete = FALSE;
00136     outb(SPDR, data);
00137 
00138     // wait for transfer to complete
00139     #ifdef SPI_USEINT
00140         while(!spiTransferComplete);
00141     #else
00142         while(!(inb(SPSR) & (1<<SPIF)));
00143         // *** reading of the SPSR and SPDR are crucial
00144         // *** to the clearing of the SPIF flag
00145         // *** in non-interrupt mode
00146         //inb(SPDR);
00147         // set flag
00148         spiTransferComplete = TRUE;
00149     #endif
00150     // return the received data
00151     return inb(SPDR);
00152 }
00153 
00154 u16 spiTransferWord(u16 data)
00155 {
00156     u16 rxData = 0;
00157 
00158     // send MS byte of given data
00159     rxData = (spiTransferByte((data>>8) & 0x00FF))<<8;
00160     // send LS byte of given data
00161     rxData |= (spiTransferByte(data & 0x00FF));
00162 
00163     // return the received data
00164     return rxData;
00165 }

Generated on Tue Sep 20 03:11:43 2005 for Procyon AVRlib by  doxygen 1.4.2