Rev 158 | Blame | Last modification | View Log | Download | RSS feed
#include <xc.h>#include <stdio.h>#include <string.h>#include "defines.h"#include "base_SPI.h"#include "base_UART.h"static SPI_DATA *spi_data_p;void SPI2_Init(SPI_DATA *data, char speed) {spi_data_p = data;// Set up SPI2 with specified pinsRPINR22 = PPS_SPI2_CLK_IN; // SPI2 CLK InputPPS_SPI2_CLK_OUT = 11; // SPI2 CLK Output#ifndef SPI2_WRITE_ONLYRPINR21 = PPS_SPI2_MISO; // SPI2 Data InputSPI_MISO_TRIS = 1; // SPI2 data in pin (MISO)#endifSPI_CLK_TRIS = 0; // SPI2 clock pinPPS_SPI2_MOSI = 10; // SPI2 Data Output (MOSI)SPI_MOSI_TRIS = 0; // SPI2 data out pin (MOSI)SPI_SLAVE_SELECT_TRIS = 0; // SPI2 slave selectSPI_SLAVE_SELECT_LAT = 1; // SPI2 SS high (Idle)SPI_RESET_TRIS = 0; // SPI2 resetSPI_RESET_LAT = 1; // SPI2 reset active lowSPI_DC_SELECT_TRIS = 0; // SPI2 D/C selectSPI_DC_SELECT_LAT = 0;SSP2STATbits.SMP = 0; // Input is sampled in the middle of data output timeSSP2STATbits.CKE = 0; // Transmit occurs on transition from Idle to active clock stateSSP2CON1bits.SSPM = speed;SSP2CON1bits.CKP = 1; // Idle state for clock is a high levelSSP2CON1bits.SSPEN = 1; // Enable MSSP module#ifdef SPI2_USE_INTERRUPTPIE3bits.SSP2IE = 1; // Enable MSSP2 interrupt#elsePIE3bits.SSP2IE = 0;#endif#ifndef SPI2_WRITE_ONLYspi_data_p->buffer_in_len = 0;spi_data_p->buffer_in_read_ind = 0;spi_data_p->buffer_in_write_ind = 0;#endifspi_data_p->buffer_out_ind = 0;spi_data_p->buffer_out_len = 0;}void SPI2_Write(char *msg, unsigned int length) {unsigned int i = 0;#ifdef SPI2_USE_INTERRUPTspi_data_p->buffer_out_len = length;spi_data_p->buffer_out_ind = 1;for (i = 0; i < length; i++) {spi_data_p->buffer_out[i] = msg[i];}SPI_SLAVE_SELECT_LAT = 0; // Bring SS line lowSSP2BUF = spi_data_p->buffer_out[0]; // Transmit first byte#elseSPI_SLAVE_SELECT_LAT = 0;while (i != length) {SSP2BUF = msg[i];i++;while (!SSP2STATbits.BF);#ifndef SPI2_WRITE_ONLYspi_data_p->buffer_in[spi_data_p->buffer_in_write_ind] = SSP2BUF;if (spi_data_p->buffer_in_write_ind == MAXSPIBUF - 1) {spi_data_p->buffer_in_write_ind = 0;} else {spi_data_p->buffer_in_write_ind++;}spi_data_p->buffer_in_len++;#else// Read data in buffer to clear itchar tmp = SSP2BUF;#endif}SPI_SLAVE_SELECT_LAT = 1;#endif}void SPI2_Write_Repeat(char c, unsigned int length) {#ifdef SPI2_USE_INTERRUPT// TODO Implement interrupts for SPI2#elseunsigned int i = 0;SPI_SLAVE_SELECT_LAT = 0;while (i != length) {SSP2BUF = c;i++;while (!SSP2STATbits.BF);#ifndef SPI2_WRITE_ONLYspi_data_p->buffer_in[spi_data_p->buffer_in_write_ind] = SSP2BUF;if (spi_data_p->buffer_in_write_ind == MAXSPIBUF - 1) {spi_data_p->buffer_in_write_ind = 0;} else {spi_data_p->buffer_in_write_ind++;}spi_data_p->buffer_in_len++;#else// Read data in buffer to clear itchar tmp = SSP2BUF;#endif}SPI_SLAVE_SELECT_LAT = 1;#endif}void SPI2_DMA_Init(void) {DMACON1bits.SSCON0 = 0;DMACON1bits.SSCON1 = 0; // DYLINTEN is software programmableDMACON1bits.TXINC = 1; // TXADDR is automatically incrementedDMACON1bits.RXINC = 0; // RXADDR is not automatically incrementedDMACON1bits.DUPLEX0 = 1;DMACON1bits.DUPLEX1 = 0; // Half-duplex mode, transmission onlyDMACON1bits.DLYINTEN = 0; // Interrupt is disabledDMACON2bits.DLYCYC = 0b0000; // Delay time of 1 cycle between bytesDMACON2bits.INTLVL = 0b0000; // Interrupt on transfer complete}void SPI2_DMA_Start(unsigned int length, void* TXADDR, void* RXADDR) {// Set length of message to transmitDMABCH = (char)(length-1 >> 8);DMABCL = (char)(length-1);// Set sourcing addressTXADDRH = (char)((int)TXADDR >> 8);TXADDRL = (char)((int)TXADDR);// Set receiving addressRXADDRH = (char)((int)RXADDR >> 8);RXADDRL = (char)((int)RXADDR);DMACON1bits.DMAEN = 1; // Start transmission}#ifndef SPI2_WRITE_ONLYvoid SPI2_Recv_Interrupt_Handler() {char c;if (SSP2STATbits.BF) { // Check if data receive flag is setif (spi_data_p->buffer_in_len == MAXSPIBUF - 1) {char output[64];sprintf(output, "SPI2: (ERROR) buffer overflow\r\n");DBG_PRINT_SPI(output, strlen(output));c = SSP2BUF; // Read SSP2BUF to clear it} else {// Save received data into bufferspi_data_p->buffer_in[spi_data_p->buffer_in_write_ind] = SSP2BUF;if (spi_data_p->buffer_in_write_ind == MAXSPIBUF - 1) {spi_data_p->buffer_in_write_ind = 0;} else {spi_data_p->buffer_in_write_ind++;}spi_data_p->buffer_in_len++;// Put next byte in SSP2BUF for transmitif (spi_data_p->buffer_out_ind != spi_data_p->buffer_out_len) {SSP2BUF = spi_data_p->buffer_out[spi_data_p->buffer_out_ind];spi_data_p->buffer_out_ind++;} else {SPI_SLAVE_SELECT_LAT = 1; // Bring SS line highspi_data_p->buffer_out_ind = 0;spi_data_p->buffer_out_len = 0;}}}}void SPI2_Read(char length) {#ifdef SPI2_USE_INTERRUPTspi_data_p->buffer_out_len = length;spi_data_p->buffer_out_ind = 1;for (char i = 0; i < length; i++) {spi_data_p->buffer_out[i] = 0x0;}SPI_SLAVE_SELECT_LAT = 0; // Bring SS line lowSSP2BUF = spi_data_p->buffer_out[0]; // Transmit first byte#elseSPI_SLAVE_SELECT_LAT = 0;for (char i = 0; i < length; i++) {SSP2BUF = 0x0;while (!SSP2STATbits.BF);spi_data_p->buffer_in[spi_data_p->buffer_in_write_ind] = SSP2BUF;if (spi_data_p->buffer_in_write_ind == MAXSPIBUF - 1) {spi_data_p->buffer_in_write_ind = 0;} else {spi_data_p->buffer_in_write_ind++;}spi_data_p->buffer_in_len++;}SPI_SLAVE_SELECT_LAT = 1;#endif}char SPI2_Buffer_Len() {return spi_data_p->buffer_in_len;}char SPI2_Read_Buffer(char* buffer) {char i = 0;while (spi_data_p->buffer_in_len != 0) {buffer[i] = spi_data_p->buffer_in[spi_data_p->buffer_in_read_ind];i++;if (spi_data_p->buffer_in_read_ind == MAXSPIBUF - 1) {spi_data_p->buffer_in_read_ind = 0;} else {spi_data_p->buffer_in_read_ind++;}spi_data_p->buffer_in_len--;}return i;}#endif