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 }