0,0 → 1,120 |
#include <xc.h> |
#include <plib.h> |
#include "defines.h" |
#include "SPI1.h" |
|
static SPI1_DATA *spi_data_ptr; |
|
void SPI1_Init(SPI1_DATA *data, void (*rx_callback)(char)) { |
spi_data_ptr = data; |
spi_data_ptr->buffer_out_ind = 0; |
spi_data_ptr->buffer_out_len = 0; |
spi_data_ptr->rx_callback = rx_callback; |
|
INTDisableInterrupts(); |
|
// 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 interrupts |
SPI1CON = 0; // Stops and resets the SPI1. |
int tmp = SPI1BUF; // Clears the receive buffer |
IFS0CLR = 0x03800000; // Clear any existing event |
IPC5CLR = 0x1F000000; // Clear the priority |
IPC5SET = 0x19000000; // Set IPL=6, Subpriority 1 |
SPI1BRG = 0x1; // Use FPB/4 clock frequency |
SPI1STATCLR = 0x40; // Clear the Overflow |
#ifndef SPI_WRITE_ONLY |
IEC0SET = 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 empty |
SPI1CON = 0x18225; |
|
INTEnableInterrupts(); |
} |
|
int SPI1_Write(char *array, int length, void (*tx_callback)(void)) { |
spi_data_ptr->tx_callback = tx_callback; |
|
if (length > SPI1_BUFFER_OUT_SIZE) |
return 0; |
if (spi_data_ptr->buffer_out_len != 0) |
return 0; |
|
// Put the data to send into the outbound buffer |
spi_data_ptr->buffer_out_len = length; |
spi_data_ptr->buffer_out_ind = length-1; |
int i; |
for (i = 0; i < length; i++) { |
spi_data_ptr->buffer_out[i] = array[i]; |
} |
IEC0SET = 0x02000000; // Enable TX interrupt |
return 1; |
} |
|
void __ISR(_SPI_1_VECTOR, ipl6) __SPI_1_Interrupt_Handler(void) { |
#ifndef SPI_WRITE_ONLY |
// Process SPI1 error flag |
if (IFS0bits.SPI1EIF) { |
// Clear the receive overflow bit if it is set |
if (SPI1STATbits.SPIROV) { |
SPI1STATbits.SPIROV = 0; |
} |
IFS0CLR = 0x00800000; // Clear the error flag |
} |
|
// Process SPI1 receive flag |
if (IFS0bits.SPI1RXIF) { |
int i; |
// Read the data received from the last transfer |
int rxBufferCount = SPI1STATbits.RXBUFELM; |
for (i = 0; i < rxBufferCount; i++) { |
char c = SPI1BUF; |
// Call the RX callback function on the received data |
if (spi_data_ptr->rx_callback != NULL) |
(*spi_data_ptr->rx_callback)(c); |
} |
IFS0CLR = 0x01000000; // Clear the RX flag |
} |
#endif |
|
// Process SPI1 transmit flag |
if (IFS0bits.SPI1TXIF && IEC0bits.SPI1TXIE) { |
int i; |
// Disable the transmit interrupt if all data has been sent |
if (spi_data_ptr->buffer_out_len == 0) { |
IEC0CLR=0x02000000; |
if (spi_data_ptr->tx_callback != NULL) |
(*spi_data_ptr->tx_callback)(); |
} else { |
// Start transmitting the data in the buffer |
int txBufferFree = 16 - SPI1STATbits.TXBUFELM; |
if (spi_data_ptr->buffer_out_len > txBufferFree) { |
for (i = 0; i < txBufferFree; i++) { |
SPI1BUF = spi_data_ptr->buffer_out[spi_data_ptr->buffer_out_ind]; |
spi_data_ptr->buffer_out_ind--; |
} |
spi_data_ptr->buffer_out_len -= txBufferFree; |
} else { |
for (i = 0; i < spi_data_ptr->buffer_out_len; i++) { |
SPI1BUF = spi_data_ptr->buffer_out[spi_data_ptr->buffer_out_ind]; |
spi_data_ptr->buffer_out_ind--; |
} |
spi_data_ptr->buffer_out_len = 0; |
} |
} |
IFS0CLR = 0x02000000; // Clear the TX flag |
} |
} |