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 }