Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Honored Contributor I
712 Views

SPI doesn't work at all

Hi,  

 

I need collect data from PIC18F4550 by SPI connection.  

The PIC is the Master running with Polarity = 0 and Phase = 1. 

The FPGA uses Altera IP SPI (3 wires Serial). All wires [SCK, MISO, MOSI and SS] are correct connected. 

 

The transfer works but with a lot of errors. A huge part of bytes toggle one or more bits. The problem can occur in all eight bits. Sometimes correct transfers are done. 

Tracking the origin of errors, I implement a function on PIC, controlling the SPI wires, for 

emulate the SPI transfer and certify about what's is happening. This function controls the time between bits and time between transfers. The code are below.  

 

In FPGA side, I'm polling for detection of new byte and print it in NIOS console.  

 

I tried different byte patterns for my tests and yours inverse.  

 

Pattern from PIC to FPGA 

01010101 

11001100 

11110000 

00111100 

 

Pattern from FPGA to PIC 

1111 1111 

0000 0000 

 

In all cases, except for [PIC 0xFF -> FPGA], errors occur. In case of [PIC 0x00 <-> 0x00 FPGA] Errors occur too.  

 

The cable has 10cm soldered direct in hosing for PIC chip. A picture is worth a thousand words. dl dot dropbox dot com/u/68170/DSC00273.JPG 

 

After all tests, I believe that FPGA is the problem. Yes, I tried use other 4 wires for connection in different pins of I/O Port of my DE2-70. Same error behavior.  

 

After this detailed description of my problems,  

if someone can give-me some light of problem, I'll thanks a lot 

 

So let's to the codes: 

 

PIC18F4550 first. Pic running using 3.3V of FPGA 

 

char SPIMasterBruteForce(char data) { //Phase 1 //Polarity/Enable 0 # define DELAY_SPI Delay10KTCYx(240); // about 200-300 milliseconds typedef volatile near union { struct{ unsigned DT0:1; unsigned DT1:1; unsigned DT2:1; unsigned DT3:1; unsigned DT4:1; unsigned DT5:1; unsigned DT6:1; unsigned DT7:1; }; unsigned data; } DATA; DATA DATA_OUT; DATA DATA_IN; DATA_OUT.data = 0; // Clean for clean DATA_IN.data = 0; // DATA_OUT.data = data; PORTAbits.RA5=1; // SS Inactive. DELAY_SPI; PORTDbits.RD1=1; // LED ON // Not necessary clock cycle before transfer. DELAY_SPI; PORTBbits.RB1=1; // SCK DELAY_SPI; PORTBbits.RB1=0; // SCK DELAY_SPI; // PORTBbits.RB1=0; // SCK (LOW) PORTAbits.RA5=0; // SS Active (LOW); DELAY_SPI; DELAY_SPI; DELAY_SPI; // 7////////////////////////////// PORTBbits.RB1=1; // SCK Propagate Bit PORTCbits.RC7=DATA_OUT.DT7; // SDO DELAY_SPI; DATA_IN.DT7=PORTBbits.RB0; // SDI Capture Bit PORTBbits.RB1=0; // SCK DELAY_SPI; // 6////////////////////////////// PORTBbits.RB1=1; // SCK (HIGH) PORTCbits.RC7=DATA_OUT.DT6; // SDO DELAY_SPI; DATA_IN.DT6=PORTBbits.RB0; // SDI PORTBbits.RB1=0; // SCK (LOW) DELAY_SPI; // 5////////////////////////////// PORTBbits.RB1=1; // SCK PORTCbits.RC7=DATA_OUT.DT5; // SDO DELAY_SPI; DATA_IN.DT5=PORTBbits.RB0; // SDI PORTBbits.RB1=0; // SCK DELAY_SPI; // 4////////////////////////////// PORTBbits.RB1=1; // SCK PORTCbits.RC7=DATA_OUT.DT4; // SDO DELAY_SPI; DATA_IN.DT4=PORTBbits.RB0; // SDI PORTBbits.RB1=0; // SCK DELAY_SPI; // 3////////////////////////////// PORTBbits.RB1=1; // SCK PORTCbits.RC7=DATA_OUT.DT3; // SDO DELAY_SPI; DATA_IN.DT3=PORTBbits.RB0; // SDI PORTBbits.RB1=0; // SCK DELAY_SPI; // 2////////////////////////////// PORTBbits.RB1=1; // SCK PORTCbits.RC7=DATA_OUT.DT2; // SDO DELAY_SPI; DATA_IN.DT2=PORTBbits.RB0; // SDI PORTBbits.RB1=0; // SCK DELAY_SPI; // 1////////////////////////////// PORTBbits.RB1=1; // SCK PORTCbits.RC7=DATA_OUT.DT1; // SDO DELAY_SPI; DATA_IN.DT1=PORTBbits.RB0; // SDI PORTBbits.RB1=0; // SCK DELAY_SPI; // 0 ///////////////////////////// PORTBbits.RB1=1; // SCK PORTCbits.RC7=DATA_OUT.DT0; // SDO DELAY_SPI; DATA_IN.DT0=PORTBbits.RB0; // SDI PORTBbits.RB1=0; // SCK DELAY_SPI; ////////////////////////////////// DELAY_SPI; DELAY_SPI; DELAY_SPI; PORTAbits.RA5=1; // SS inactive (HIGH) ; // Not necessary clock cycle after transfer. DELAY_SPI; PORTBbits.RB1=1; DELAY_SPI; PORTBbits.RB1=0; DELAY_SPI; PORTDbits.RD1=0; // LED OFF return DATA_IN.data; } void SPIMasterMySPITest(void) { // Setup IO Pins in PIC TRISCbits.TRISC0 = 0; //LED Green - Output TRISDbits.TRISD1 = 0; //LED Yellow - Output TRISDbits.TRISD0 = 0; //LED Red - Output PORTCbits.RC0 = 0; // LED Green - OFF PORTDbits.RD1 = 0; // LED Yellow- OFF PORTDbits.RD0 = 0; // LED Red - OFF TRISBbits.TRISB1 = 0; // SCK - Output PORTBbits.RB1 = 0; // SCK - (LOW) TRISBbits.TRISB0 = 1; // SDI - Input (MISO) PORTBbits.RB0 = 0; // Not necessary - Force cleaning of bit register TRISCbits.TRISC7 = 0; // SDO - Output (MOSI) PORTCbits.RC7 = 0; // SDO - (LOW) TRISAbits.TRISA5 = 0; // SS - Output PORTAbits.RA5 = 1; // SS - (LOW) while (1) { PORTDbits.RD1=1; // Yellow LED ON Delay10KTCYx(240); // BIG Delay between transfers SPIMasterBruteForce(0b10101010); // Sending the number 170 for test PORTDbits.RD1=0; // Yellow LED ON Delay10KTCYx(240); // BIG Delay between transfers } } void main(void) { ADCON0 = 0x00; // ADC OFF ADCON1 = 0x0F; // ALL I/O PINS DIGITAL CMCON = 0x07; // COMPARATOR DISCONNECTED FROM PORT(A) while (1) { SPIMasterMySPITest(); } } 

 

 

NOW FPGA CODE 

 

void SPIPolling(void) { if (IORD_ALTERA_AVALON_SPI_STATUS(SPI_BASE) & ALTERA_AVALON_SPI_STATUS_RRDY_MSK ) { printf(": %d \n", (char)IORD_ALTERA_AVALON_SPI_RXDATA(SPI_BASE)); } if (IORD_ALTERA_AVALON_SPI_STATUS(SPI_BASE) & ALTERA_AVALON_SPI_STATUS_TRDY_MSK ) { IOWR_ALTERA_AVALON_SPI_TXDATA(SPI_BASE, 0); //255 ); } } int main() { unsigned char count = 0; unsigned int count2 = 25000; printf("Hello from Nios II!\n"); while(1) { SPIPolling(); // Some lights to indicate that my NIOS is alive. IOWR_ALTERA_AVALON_PIO_DATA(LED_BASE, count ) ; count++; if (count==255) count = 0; while (count2) count2--; if (!count2) count2 = 25000; } return 0; }
0 Kudos
2 Replies
Highlighted
Honored Contributor I
19 Views

Are you sure that the clock on the FPGA's SPI interface isn't too fast for the PIC controller? 

Try to put a signaltap probe on the SPI interface to see what the signals look like.
0 Kudos
Highlighted
Honored Contributor I
19 Views

I notice, that are writing SDO and reading SDI after SCK rising edge, which correspondends to no usual SPI mode. I don't see, which SPI mode is implemented in the FPGA, but I guess that it doesn't match the master's behaviour, which would explain well the erratic result. 

 

P.S.: If you intend SPI mode 0, you have to set SDO before the rising clock edge.
0 Kudos