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 #else 00060 // setup SPI I/O pins 00061 sbi(PORTB, 7); // set SCK hi 00062 sbi(DDRB, 7); // set SCK as output 00063 cbi(DDRB, 6); // set MISO as input 00064 sbi(DDRB, 5); // set MOSI as output 00065 sbi(DDRB, 4); // SS must be output for Master mode to work 00066 #endif 00067 00068 // setup SPI interface : 00069 // clock = f/16 00070 // select clock phase positive-going in middle of data 00071 // master mode 00072 // enable SPI 00073 outp((1<<MSTR)|(1<<SPE)|(1<<SPR0), SPCR ); 00074 00075 // some other possible configs 00076 //outp((1<<CPHA)|(1<<CPOL)|(1<<MSTR)|(1<<SPE)|(1<<SPR0)|(1<<SPR1), SPCR ); 00077 //outp((1<<CPHA)|(1<<MSTR)|(1<<SPE)|(1<<SPR0), SPCR ); 00078 00079 // clear status 00080 inp(SPSR); 00081 spiTransferComplete = TRUE; 00082 00083 // enable SPI interrupt 00084 #ifdef SPI_USEINT 00085 sbi(SPCR, SPIE); 00086 #endif 00087 } 00088 00089 void spiSendByte(u08 data) 00090 { 00091 // send a byte over SPI and ignore reply 00092 if(spiTransferComplete) 00093 { 00094 spiTransferComplete = FALSE; 00095 outp(data, SPDR); 00096 } 00097 } 00098 00099 u08 spiTransferByte(u08 data) 00100 { 00101 // send the given data 00102 if(spiTransferComplete) 00103 { 00104 spiTransferComplete = FALSE; 00105 outp(data, SPDR); 00106 } 00107 // wait for transfer to complete 00108 #ifdef SPI_USEINT 00109 while(!spiTransferComplete); 00110 #else 00111 while(!(inp(SPSR) & (1<<SPIF))); 00112 // *** reading of the SPSR and SPDR are crucial 00113 // *** to the clearing of the SPIF flag 00114 // *** in non-interrupt mode 00115 //inp(SPDR); 00116 // set flag 00117 spiTransferComplete = TRUE; 00118 #endif 00119 // return the received data 00120 return inp(SPDR); 00121 } 00122 00123 u16 spiTransferWord(u16 data) 00124 { 00125 u16 rxData = 0; 00126 00127 // send MS byte of given data 00128 rxData = (spiTransferByte((data>>8) & 0x00FF))<<8; 00129 // send LS byte of given data 00130 rxData |= (spiTransferByte(data & 0x00FF)); 00131 00132 // return the received data 00133 return rxData; 00134 }