Rev 199 | Rev 212 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
#include <xc.h>#include <plib.h>#include "defines.h"#include "SPI1.h"static SPI1_DATA *spi_data_ptr;void SPI1_Init(SPI1_DATA *data) {spi_data_ptr = data;spi_data_ptr->outBufferInd = 0;spi_data_ptr->outBufferLen = 0;#ifndef SPI1_WRITE_ONLYspi_data_ptr->inBufferInd = 0;spi_data_ptr->inBufferLen = 0;#endifINTDisableInterrupts();// Note: FIFO enhanced buffer depth is 4/8/16 for 32/16/8 bit widths// Alternative Configuration:// The third value is the SPI bitrate which is 1/2 the frequency of the// desired clock frequency. Thus 40Mhz / (20Mhz / 2) = 4.// Note: SPI_OPEN_TBE_NOT_FULL should only be used at >10Mhz speeds// SpiChnOpen(SPI_CHANNEL1, SPI_OPEN_MSTEN | SPI_OPEN_ENHBUF | SPI_OPEN_TBE_NOT_FULL | SPI_OPEN_RBF_NOT_EMPTY, 4);// INTSetVectorPriority(INT_SPI_1_VECTOR, INT_PRIORITY_LEVEL_6);// INTSetVectorSubPriority(INT_SPI_1_VECTOR, INT_SUB_PRIORITY_LEVEL_1);// INTClearFlag(INT_SPI1E);// INTClearFlag(INT_SPI1TX);// INTClearFlag(INT_SPI1RX);// FSCK = FPB / (2 * (SPIxBRG + 1))IEC0CLR = 0x03800000; // Disable all SPI interruptsSPI1CON = 0; // Stops and resets the SPI1.int tmp = SPI1BUF; // Clears the receive bufferIFS0CLR = 0x03800000; // Clear any existing eventIPC5CLR = 0x1F000000; // Clear the priorityIPC5SET = 0x19000000; // Set IPL=6, Subpriority 1SPI1BRG = 0x1; // Use FPB/4 clock frequencySPI1STATCLR = 0x40; // Clear the Overflow#ifndef SPI1_WRITE_ONLYIEC0SET = 0x01800000; // Enable RX and Error interrupts#endif// Enhanced buffer, SPI on, 8 bits transfer, SMP=1, Master mode// SPIxTXIF set on buffer empty, SPIxRXIF set on buffer not emptySPI1CON = 0x18225;INTEnableInterrupts();}#ifndef SPI1_WRITE_ONLYint SPI1_Read_Buffer(unsigned char *array, unsigned int count) {if (count > SPI1_BUFFER_SIZE)return 0;if (spi_data_ptr->inBufferLen == 0)return 0;// Save previous interrupt stateint prev = IEC0 & 0x03800000;// Temporarily disable interruptsIEC0CLR = 0x03800000;int ret = spi_data_ptr->inBufferLen;int i;for (i = 0; i < count; i++) {array[i] = spi_data_ptr->inBuffer[i];}// Reset buffer pointersspi_data_ptr->inBufferInd = 0;spi_data_ptr->inBufferLen = 0;// Restore saved interrupt stateIEC0SET = prev;// Return the number of valid bytes in the bufferreturn ret;}#endifint SPI1_Write(unsigned char *array, unsigned int count, void (*callback)(void)) {spi_data_ptr->callback_function = callback;if (count > SPI1_BUFFER_SIZE)return 0;if (spi_data_ptr->outBufferLen != 0)return 0;spi_data_ptr->outBufferLen = count;spi_data_ptr->outBufferInd = count-1;int i;for (i = 0; i < count; i++) {spi_data_ptr->outBuffer[i] = array[i];}IEC0SET = 0x02000000; // Enable TX interruptreturn 1;}void __ISR(_SPI_1_VECTOR, ipl6) __SPI_1_Interrupt_Handler(void) {#ifndef SPI1_WRITE_ONLY// Process SPI1 error flagif (IFS0bits.SPI1EIF) {// Clear the receive overflow bit if it is setif (SPI1STATbits.SPIROV) {SPI1STATbits.SPIROV = 0;}IFS0CLR = 0x00800000; // Clear the error flag}// Process SPI1 receive flagif (IFS0bits.SPI1RXIF) {int i;// Read the data received from the last transferint rxBufferCount = SPI1STATbits.RXBUFELM;if (spi_data_ptr->inBufferLen + rxBufferCount < SPI1_BUFFER_SIZE) {for (i = 0; i < rxBufferCount; i++) {spi_data_ptr->inBuffer[spi_data_ptr->inBufferInd] = SPI1BUF;spi_data_ptr->inBufferInd++;spi_data_ptr->inBufferLen++;}} else {// If buffer is full, discard data in enhanced bufferfor (i = 0; i < rxBufferCount; i++) {int tmp = SPI1BUF;}}IFS0CLR = 0x01000000; // Clear the RX flag}#endif// Process SPI1 transmit flagif (IFS0bits.SPI1TXIF) {int i;// Disable the transmit interrupt if all data has been sentif (spi_data_ptr->outBufferLen == 0) {IEC0CLR=0x02000000;if (spi_data_ptr->callback_function != NULL)(*spi_data_ptr->callback_function)();} else {// Start transmitting the data in the bufferint txBufferFree = 16 - SPI1STATbits.TXBUFELM;if (spi_data_ptr->outBufferLen > txBufferFree) {for (i = 0; i < txBufferFree; i++) {SPI1BUF = spi_data_ptr->outBuffer[spi_data_ptr->outBufferInd];spi_data_ptr->outBufferInd--;}spi_data_ptr->outBufferLen -= txBufferFree;} else {for (i = 0; i < spi_data_ptr->outBufferLen; i++) {SPI1BUF = spi_data_ptr->outBuffer[spi_data_ptr->outBufferInd];spi_data_ptr->outBufferInd--;}spi_data_ptr->outBufferLen = 0;}}IFS0CLR = 0x02000000; // Clear the TX flag}}