/** * @file spi.c * @brief SPI functions * * Implement SPI inteface communications * * @author Rustem Kalimullin * @par E-mail: * hellos@mail.ru * @par Copyright: * (c) Kurt, 2005 */ #include "common.h" #define SPI_PORT_WR (P3OUT) //!< Output port #define SPI_PORT_RD (P3IN) //!< Input port #define SPI_PORT_DIR (P3DIR) #define SPI_PORT_SEL (P3SEL) //!< Port options #define SPI_DO (1<<1) //!< Output pin mask #define SPI_DI (1<<2) //!< Input pin mask #define SPI_CK (1<<3) //!< Clock pin mask //--------------------------------------------------------- //! Send @a data to serial line. Word length in @a bits unsigned int spi_write_bits( unsigned int data, unsigned int bits ) { if( (bits > 16) || (bits == 0) ) return 0xFFFF; for( unsigned int i=16-bits; i > 0; i-- ) data <<= 1; // Align data word to left unsigned int read = 0; do { if( data & 0x8000 ) { SPI_PORT_WR |= SPI_DO; } else { SPI_PORT_WR &= ~SPI_DO; } SPI_PORT_WR |= SPI_CK; for( unsigned int i=3; i; --i ) continue; SPI_PORT_WR &= ~SPI_CK; data <<= 1; read <<= 1; if( SPI_PORT_RD & SPI_DI ) read |= 1; } while( --bits ); return read; } //--------------------------------------------------------- //! Enable hardware SPI void spi_enable(void) { U0CTL |= SWRST; SPI_PORT_SEL |= (SPI_DO | SPI_DI | SPI_CK ); // enable SPI option SPI_PORT_DIR |= (SPI_DO | SPI_CK); // output pins SPI_PORT_DIR &= ~(SPI_DI); // input pins U0ME |= USPIE0; // Enable USART0 SPI mode U0CTL &= ~SWRST; } //--------------------------------------------------------- //! Disable hardware SPI void spi_disable(void) { U0CTL |= SWRST; SPI_PORT_SEL &= ~(SPI_DO | SPI_DI | SPI_CK ); // disable SPI option SPI_PORT_DIR |= (SPI_DO | SPI_CK); // output pins SPI_PORT_DIR &= ~(SPI_DI); // input pins U0ME &= ~USPIE0; // Disable USART0 SPI mode U0CTL &= ~SWRST; } //--------------------------------------------------------- //! Init hardware SPI void spi_init( void ) { U0CTL = CHAR | SYNC | MM | SWRST; // 8-bit SPI Master #ifdef KR_SPI_FULLSPEED U0TCTL = CKPL+SSEL0+SSEL1+STC; // ACLK, 3-pin mode U0BR0 = 0x02; // UCLK = SMCLK #else U0TCTL = CKPL+SSEL1+SSEL0+STC; // SMCLK, 3-pin mode U0BR0 = 0x04; // UCLK/4 #endif U0BR1 = 0x00; U0MCTL = 0x00; // no modulation spi_enable(); } //--------------------------------------------------------- //! Send @a data byte to serial line. unsigned char spi_write( unsigned char data ) { unsigned int tot; tot = 0xFFF; do { if( 0 == --tot ) return 0xFF; } while( !(U0IFG & UTXIFG0) ); // USART0 TX buffer ready? U0TXBUF = data; tot = 0xFFF; do { if ( 0 == --tot ) return 0xFF; } while( !(U0TCTL & TXEPT) ); // USART0 Transmit complete? return U0RXBUF; } //--------------------------------------------------------- //! Receive byte from serial line. unsigned char spi_read( void ) { return spi_write(0x00); }