SPI Master


	//----- SETUP SPI 1 -----
	//Used for: 
	//Idle low, active high
	//Transmit on active to idle (falling edge)
	SpiChnOpen(SPI_CHANNEL1, (SPI_CON_MSTEN | SPI_OPEN_CKE_REV | SPI_CON_MODE8), 2);       	//40MHz fpb / 2 = 20MHz

SPI Slave


#define	COMMS_SPI_NAME					SPI_CHANNEL3
#define	COMMS_SPI_ID					SPI_CHANNEL3
#define	COMMS_SPI_SS_PIN_STATE			mPORTEReadBits(BIT_8)

	//----- SETUP SPI 3 -----
	//Used for:  (we are slave with SS pin used)
	//Idle low, active high
	//Transmit on idle to active (rising edge)

	SpiChnClose(COMMS_SPI_NAME);

	SpiChnOpen(COMMS_SPI_NAME, (SPI_OPEN_SLVEN | SPI_CON_MODE8 | SPI_OPEN_RBF_NOT_EMPTY | SPI_OPEN_ENHBUF | SPI_OPEN_SSEN), 50);       	//Master sets clock rate
	SpiChnWriteC(COMMS_SPI_NAME, (unsigned int)0xff);			//We are slave so setup 1st response byte to null

	INTSetVectorPriority(INT_VECTOR_SPI(COMMS_SPI_ID), INT_PRIORITY_LEVEL_5);				//1=lowest priority to 7=highest priority.  ISR function must specify same value
	//INTClearFlag(INT_SOURCE_SPI_TX(COMMS_SPI_ID));
	//INTEnable(INT_SOURCE_SPI_TX(COMMS_SPI_ID), INT_ENABLED);
	INTClearFlag(INT_SOURCE_SPI_RX(COMMS_SPI_ID));
	INTEnable(INT_SOURCE_SPI_RX(COMMS_SPI_ID), INT_ENABLED);
	INTClearFlag(INT_SOURCE_SPI_ERROR(COMMS_SPI_ID));
	INTEnable(INT_SOURCE_SPI_ERROR(COMMS_SPI_ID), INT_ENABLED);

 


WORD comms_spi_tx_byte;
WORD comms_spi_rx_byte;
WORD comms_spi_rx_no_of_bytes_to_rx;

//************************************
//************************************
//********** SPI INTERRUPTS **********
//************************************
//************************************
void __ISR(_SPI_3_VECTOR, ipl5) Spi3InterruptHandler (void) 		//(ipl# must match the priority level assigned to the irq where its enabled)
{
	static BYTE data;
	
	
	Nop();


/*
	if (
	(INTGetEnable(INT_SOURCE_SPI_TX(COMMS_SPI_ID))) &&
	(INTGetFlag(INT_SOURCE_SPI_TX(COMMS_SPI_ID)))
	)
	{
		//--------------------------------------
		//--------------------------------------
		//---------- SPI TX INTERRUPT ----------
		//--------------------------------------
		//--------------------------------------


		//INTClearFlag(INT_SOURCE_SPI_TX(COMMS_SPI_ID));
	}
*/


	if (
	(INTGetEnable(INT_SOURCE_SPI_ERROR(COMMS_SPI_ID))) &&
	(INTGetFlag(INT_SOURCE_SPI_ERROR(COMMS_SPI_ID)))
	)
	{
		//-----------------------------------------
		//-----------------------------------------
		//---------- SPI ERROR INTERRUPT ----------
		//-----------------------------------------
		//-----------------------------------------
		
		//Read and clear the SPIROV (overflow) bit
		SpiChnGetRov(COMMS_SPI_ID, 1);

    	
    	//Clear RX buffer of bad data
		while (SpiChnDataRdy(COMMS_SPI_NAME))
			data = SpiChnReadC(COMMS_SPI_NAME);

		INTClearFlag(INT_SOURCE_SPI_RX(COMMS_SPI_ID));
		INTClearFlag(INT_SOURCE_SPI_ERROR(COMMS_SPI_ID));

		comms_spi_rx_byte = 0xffff;
	}



	if (
	(INTGetEnable(INT_SOURCE_SPI_RX(COMMS_SPI_ID))) &&
	(INTGetFlag(INT_SOURCE_SPI_RX(COMMS_SPI_ID)))
	)
	{
		//--------------------------------------
		//--------------------------------------
		//---------- SPI RX INTERRUPT ----------
		//--------------------------------------
		//--------------------------------------

		if (comms_rx_reset_1ms_timer == 0)			//We also check for CS gone high and reset comms_spi_rx_byte
			comms_spi_rx_byte = 0;
				
		comms_rx_reset_1ms_timer = 10;				//<<<< Gap required between packets to mark start of packet

		while (SpiChnDataRdy(COMMS_SPI_NAME))
		{
			//----- GET DATA BYTE -----
			data = (BYTE)SpiChnReadC(COMMS_SPI_NAME);

			//Check for SPI / UART COMMS CLASH
			if (comms_uart_rx_active_10ms_timer)			//If UART is active then ignore SPI comms (clash)
			{
				SpiChnWriteC(COMMS_SPI_NAME, (unsigned int)0xff);		//Return null next time
				continue;
			}
			comms_spi_rx_active_10ms_timer = 10;			//Flag that active comms is SPI (UART to ignore)

			//Check for still processing last RX
			if (comms_rx_process_packet)
			{
				SpiChnWriteC(COMMS_SPI_NAME, (unsigned int)0xff);		//Return null next time
				continue;
			}


			if (comms_spi_tx_byte < comms_tx_no_of_bytes_to_tx)
			{
				//---------------------------------
				//---------------------------------
				//----- TRANSMITTING RESPONSE -----
				//---------------------------------
				//---------------------------------
				SpiChnWriteC(COMMS_SPI_NAME, (unsigned int)comms_tx_rx_buffer[comms_spi_tx_byte++]);
				continue;
			}
			
			//Not transmitting so send mull
			SpiChnWriteC(COMMS_SPI_NAME, (unsigned int)0xff);		//Return null next time
			



			//--------------------------
			//--------------------------
			//----- RECEIVING DATA -----
			//--------------------------
			//--------------------------
			if (comms_spi_rx_byte == 0)
			{
				//--------------------
				//----- LENGTH H -----
				//--------------------
				comms_spi_rx_no_of_bytes_to_rx = (WORD)data;
				comms_spi_rx_no_of_bytes_to_rx <<= 8;
				comms_tx_rx_buffer[comms_spi_rx_byte++] = data;
			}
			else if (comms_spi_rx_byte == 1)
			{
				//--------------------
				//----- LENGTH L -----
				//--------------------
				comms_spi_rx_no_of_bytes_to_rx |= (WORD)data;
				comms_tx_rx_buffer[comms_spi_rx_byte++] = data;
				
				if (comms_spi_rx_no_of_bytes_to_rx >= LENGTH_OF_USART_BUFFER)
					comms_spi_rx_byte = 0xffff;
			}
			else if (comms_spi_rx_byte < comms_spi_rx_no_of_bytes_to_rx)
			{
				//--------------------------
				//----- NEXT DATA BYTE -----
				//--------------------------
				comms_tx_rx_buffer[comms_spi_rx_byte++] = data;

				if (comms_spi_rx_byte >= comms_spi_rx_no_of_bytes_to_rx)
				{
					//---------------------------------
					//----- VALID PACKET RECEIVED -----
					//---------------------------------
					comms_rx_process_packet = 2;					//Flag for main function to process rx

					break;
				}
			}

		}
		INTClearFlag(INT_SOURCE_SPI_RX(COMMS_SPI_ID));				//Do after reading data as any data in RX FIFO will stop irq bit being cleared
	}
	
}

 

USEFUL?
We benefit hugely from resources on the web so we decided we should try and give back some of our knowledge and resources to the community by opening up many of our company’s internal notes and libraries through mini sites like this. We hope you find the site helpful.
Please feel free to comment if you can add help to this page or point out issues and solutions you have found, but please note that we do not provide support on this site. If you need help with a problem please use one of the many online forums.

Comments

Your email address will not be published. Required fields are marked *