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.