A discussion group for the PICMicro microcontroller. Also called the Microchip PIC, this list is dedicated to the use and abuse of this fine, simple, microcontroller. Close to topic posts are welcome, ie. general electronics.
Hello again,
I think I've exhausted myself over this one. SPI is supposed to be REALLY simple, right?
But, I can not get my SPI slave (PIC24) to do even recognize that SPI is happening at
all.
Here is the rest of the story:
My project has two MCU's in it. A dsPIC30F3012 that reads the sensors and performs all the
fun DSP stuff. It is the SPI Master and spits out data for the PIC24HJ64GP504 who will use
that sensor data to control a watercraft.
Because I needed the analog inputs on the dsPIC I am forced to do software SPI on it. No
problem, I setup an interrupt driven SPI master using Timer1. I've attached the code I've
been using for testing it below.
Now I've verified and re-verified that the PCB traces are good and that the Clock and Data
signals are making it from the dsPIC into the PIC24. Both parts are 3.3V driven and there
is nothing but copper from pin to pin. I will be using the Slave Select feature later, but
for testing purposes I am not.
I believe my PIC24 is good as I've gotten the UARTs to work. That also makes me believe
that I am doing the PPS stuff and Oscillator switching right.
Please someone, shine a light on this for me. =) I am using the MPLAB C30 compiler and a
PicKit2 debugger.
Here is the PIC24H code:
CODE
#include
unsigned int flag, token;
int main(void)
{
//Setup Ports & PPS
{
TRISA= 0b0000000000000000;
TRISB= 0b0111000010000000;
TRISC= 0b0000001000100000;
__builtin_write_OSCCONL(OSCCON & ~(1<<6));
//SPI2 - Slave
RPINR22bits.SDI2R=12; //RP12 - Data Input
RPINR22bits.SCK2R=13; //RP13 - Clock Input
RPINR23bits.SS2R=14; //RP14 - Slave Select Input
__builtin_write_OSCCONL(OSCCON | (1<<6));
}
//Set clock to External PLL @ 40MIPS w/ 10MHz EC Clock
{
PLLFBD=30;
CLKDIVbits.PLLPOST=0;
CLKDIVbits.PLLPRE=0;
__builtin_write_OSCCONH(0x03);
__builtin_write_OSCCONL(0x01);
while (OSCCONbits.COSC != 0b011);
while(OSCCONbits.LOCK!=1);
}
//Setup SPI2
{
SPI2BUF=0;
SPI2CON1bits.MODE16=1;
SPI2STATbits.SPIROV=0;
SPI2STATbits.SPIEN=1;
}
while(1)
{
while(!SPI2STATbits.SPIRBF);
token=SPI2BUF; //Break Point is SET HERE
if (SPI2STATbits.SPIROV) SPI2STATbits.SPIROV=0;
}
return(0);
}
I set a breakpoint at the commented code above and it never breaks. SFR Watching reveals
that the SPIRBF flag never get set, nothing gets set...
And here is the dsPIC Code:
CODE
#include
#define SCK LATCbits.LATC13
#define SDO LATCbits.LATC14
#define SS LATDbits.LATD0
volatile unsigned int SPITX;
volatile char SPIState;
unsigned int delay;
void __attribute__((interrupt,no_auto_psv)) _T1Interrupt(void);
void send_word(unsigned int dat);
void __attribute__((interrupt,no_auto_psv)) _T1Interrupt(void)
{
TMR1=0;
switch (SPIState)
{
case 32 : SCK=1; if(SPITX & 0b1000000000000000) SDO=1; else SDO=0; SPIState--; break;
case 31 : SCK=0; SPIState--; break;
case 30 : SCK=1; if(SPITX & 0b0100000000000000) SDO=1; else SDO=0; SPIState--; break;
case 29 : SCK=0; SPIState--; break;
case 28 : SCK=1; if(SPITX & 0b0010000000000000) SDO=1; else SDO=0; SPIState--; break;
case 27 : SCK=0; SPIState--; break;
case 26 : SCK=1; if(SPITX & 0b0001000000000000) SDO=1; else SDO=0; SPIState--; break;
case 25 : SCK=0; SPIState--; break;
case 24 : SCK=1; if(SPITX & 0b0000100000000000) SDO=1; else SDO=0; SPIState--; break;
case 23 : SCK=0; SPIState--; break;
case 22 : SCK=1; if(SPITX & 0b0000010000000000) SDO=1; else SDO=0; SPIState--; break;
case 21 : SCK=0; SPIState--; break;
case 20 : SCK=1; if(SPITX & 0b0000001000000000) SDO=1; else SDO=0; SPIState--; break;
case 19 : SCK=0; SPIState--; break;
case 18 : SCK=1; if(SPITX & 0b0000000100000000) SDO=1; else SDO=0; SPIState--; break;
case 17 : SCK=0; SPIState--; break;
case 16 : SCK=1; if(SPITX & 0b0000000010000000) SDO=1; else SDO=0; SPIState--; break;
case 15 : SCK=0; SPIState--; break;
case 14 : SCK=1; if(SPITX & 0b0000000001000000) SDO=1; else SDO=0; SPIState--; break;
case 13 : SCK=0; SPIState--; break;
case 12 : SCK=1; if(SPITX & 0b0000000000100000) SDO=1; else SDO=0; SPIState--; break;
case 11 : SCK=0; SPIState--; break;
case 10 : SCK=1; if(SPITX & 0b0000000000010000) SDO=1; else SDO=0; SPIState--; break;
case 9 : SCK=0; SPIState--; break;
case 8 : SCK=1; if(SPITX & 0b0000000000001000) SDO=1; else SDO=0; SPIState--; break;
case 7 : SCK=0; SPIState--; break;
case 6 : SCK=1; if(SPITX & 0b0000000000000100) SDO=1; else SDO=0; SPIState--; break;
case 5 : SCK=0; SPIState--; break;
case 4 : SCK=1; if(SPITX & 0b0000000000000010) SDO=1; else SDO=0; SPIState--; break;
case 3 : SCK=0; SPIState--; break;
case 2 : SCK=1; if(SPITX & 0b0000000000000001) SDO=1; else SDO=0; SPIState--; break;
case 1 : SCK=0; SPIState--; break;
case 0 : SCK=0; SDO=0; break;
default : SCK=0; SDO=0; SPIState=0; break;
}
IFS0bits.T1IF=0;
}
int main(void)
{
ADPCFG = 0b0000000000110000; //AN4 & AN5 Digital Inputs Other are Analog
TRISB=0b0000000011001111;
TRISC=0b0000000000000000;
TRISD=0b0000000000000000;
SCK=0;
SDO=0;
SS=1;
SPITX=0;
SPIState=0;
PR1=3000;
TMR1=0;
IFS0bits.T1IF=0;
IEC0bits.T1IE=1;
T1CONbits.TON=1;
while(1)
{
send_word(0xFF00);
while(delay--);
send_word(0xAAAA);
while(delay--);
send_word(0x00);
while(delay--);
}
return(0);
}
void send_word(unsigned int dat)
{
SPITX=dat;
SPIState=32;
while(SPIState);
}
I'll bet that SPI code is a little heavy handed and could be done more elegantly...
Here is the trace of the Data and Clock lines. Top trace is clock, bottom trace is data.
Here I am sending out data word 0xAAAA. Looks good to me. Clock speed is around 10KHz as
I've seriously slowed it down. I've tried it at 100KHz as well.
http://img13.imageshack.us/img13/227/img00004x.jpg
Thanks for your Help!
------------------------------------
to unsubscribe, go to http://www.yahoogroups.com and follow the instructions

(You need to be a member of piclist -- send a blank email to piclist-subscribe@yahoogroups.com )