Pic32 W5500 spi

#1

Hi there,
I have one of the W5500 Modules and a PIC32MX795 on an olimex board.
I have this and a small 16x1 lcd wired up on some perfboard.
On boot i can ping the W5500 at its default address of 192.168.1.2 so i know the board is working.
I have copyed the simple driver code iolibrary_bsd_ethernet into my mplab project compiles fine with no errors
( as part of project not as a library )
i uncomented the following two defines in the wizchip_conf.c
.IF.SPI._read_byte = wizchip_spi_readbyte,
.IF.SPI._write_byte = wizchip_spi_writebyte
I then implineted
wizchip_cs_select(void) and wizchip_cs_deselect(void) Watching with a scope these work fine.
in wizchip_spi_writebyte(uint8_t wb) i call my function 'char writeSPI3( char i )'
which contains {
SPI3BUF = i; // write to buffer for TX
while( !SPI3STATbits.SPIRBF ); // wait for TX complete
return SPI3BUF; // read the received values
}
for the uint8_t wizchip_spi_readbyte(void) function i do
{
unsigned char Dummy = 0;
return writeSPI3( Dummy ); // send a dummy byte and catch the returned byte.
}
in main i open the spi chanel with this ( it does talk an spi lcd in another project )
SpiChnOpen(SPI_CHANNEL3, SPI_OPEN_CKP_HIGH |SPI_OPEN_MSTEN |SPI_OPEN_MODE8 | SPI_OPEN_ON , 25);
then i do a
unsigned char A = 0;
WIZCHIP_READ_BUF(0x0039, &A, 1);
sprintf(tbuff, "A=%X ",A);
I get 2B as a return value but reading elsware in the forum i hather i am meant to get 0x04
by fiddling auround with the open mode i can get 2B or 1D or 1 but not 0x04 any suggestions please i am going nuts
trying to get the basic spi code working…

#2

Hi,
You maybe have some problem about SPI drive…

Check another register as RTR and RCR instead of VERSIONR.
RTR & RCR reset value have 0x07D0 & 0x08, resepectively.

And Probe the SPI signal using Oscilloscope and post it on here.

Thank you.

#3

Hi there,
In responce to my own post, I have learnt a fair bit and am now starting to make a little progress…
This information is mainly going to be of use to those wanting to use the W5500 module with the microchip pic32.
Specifically i am working with an Olimex PIC32-T795 Development board This comes with the PIC32MX795F512H Micro.
At 1st i got absolutly noware at all then id desperation i checked with a scope and found i had the mosi and miso lines crossed over. After sorting that out i managed to open the spi channel with the right params to talk with the W5500

This is the spi-channel open statement i am useing the 25 on the end is the clock divisor but i have not yet reached the point were speed matters.
SpiChnOpen(SPI_CHANNEL3, SPI_OPEN_CKE_REV |SPI_OPEN_MSTEN |SPI_OPEN_MODE8 | SPI_OPEN_ON , 25);

In my system.h i have the following 4 defines for controlling the reset pin and the chip select pin.
#define WIZ550_SCSnSet() {LATDSET=_LATD_LATD0_MASK;} // Wiz550 scsn pin
#define WIZ550_SCSnClr() {LATDCLR=_LATD_LATD0_MASK;}
#define WIZ550_RSTSet() {LATDSET=_LATD_LATD11_MASK;} // Wiz550 reset pin
#define WIZ550_RSTClr() {LATDCLR=_LATD_LATD11_MASK;}

Then in the io library files i can just use WIZ550_SCSnClr(); to enable the slave selct line ( pull it low )
and of course WIZ550_SCSnSet(); to de_select the module.

in my system.c file i have this.
char writeSPI3( char i )
{
SPI3BUF = i; // write to buffer for TX
while( !SPI3STATbits.SPIRBF ); // wait for TX complete
return SPI3BUF; // read the received values
}

So that in the iolibrary i have this ( i sent a null byte to get the return value )
uint8_t wizchip_spi_readbyte(void)
{
return writeSPI3( 0x00 );
};
and this for the data send.
void wizchip_spi_writebyte(uint8_t wb)
{
writeSPI3( wb );
};

i also had to uncomment the following two lines in the _WIZCHIP WIZCHIP = structure.
.IF.SPI._read_byte = wizchip_spi_readbyte,
.IF.SPI._write_byte = wizchip_spi_writebyte

At this point i can in my main. file i can do this
unsigned char bbb[20];
WIZCHIP_READ_BUF(SIPR, bbb, 4);
lcd_clear();
sprintf(tbuff,"%d.%d.%d.%d",bbb[0],bbb[1],bbb[2],bbb[3]);
lcd_puts(tbuff);
DelayMs(1000);
This prints out the default ip address of the module

and this prints out the version number for the module.
C = getVERSIONR();
lcd_clear();
sprintf(tbuff,“Wiz5500 Ver=%d”,C);
lcd_puts(tbuff);
DelayMs(500);

In the PDF file dated 2013/08/30 02:44 the module pinouts are shown as two rows of 8 contacts this is wrong it should show a row of 8 and a row of 6 pins.

I was also led astray when i looked at one of the header files w5500.h that showed to read a a value from the module
uint8_t WIZCHIP_READ (uint32_t AddrSel); supply the address and get back the value, i hadent realised that there is also some extrra pre-amble in the address field.
I hope this info helps a few others.
I will post again when i have the rewst workingh.

#4

How did you get the schematic?
Regarding pins of wiz550io, Please refer to below link.
wizwiki.net/wiki/lib/exe/fetch.p … 140117.pdf

#5

Hi again,
Yes that circuit is correct shows an 8 pin and a 6 pin interface to the module.
I have now downloaded and poped the udp and tcp echo examples and they both worked 1st time.
And i was quite pleased to see them just work without any great struggle, next get it working under interupts so i can
have a main loop ‘do stuff’ and only call in/out to the network when needed.
in my app i will have veriable sized data blocks to return to the pc ranging from a few status bytes to 30mbytes depending on
what functions are called. Even the big data block will only be coming in chunks of 50k or so due to local ram on the pic
not being large enough.

#6

Would you please post a copy of your main.c. I am trying to use the ioLibrary with another PIC processor and it would be helpful if I could see the main.c code.
Thanks

#7

Here’s some test code i’ve used for the PIC16F876.
It works pretty well when it comes to SPI communication but I’m keep getting a SOCKERR_SOCKMODE when calling the listen function…(still fighting with that…) :confused:

#include <xc.h> 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ethernet\socket.h" 
#include "ethernet\wizchip_conf.h"


#define DATA_BUF_SIZE   64
uint8_t gDATABUF[DATA_BUF_SIZE];

#define WIZRESET RA0
#define WIZCS    RA1
#define WIZRDY   RA2

void hwinit()
{
   ADCON1 = 0x7;
   TRISB = 0;
   PORTB = 0;

   TRISC3 = 0;  // SPI SCK
   TRISC5 = 0;  // SPI SDO
   TRISA2 = 1;  // RDY input
   TRISA1 = 0;  // CS
   TRISA0 = 0;  // HE RESET  

   SSPEN = 0;					// disable SPI port for reconfiguration
   SSPSTAT = 0b01000000;  // SMP = 0, CKE = 1
   SSPCON = 0b00100010;  // WCOL = 0, SSPOV = 0, SSPEN = 1, CKP = 0 (idle low), SSPM = 0010 (SPI Master, FOSC/64)
   SSPEN = 1;					// re-enable SPI port
}

wiz_NetInfo gWIZNETINFO=
{
 {0x00, 0x08, 0xdc,0x1d, 0x2a, 0x91}, // mac
 {192, 168, 95, 199},                 // ip
 {255,255,255,0},                     // mask
 {192,168,95,1},                      // gateway
 {192,168,95,1},                      // dns
 NETINFO_STATIC};                     // DHCP type

void main(void)
{  

  uint8_t tmp = 0;
  uint8_t tmpstr[6] = {0};
  int32_t ret = 0;
  uint8_t memsize[2][8] = { {2,2,2,2,2,2,2,2},{2,2,2,2,2,2,2,2}};

  hwinit();

  /* reset W5500 */
  WIZRESET = 0;
  delay_ms(10);
  WIZRESET = 1;  
  
  delay_ms(10);

  while(WIZRDY!=1);
  WIZCS = 1;		 // SET CS High

  /* wizchip initialize*/
  if(ctlwizchip(CW_INIT_WIZCHIP,(void*)memsize) == -1) 
  {
        return; // restart
  }
 
   do
   {
       if(ctlwizchip(CW_GET_PHYLINK, (void*)&tmp) == -1)
      {
          RB4 = ~RB4;  // debug toggle
       }   
   }while(tmp == PHY_LINK_OFF);
   
    ctlnetwork(CN_SET_NETINFO, (void*)&gWIZNETINFO);
    ctlnetwork(CN_GET_NETINFO, (void*)&gWIZNETINFO);

    // Get network info
    ctlwizchip(CW_GET_ID,(void*)tmpstr); // tmpstr should contain "W5500" 

    while(1)
    {
     uint8_t p;
     uint8_t sn = 0;

      if((ret = socket(sn,Sn_MR_TCP,250,0)) != sn)
      {
          close(sn);   
          continue;
      }
     
      if((ret = listen(sn)) != SOCK_OK)
      {
         close(sn);      
         continue;
      }

      ..
	  ..
    }
}


void interrupt pic_isr(void)
{
  if (T0IF) // check if it's the timer interrupt
  { 
    T0IF = 0;       // clear interrupt flag
  }
  else if  (ADIF) // ADC interrupt
  {
    ADIF = 0; // clear flag
  }
  else if (INTF) // RA2/INT External Interrupt Flag
  {
    INTF = 0;
  }
  else if (SSPIF)
  {
    SSPIF = 0;
  }
}
#8

Hi,
Thank for your good port.

Note that
SOCKERR_SOCKMODE error returns when abnormal command is used in corresponding Sn_MODE as TCP and UDP.
For example, If Sn_MR was UDP and Sn_CR_CONNECT was commanded, SOCKET API returned SOCKERR_SOCKMODE.

Thank you.