www.pudn.com > cc03-demo-spi-0_0_1.rar > spi_drv.c


/*C************************************************************************** 
* NAME:         spi_drv.c 
*---------------------------------------------------------------------------- 
* Copyright (c) 2003 Atmel. 
*---------------------------------------------------------------------------- 
* RELEASE:      cc03-demo-spi-0_0_1       
* REVISION:     1.1.1.1      
*---------------------------------------------------------------------------- 
* PURPOSE:  
* spi library low level functions (init, receive and send functions)                                                
* and global variables declarations to use with user software application 
*****************************************************************************/ 
 
 
 
/*_____ I N C L U D E S ____________________________________________________*/ 
#include "config.h" 
#include "spi_drv.h" 
 
/*_____ M A C R O S ________________________________________________________*/ 
 
/*_____ D E F I N I T I O N ________________________________________________*/ 
 
/*_____ D E C L A R A T I O N ______________________________________________*/ 
 
// Here are some global flags to use with spi library 
// These global flags arec used to communicate with higher level functions ( user application ) 
volatile bit b_spi_error;				// General pupose error flag 
volatile bit b_spi_transmit_completed;	// for interrupt transmition use ( set when completed ) 
volatile bit b_spi_busy;				// set when spi interface is in use 
 
// Here the globals variables to communicate with spi interrupt routine 
volatile unsigned char *spi_string_ptr;	// pointer to data buffer 
volatile unsigned char spi_nb_data;		// number of data 
 
 
 
/*F************************************************************************** 
* NAME: spi_master_init  
*---------------------------------------------------------------------------- 
* PARAMS: 
* cpol: bit CPOL value 
* cpha: bit CPHA value 
* ssdis: bit SSDIS value 
* speed: Uchar spi speed ratio transmission Vs Fper  
* return:   none 
*---------------------------------------------------------------------------- 
* PURPOSE:  
* Initialize the spi module in master mode 
*---------------------------------------------------------------------------- 
* EXAMPLE: 
* spi_master_init(0,1,1,4); // init spi in mater mode with CPOL=0, CPHA=1,  
*                           // SSDIS=1 and bitrate=Fper/4  
*---------------------------------------------------------------------------- 
* NOTE: 
*****************************************************************************/ 
void spi_master_init(bit cpol, bit cpha, bit ssdis,Uchar speed) 
{ 
	b_spi_busy=0; 
	b_spi_error=0; 
	b_spi_transmit_completed=0; 
	SPCON = 0; 
	SPCON |= MSK_SPCON_MSTR; 
	spi_set_speed(speed); 
	if (cpol) SPCON |= MSK_SPCON_CPOL; 
	if (cpha) SPCON |= MSK_SPCON_CPHA; 
	if (ssdis) 	SPCON |= MSK_SPCON_SSDIS; 
	SPCON |= MSK_SPCON_SPEN; 
} 
 
/*F************************************************************************** 
* NAME: spi_slave_init  
*---------------------------------------------------------------------------- 
* PARAMS: 
* cpol: bit CPOL value 
* cpha: bit CPHA value 
* ssdis: bit SSDIS value 
* return:   none 
*---------------------------------------------------------------------------- 
* PURPOSE:  
* Initialize the spi module in slave mode 
*---------------------------------------------------------------------------- 
* EXAMPLE: 
* spi_master_init(0,1,1); // init spi in mater mode with CPOL=0, CPHA=1, SSDIS=1 
*---------------------------------------------------------------------------- 
* NOTE: 
*****************************************************************************/ 
void spi_slave_init(bit cpol, bit cpha, bit ssdis) 
{ 
	b_spi_busy=0; 
	b_spi_error=0; 
	b_spi_transmit_completed=0; 
	SPCON = 0; 
	if (cpol) SPCON |= MSK_SPCON_CPOL; 
	if (cpha) SPCON |= MSK_SPCON_CPHA; 
	if (ssdis) 	SPCON |= MSK_SPCON_SSDIS; 
	SPCON |= MSK_SPCON_SPEN; 
} 
 
/*F************************************************************************** 
* NAME: spi_transmit_byte 
*---------------------------------------------------------------------------- 
* PARAMS:  tx_data: byte to send 
* return:  byte received  
*---------------------------------------------------------------------------- 
* PURPOSE:  
* Send and receive a byte with spi interface  
*---------------------------------------------------------------------------- 
* NOTE:  
* If a current spi transfert is on going, the function performs an active wait polling on spi event. 
* This function can be used both in slave and master mode 
*****************************************************************************/ 
unsigned char spi_transmit_byte(unsigned char tx_data) 
{ 
	unsigned char rx_data; 
 
	if ( b_spi_busy )				// If current transfert is on going 
	{ 
		while(!Spif_set()); 	//Wait end of current transfert 
		rx_data=SPDAT; 
	} 
	SPDAT=tx_data; 
	b_spi_busy=1; 
	return	rx_data; 
} 
 
 
/*F************************************************************************** 
* NAME: spi_get_data 
*---------------------------------------------------------------------------- 
* PARAMS: none 
* return: byte received  
*---------------------------------------------------------------------------- 
* PURPOSE:  
* Return the content of the spi data register  
*---------------------------------------------------------------------------- 
* NOTE:  
* This function performs an active wait polling 
*****************************************************************************/ 
unsigned char spi_get_data() 
{ 
	unsigned char to_return; 
	while(!Spif_set()); //Wait end of current transfert 
	to_return=SPDAT;		 
	b_spi_busy=0;						// Release spi ressouce  
	return to_return; 
 
} 
 
 
 
/*F************************************************************************** 
* NAME: spi_put_data 
*---------------------------------------------------------------------------- 
* PARAMS: to_transmit: data to send 
* return: none 
*---------------------------------------------------------------------------- 
* PURPOSE: 
* Send a data byte to the spi interface 
*---------------------------------------------------------------------------- 
* NOTE:  
* This function should be use in spi slave mode to load spi data register 
* with the next data to be transmited in slave mode 
*****************************************************************************/ 
void spi_put_data( unsigned char to_transmit) 
{ 
	SPDAT=to_transmit; 
 
} 
 
 
 
/*F************************************************************************** 
* NAME: spi_transmit_burst_polling 
*---------------------------------------------------------------------------- 
* PARAMS: *ptr_buf: data to send 
* nb_data: number of data to send 
* return: none  
*---------------------------------------------------------------------------- 
* PURPOSE: 
* Transmit a data string throught the spi interface in polling mode  
*---------------------------------------------------------------------------- 
* NOTE:  
* This function performs an active wait polling 
*****************************************************************************/ 
void spi_transmit_burst_polling( unsigned char  *ptr_buf, unsigned char nb_data) 
{ 
unsigned char received; 
  while (nb_data != 0) 
  { 
 
		while(Spte_set())     // Wait for transmit buffer free 
		{ 
	   	SPDAT = *ptr_buf;	 
 	   	received = SPDAT; 
    	*ptr_buf = received; 
    	ptr_buf++; 
    	nb_data--; 
		} 
  } 
} 
 
 
/*F************************************************************************** 
* NAME: spi_set_speed 
*---------------------------------------------------------------------------- 
* PARAMS: ratio: spi clock ratio/XTAL   
* return: bit: status   
*---------------------------------------------------------------------------- 
* PURPOSE:  
* Configure the baud rate of the spi, set CR2, CR1, CR0 
*---------------------------------------------------------------------------- 
* NOTE:  
* This function is use only in spi master mode 
*****************************************************************************/ 
bit spi_set_speed (unsigned char ratio) 
{ 
switch ( ratio ) 
	{ 
	case 2: 
		SPCON |= SPI_RATIO_2; 
		return	TRUE; 
	break; 
 
	case 4: 
		SPCON |= SPI_RATIO_4; 
		return	TRUE; 
	break; 
 
	case 8: 
		SPCON |= SPI_RATIO_8; 
		return	TRUE; 
	break; 
 
	case 16: 
		SPCON |= SPI_RATIO_16; 
		return	TRUE; 
	break; 
 
	case 32: 
		SPCON |= SPI_RATIO_32; 
		return	TRUE; 
	break; 
 
	case 64: 
		SPCON |= SPI_RATIO_64; 
		return	TRUE; 
	break; 
 
	case 128: 
		SPCON |= SPI_RATIO_128; 
		return	TRUE; 
	break; 
 
	default : 
		return	FALSE; 
	break; 
	} 
} 
 
/*F************************************************************************** 
* NAME: spi_transmit_burst_it 
*---------------------------------------------------------------------------- 
* PARAMS:   
* *string_ptr: the string which must be send 
* data_nb: number of data to send 
* return: bit 
*---------------------------------------------------------------------------- 
* PURPOSE:  
* Initialize an spi tranfert in interrupt mode 
* Works in interrupt mode 
* If a current transfert is on going, the function returns '0' 
*---------------------------------------------------------------------------- 
* NOTE:  
* This function can be used in slave or master mode 
*****************************************************************************/ 
bit spi_transmit_burst_it (Uchar *string_ptr, Uchar data_nb) 
{ 
	if ( ~b_spi_busy ) 
	{ 
		b_spi_busy=1; 
		b_spi_transmit_completed=0; 
		b_spi_error=0; 
		spi_string_ptr = string_ptr; 
	  spi_nb_data = data_nb; 
		SPDAT=*spi_string_ptr; 
		return 1; 
	} 
	else	//current transfert on going 
	{ 
		return 0; 
	} 
} 
 
 
/*F************************************************************************** 
* NAME: spi_interrupt 
*---------------------------------------------------------------------------- 
* PARAMS:   
* *spi_string_ptr: the string which must be send 
* spi_nb_data: number of data to send 
* return: none 
*---------------------------------------------------------------------------- 
* PURPOSE: 
* spi - interruption program for serial transmission ( Master and Slave mode ) 
*---------------------------------------------------------------------------- 
* NOTE: 
*****************************************************************************/ 
void spi_interrupt(void) interrupt IRQ_SPI 
{ 
	if(Spif_set()) 
	{ 
		*spi_string_ptr=SPDAT; 
		spi_nb_data--; 
		if (spi_nb_data!=0) 
		{ 
			spi_string_ptr++; 
			SPDAT=*spi_string_ptr; 
		} 
		else 
		{ 
			b_spi_busy=0; 
			b_spi_transmit_completed=1; 
		} 
	} 
 
}