/* * used to set the directions of the ports (like when you use TRIS registers) * this function is actually identical to setGPIO, but I think a different * for setting the port directio helps with keeping the code organized */ void setIODIR(char address, char dir) { CS = 0; WriteSPI1(0x40); // write command (0b0100[A2][A1][A0][R/W]) also equal to 0x40 WriteSPI1(address); // select IODIRB WriteSPI1(dir); // set direction CS = 1; }
/******************************************************************** * Function Name: LDByteWriteSPI * * Parameters: OpCode/register, data. * * Description: Writes Data Byte to SPI device * * * ********************************************************************/ void LDByteWriteSPI(unsigned char OpCode, unsigned char Data ) { CS_nRF = 0; // Select Device WriteSPI1 ( OpCode ); // Send Write OpCode WriteSPI1 ( Data ); // Write Byte to device CS_nRF = 1; // Deselect device SPI1STATbits.SPITBF = 0; //Clear Transmit Buffer Full Status bit }
/* * used to set the values of the ports ( think of it as when you use a PORT register) */ void setGPIO(char address, char value) { CS = 0; // we are about to initiate transmission // pins A2,A1 and A0 of the MCP23S17 chip are equal to 0 because they are grounded // we are just going to be writing so R/W=0 also WriteSPI1(0x40); // write command 0b0100[A2][A1][A0][R/W] = 0b01000000 = 0x40 WriteSPI1(address); // select register by providing address WriteSPI1(value); // set value CS = 1; // we are ending the transmission }
/******************************************************************** * Function Name: LDCommandWriteSPI * * Parameters: OpCode/register. * * Description: Writes Command to SPI device * * * ********************************************************************/ void LDCommandWriteSPI(unsigned char OpCode ) { CS_nRF = 0; // Select Device WriteSPI1 ( OpCode ); // Send Write OpCode CS_nRF = 1; // Deselect device SPI1STATbits.SPITBF = 0; //Clear Transmit Buffer Full Status bit }
void spiSlaveInit(void){ // SPI1CON1 Register Settings SPI1CON1bits.DISSCK = 0; //Internal Serial Clock is Enabled. SPI1CON1bits.DISSDO = 0; //SDOx pin is controlled by the module. SPI1CON1bits.MODE16 = 1; //Communication is word-wide (16 bits). SPI1CON1bits.SMP = 0; //Cleared in slave mode. SPI1CON1bits.CKE = 0; //Serial output data changes on transition from //Idle clock state to active clock state SPI1CON1bits.CKP = 0; //Idle state for clock is a low level; //active state is a high level SPI1CON1bits.SSEN = 1; // SS Used in slave mode SPI1CON1bits.MSTEN = 0; //Slave Mode Enabled // Configure the clock for 10 MHz SPI1CON1bits.SPRE = 7; //Secondary prescaler to 1:1 SPI1CON1bits.PPRE = 2; //Primary prescaler 4:1 // Enable the module SPI1STATbits.SPIEN = 1; //Enable SPI Module // write the buffer to start getting data // this will not be sent until data is received WriteSPI1(0x0000); // Enable the interrupts IFS0bits.SPI1IF = 0; IPC2bits.SPI1IP = 6; IEC0bits.SPI1IE = 1; }
int SPI1_transfer( int data) { LATBbits.LATB0 = 0; // set pin RB0 low / disable latch while (TxBufFullSPI1()); // ensure buffer is free before writing WriteSPI1(data); // send the data through SPI while (SPI1STATbits.SPIBUSY); // blocking wait for end of transaction LATBbits.LATB0 = 1; // set pin RB0 high / enable latch }
/******************************************************************** * Function Name: LDByteReadSPI * * Parameters: EE memory control, address, pointer and * * length bytes. * * Description: Reads data Byte from SPI EE memory device. * * This routine can be used for any SPI * * EE memory device with 1 byte of address * * * ********************************************************************/ unsigned char LDByteReadSPI(unsigned char OpCode, unsigned char *rdptr, unsigned char length ) { CS_nRF = 0; // Select Device WriteSPI1( OpCode ); // Send Read OpCode or register getsSPI( rdptr, length ); // read in multiple bytes CS_nRF = 1; // Deselect Device return ( 0 ); }
// Interrupt service routine for SPI1 Slave void __attribute__((__interrupt__, no_auto_psv)) _SPI1Interrupt(void){ static unsigned int spiBufIdx = 1; unsigned int dataRead; // get the next index ready for writting // if the SPI index is less than the size of the buffer if (spiBufIdx < SPIBUFSIZE){ // request the next data WriteSPI1(spiBufIdx); }else{ // if it is equals to the size of the buffer if (spiBufIdx == SPIBUFSIZE ){ // signal that this is the end WriteSPI1(ENDSPI); } else { // if it is greater than the buffer, then write a zero // no more data will be comming for this cycle after this // interrupt WriteSPI1(0x0000); } } // read the received data dataRead = ReadSPI1(); // if the received data is the begin indication if (dataRead == BEGINSPI){ // just increment the outbuffer, discard the data read spiBufIdx++; } else{ // a data was received // Post-increment the SPIBUF index and assign the data // accordingly spiRxBuf[currentBuffer][(spiBufIdx++) -2] = dataRead; // if you reach the limit if (spiBufIdx > SPIBUFSIZE){ // Reset the index spiBufIdx = 1; // switch the working buffers lastBuffer = currentBuffer; currentBuffer = currentBuffer > 2? 0:currentBuffer+1; } } // clear the interrupt IFS0bits.SPI1IF = 0; }
/******************************************************************** * Function Name: LDPageWriteSPI * * Parameters: Opcode, pointer addr, string length * * Description: Writes data string to SPI device * * OpCode is the register that receives the * * data * * * ********************************************************************/ unsigned char LDPageWriteSPI( unsigned char OpCode, unsigned char *wrptr, unsigned char strlength ) { CS_nRF = 0; // Select Device WriteSPI1 ( OpCode ); // send OpCode PutStringSPI ( wrptr, strlength ); // Write Page to device CS_nRF = 1; // Deselect Device SPI1STATbits.SPITBF = 0; //Clear Transmit Buffer Full Status bit return ( 0 ); }
unsigned char readnRFbyte(unsigned char OpCode ) { char rdata; CS_nRF = 0; // Select Device WriteSPI1( OpCode ); // Send Read OpCode or register rdata = ReadSPI1(); // read in one bytes CS_nRF = 1; // Deselect Device return ( rdata ); }
void spiSend(unsigned char * data2Send){ unsigned char i; unsigned int rcvdIdx = 0; // First send a dummy value to let know the // slave that you are ready to transmit WriteSPI1(BEGINSPI); while(!DataRdySPI1()); rcvdIdx = ReadSPI1(); // While we do not receive the flag indicating // that we are done, keep sending the requested // index while (rcvdIdx != ENDSPI){ WriteSPI1(data2Send[rcvdIdx]); while(!DataRdySPI1()); rcvdIdx = ReadSPI1(); } }
//instead of writing SPI code repeatedly, made a function. //Used various chip selects on the same channel to change //values of various different digital potentiometers void deliverSPICh1Datum(int datum){ // test for ready while (TxBufFullSPI1()); // write to spi2 WriteSPI1(Digipot_config_chan_A | datum); // test for done while (SPI1STATbits.SPIBUSY); // wait for end of transaction // CS high // mPORTBSetBits(BIT_4); // end transaction }
void spiSend(unsigned char * data2Send) { unsigned char i; unsigned int rcvdIdx = 0; //static unsigned char sendSPIData = 1; // Send the amount of data received via SPI for(i = 1; i <= data2Send[0]; i += 1 ) { WriteSPI1(data2Send[i]); while(!DataRdySPI1()); rcvdIdx = ReadSPI1(); } }
/***************************************************************************** Function: void DRV_SPI_TxRx(void) Summary: Transmits and receives SPI bytes Description: Transmits and receives N bytes of SPI data. Precondition: None Parameters: pTxBuf - pointer to SPI tx data txLen - number of bytes to Tx pRxBuf - pointer to where SPI rx data will be stored rxLen - number of SPI rx bytes caller wants copied to p_rxBuf Returns: None Remarks: Will clock out the larger of txLen or rxLen, and pad if necessary. *****************************************************************************/ void DRV_SPI_TxRx(SpiChannel chn, uint8_t *pTxBuf, uint16_t txLen, uint8_t *pRxBuf, uint16_t rxLen) { uint16_t byteCount; uint16_t i; uint8_t rxTrash; /* total number of byte to clock is whichever is larger, txLen or rxLen */ byteCount = (txLen >= rxLen)?txLen:rxLen; for (i = 0; i < byteCount; ++i) { /* if still have bytes to transmit from tx buffer */ if ((txLen > 0) && (pTxBuf != 0)) { #if defined (__C32__) SpiChnWriteC(chn, *pTxBuf++); #elif defined (__C30__) switch(chn) { case 1: WriteSPI1(*pTxBuf++); break; case 2: WriteSPI2(*pTxBuf++); break; } #endif --txLen; } /* else done writing bytes out from tx buffer */ else { #if defined (__C32__) SpiChnWriteC(chn, 0); /* clock out a "don't care" byte */ #elif defined (__C30__) switch(chn) { case 1: WriteSPI1(0x00); break; case 2: WriteSPI2(0x00); break; } #endif } /* wait until tx/rx byte to completely clock out */ WaitForDataByte(chn); /* if still have bytes to read into rx buffer */ if ((rxLen > 0) && (pRxBuf != 0)) { #if defined (__C32__) *pRxBuf++ = SpiChnReadC(chn); #elif defined (__C30__) switch(chn) { case 1: *pRxBuf++ = ReadSPI1(); break; case 2: *pRxBuf++ = ReadSPI2(); break; } #endif --rxLen; } /* else done reading bytes into rx buffer */ else { #if defined (__C32__) rxTrash = SpiChnReadC(chn); /* read and throw away byte */ #elif defined (__C30__) switch(chn) { case 1: rxTrash = ReadSPI1(); break; case 2: rxTrash = ReadSPI2(); break; } #endif } } /* end for loop */ }