Electrical – SPI refuses to send in dspic33

picspi

I'm trying to talk to an RFM22 wireless module. I'm having a hard time getting the SPI functional. I'm working with a dspic33ep512mc806. I'm debugging directly in hardware with a pickit3.

After configuring the SPI1 module I copy one piece of data into the SPI1BUF and wait for the receive to complete in a while loop. The code never gets past that while loop while(! SPI1STATbits.SPIRBF ); as though the SPI module is not running.

What could be the issue?

I've tried several different SPI configurations. I've tried using the SPI interrupt flag but that doesn't work either.

void init_SPI(void){
T3CONbits.TON = 0;
T3CONbits.TCKPS = 0b01; //prescalar to 8
PR3 = 500; //set timer 4 
TMR3 = 0; //reset timer 4 counter
T3CONbits.TON = 1; //Turn timer 4 on
//spi frequency 6MHz
//SPI1CON1bits.PPRE = 0b10; //4 prescalar
//SPI1CON1bits.SPRE = 0b011; //5 postscalar
RPINR20 = 0b1010100; //spi input pin RE4
RPOR5bits.RP82R = 0b000101; //spi ouput RE2
RPOR4bits.RP80R = 0b000110; //spi clock output RE0
//SPI1CON1bits.MSTEN = 1; //enable master mode
SPI1CON1 = 0x0120;
SPI1STAT = 0x8000; //enable spi rest settings default 
CS = 1;
delay_ms(10);
write(0x07, 0x01); // to ready mode}
*******************************************************************
*******************************************************************
void write(uint8_t address, char data){
//write any data byte to any single address
//adds a 0 to the MSB of the address byte (WRITE mode)
address |= 0x80;
CS = 0;
delay_ms(1);
txdata(address);
delay_ms(1);
txdata(data);
delay_ms(1);
CS = 1;}
****************************************
****************************************
char read(uint8_t address){
//returns the contents of any 1 byte register from any address
//sets the MSB for every address byte (READ mode)
char byte;
address &= 0x7F;
CS = 0;
txdata(address);
byte = rxdata();
CS = 1;
return byte;}
**************************************
**************************************
char rxdata(void){
SPI1BUF = 0x55;
while(! SPI1STATbits.SPIRBF );
//while (!(IFS0bits.SPI1IF));
//IFS0bits.SPI1IF = 0;
return SPI1BUF;}
**********************************************
**********************************************
void txdata(char data){
while( SPI1STATbits.SPITBF );
SPI1BUF = data;
while(! SPI1STATbits.SPIRBF );
//while (!(IFS0bits.SPI1IF));
//IFS0bits.SPI1IF = 0;}

#include <xc.h>

// DSPIC33EP512MC806 Configuration Bit Settings
// 'C' source line config statements

// FGS
#pragma config GWRP = OFF // General Segment Write-Protect bit (General Segment may be written)
#pragma config GSS = OFF // General Segment Code-Protect bit (General Segment Code protect is disabled)
#pragma config GSSK = OFF // General Segment Key bits (General Segment Write Protection and Code Protection is Disabled)

// FOSCSEL
#pragma config FNOSC = FRC // Initial Oscillator Source Selection bits (Internal Fast RC (FRC))
#pragma config IESO = ON // Two-speed Oscillator Start-up Enable bit (Start up device with FRC, then switch to user-selected oscillator source)

// FOSC
#pragma config POSCMD = HS // Primary Oscillator Mode Select bits (HS Crystal Oscillator Mode)
#pragma config OSCIOFNC = ON // OSC2 Pin Function bit (OSC2 is general purpose digital I/O pin)
#pragma config IOL1WAY = ON // Peripheral pin select configuration (Allow multiple reconfigurations)
#pragma config FCKSM = CSECMD // Clock Switching Mode bits (Clock switching is enabled,Fail-safe Clock Monitor is disabled)

// FWDT
#pragma config WDTPOST = PS32768 // Watchdog Timer Postscaler bits (1:32,768)
#pragma config WDTPRE = PR128 // Watchdog Timer Prescaler bit (1:128)
#pragma config PLLKEN = ON // PLL Lock Wait Enable bit (Clock switch to PLL source will wait until the PLL lock signal is valid.)
#pragma config WINDIS = OFF // Watchdog Timer Window Enable bit (Watchdog Timer in Non-Window mode)
#pragma config FWDTEN = OFF // Watchdog Timer Enable bit (Watchdog timer enabled/disabled by user software)

// FPOR
#pragma config FPWRT = PWR128 // Power-on Reset Timer Value Select bits (128ms)
#pragma config BOREN = ON // Brown-out Reset (BOR) Detection Enable bit (BOR is enabled)
#pragma config ALTI2C1 = OFF // Alternate I2C pins for I2C1 (SDA1/SCK1 pins are selected as the I/O pins for I2C1)

// FICD
#pragma config ICS = PGD2 // ICD Communication Channel Select bits (Communicate on PGEC2 and PGED2)
#pragma config RSTPRI = PF // Reset Target Vector Select bit (Device will obtain reset instruction from Primary flash)
#pragma config JTAGEN = OFF // JTAG Enable bit (JTAG is disabled)

// FAS
#pragma config AWRP = OFF // Auxiliary Segment Write-protect bit (Aux Flash may be written)
#pragma config APL = OFF // Auxiliary Segment Code-protect bit (Aux Flash Code protect is disabled)
#pragma config APLK = OFF // Auxiliary Segment Key bits (Aux Flash Write Protection and Code Protection is Disabled)

Best Answer

RE0, RE2 and RE4 have analog function on the pins. The PIC resets in analog mode so analog has to be disabled in order to use the pin for I/O.

Regarding SPI reads: Keep in mind the timing of the read/write is essentially simultaneous. i.e. if data is waiting on the slave and we want to receive it as a char then in the read function(pseudo): char ch; ch = writeSpi2(0); // write dummy value to slave. The slave value is now in ch return ch;