CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

SPI Wiznet garbage
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
learner



Joined: 17 Mar 2010
Posts: 10

View user's profile Send private message

SPI Wiznet garbage
PostPosted: Wed Mar 17, 2010 6:21 pm     Reply with quote

My project is very similar to:
http://www.ccsinfo.com/forum/viewtopic.php?t=40693&start=15&postdays=0&postorder=asc&highlight=wiznet

I have the same wiznet812 module and PIC18F4455 connected using SPI. I am having a problem that my wiznet writes and reads are not consistent. When I write data to 4 registers in Wiznet and read them back, I dont always read the same values, it's right some times and garbage at other times.

I am using PCH v4.066, 37489 as its in a school computer and I did notice people saying that anything below 4.070 is highly unstable, I dont know if that is causing the problem.

I have tried using spi_read() instead of spi_write(), resetting Wiznet before every write, used different spi clocks, changed delays, etc but the results have been the same.

I have pasted the code below and my result as seen on Serial I/O window.

Code:

#include <18F4455.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN                //needed for USB functionality
#use delay(clock=48000000)    //needed for USB functionality

#include <usb_cdc.h>         //needed to perform USB to SERIAL functionality
#rom int 0xf00000={1,2,3,4}  //needed for USB functionality

#include <usb_bootloader.h>

#define SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1  (SPI_L_TO_H)
#define SPI_MODE_2  (SPI_H_TO_L)
#define SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)
 
// PIC pins assigned to W5100 signals.
#define W5100_CS     PIN_B2
#define W5100_RESET  PIN_B3
     
// W5100 Commands (from W5100 data sheet).
#define W5100_WRITE_CMD  0xF0
#define W5100_READ_CMD   0x0F
 
// W5100 Register addresses (from W5100 data sheet).
#define W5100_MR_REG   0x0000
#define W5100_GAR0_REG 0x0001
#define W5100_GAR1_REG 0x0002
#define W5100_GAR2_REG 0x0003
#define W5100_GAR3_REG 0x0004
// etc.
 
// This routine writes 1 byte of data to a W5100 register
//!// at the specified register address.
void w5100_write_reg(int16 addr, int8 data)
{
   output_low(W5100_CS);   delay_us(30);
   spi_write(W5100_WRITE_CMD);
   spi_write((addr&0xFF00)>> 8);  // Send address msb
   spi_write((addr&0x00FF));       // Send address lsb
   spi_write((data&0x00FF));       // Write data to W5100
   output_high(W5100_CS);delay_us(30);
}

int8 w5100_read_reg(int16 addr)
{
   int8 retval;   
   output_low(W5100_CS);delay_us(30);
   spi_write(W5100_READ_CMD);
   spi_write((addr&0xFF00) >> 8);  // Send address msb
   spi_write((addr&0x00FF));       // Send address lsb
   retval = spi_read(0);  // Read data from W5100
   output_high(W5100_CS);delay_us(30);
 
   return(retval);
}

int8 gar0, gar1, gar2, gar3;
unsigned int8 status;

void main()
{
   usb_cdc_init();  //configure the CDC driver
   usb_init();      //start up the USB driver
     
      // Initialize the W5100 chip select signal to the deselected state.
      output_high(W5100_CS); delay_us(20);
     
      // Reset the W5100 chip and then wait for the time
      // specified in the W5100 data sheet.   
      output_low(W5100_RESET);
      delay_us(10);  // Minimum reset pulse width is 2 us
      output_high(W5100_RESET);
      delay_ms(25);   // Maximum Plock delay time is 10 ms
     
      // Setup the PIC's SPI module to work with the W5100 chip.
      setup_spi(SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_64);
     
      // Display the results. Look on the terminal window
      // to see if it's correct.  Should be: 12 34 56 78
   while(TRUE)
   {
      while(usb_cdc_connected())
      {
         usb_task();

         // See if we can write to the Gateway Address Registers   
         // (GAR0-GAR3). Just fill them with some test data.
         w5100_write_reg(W5100_GAR0_REG, 0x12);delay_us(15);
         w5100_write_reg(W5100_GAR1_REG, 0x34);delay_us(15);
         w5100_write_reg(W5100_GAR2_REG, 0x56);delay_us(15);
         w5100_write_reg(W5100_GAR3_REG, 0x78);delay_us(15);
     
         // Now read back the GAR registers.   
         gar0 = w5100_read_reg(W5100_GAR0_REG);delay_us(15);
         gar1 = w5100_read_reg(W5100_GAR1_REG);delay_us(15);
         gar2 = w5100_read_reg(W5100_GAR2_REG);delay_us(15);
         gar3 = w5100_read_reg(W5100_GAR3_REG);delay_us(15);
         
         // Send to Serial port monitor
         printf(usb_cdc_putc,"Result: %X %X %X %X \n\r", gar0, gar1, gar2, gar3);
         delay_ms(2000);
      }
   }
}



Result:
Code:

Result: F0 34 56 78   
Result: 02 00 00 78   
Result: 12 04 00 08   
Result: 00 04 00 78   
Result: 12 34 56 78     
Result: 12 34 56 78     
Result: FF 34 56 78     
Result: FF 34 56 78   
Result: 12 34 56 78   
Result: 12 34 56 78   
Result: F0 04 00 78   
Result: F0 04 00 08   
Result: F0 34 56 78   
Result: F0 04 00 78     
Result: 12 34 56 78     
Result: 02 00 02 00   
Result: 12 04 00 78   
Result: FF 34 56 78     
Result: F0 04 00 08     
Result: F0 34 56 78     
Result: F0 04 00 08     
Result: FF 34 56 78     
Result: F0 34 56 78     
Result: F0 04 00 78     
Result: F0 34 56 78     
Result: FF 34 56 78     
Result: 12 34 56 78     
Result: 12 34 56 78     
Result: FF 34 56 78     
Result: FF 34 56 78     
Result: 12 04 00 08     
Result: 12 34 56 78     
Result: 12 34 56 78     
Result: 12 04 00 78     
Result: 12 04 00 08     
Result: 12 F0 56 78     
Result: 12 F0 56 78     
Result: 02 00 00 08     
Result: F0 34 56 78     
Result: 02 00 02 00     
Result: 12 34 56 78   
Result: 12 34 56 78     
Result: 12 34 02 00     
Result: 12 34 56 78     
Result: FF 34 56 78     
Result: 12 34 56 78     
Result: FF 34 56 78     
Result: 12 04 00 78     
Result: FF 34 F0 78     
Result: 02 00 00 08     
Result: 02 00 02 00     
Result: 12 34 56 78     
Result: 12 34 56 02     
Result: 12 34 56 78     
Result: F0 04 00 08     
Result: 00 34 00 78     
Result: F0 04 00 78
learner



Joined: 17 Mar 2010
Posts: 10

View user's profile Send private message

PostPosted: Thu Mar 18, 2010 10:59 am     Reply with quote

any suggestions anyone? plz do let me know if you need more information.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Mar 18, 2010 12:01 pm     Reply with quote

Test the CDC interface. See if it's working. Put in some faked up data
in the "gar" variables and see if it gets back to the PC OK.

For testing, add the lines shown in bold below:
Quote:

// Now read back the GAR registers.
gar0 = w5100_read_reg(W5100_GAR0_REG);delay_us(15);
gar1 = w5100_read_reg(W5100_GAR1_REG);delay_us(15);
gar2 = w5100_read_reg(W5100_GAR2_REG);delay_us(15);
gar3 = w5100_read_reg(W5100_GAR3_REG);delay_us(15);

// *** TESTING ***
gar0 = 0x89;
gar1 = 0xAB;
gar2 = 0xCD;
gar3 = 0xEF;

// Send to Serial port monitor
printf(usb_cdc_putc,"Result: %X %X %X %X \n\r", gar0, gar1, gar2, gar3);
delay_ms(2000);
learner



Joined: 17 Mar 2010
Posts: 10

View user's profile Send private message

PostPosted: Thu Mar 18, 2010 12:48 pm     Reply with quote

Yes, cdc is working. 'Read' means the data I'm reading from Wiznet, 'Test' means the values assigned directly to the variables:

Read: 12 04 00 08
Test: 89 AB CD EF
Read: F0 34 56 78
Test: 89 AB CD EF
Read: 02 00 02 00
Test: 89 AB CD EF
Read: 12 34 56 78
Test: 89 AB CD EF
Read: FF 34 56 78
Test: 89 AB CD EF
Read: 12 34 56 78
Test: 89 AB CD EF
Read: 12 04 00 78
Test: 89 AB CD EF
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Mar 18, 2010 2:14 pm     Reply with quote

Do a further test. See if it's a problem with reading.
Write to the "gar" registers once, above the loop.
Then repeatedly read the registers. See if they always
return the same data, or if it's garbled occasionally.
Here is the modified code for this test:
Code:

// See if we can write to the Gateway Address Registers   
// (GAR0-GAR3). Just fill them with some test data.
w5100_write_reg(W5100_GAR0_REG, 0x12);delay_us(15);
w5100_write_reg(W5100_GAR1_REG, 0x34);delay_us(15);
w5100_write_reg(W5100_GAR2_REG, 0x56);delay_us(15);
w5100_write_reg(W5100_GAR3_REG, 0x78);delay_us(15);


while(TRUE)
   {
      while(usb_cdc_connected())
      {
         usb_task();
     
         // Now read back the GAR registers.   
         gar0 = w5100_read_reg(W5100_GAR0_REG);delay_us(15);
         gar1 = w5100_read_reg(W5100_GAR1_REG);delay_us(15);
         gar2 = w5100_read_reg(W5100_GAR2_REG);delay_us(15);
         gar3 = w5100_read_reg(W5100_GAR3_REG);delay_us(15);
         
         // Send to Serial port monitor
         printf(usb_cdc_putc,"Result: %X %X %X %X \n\r", gar0, gar1, gar2, gar3);
         delay_ms(2000);
      }
   }
learner



Joined: 17 Mar 2010
Posts: 10

View user's profile Send private message

PostPosted: Thu Mar 18, 2010 2:40 pm     Reply with quote

Hmm, looks like my reads are garbled. At one point in my test I did get 12 34 56 78, but I reset and ran again and here's what I got.
Quote:

Read: 12 34 F0 08
Read: 00 34 F0 02
Read: 00 34 F0 00
Read: 12 04 00 08
Read: 00 04 00 00
Read: 12 04 00 08
Read: 00 34 F0 00

But how do I know whether my writes are working 100% as well?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Mar 18, 2010 3:14 pm     Reply with quote

Try writing all zeros and see what you read back.
See the modifications in bold below:
Quote:

// See if we can write to the Gateway Address Registers
// (GAR0-GAR3). Just fill them with some test data.
w5100_write_reg(W5100_GAR0_REG, 0x00);delay_us(15);
w5100_write_reg(W5100_GAR1_REG, 0x00);delay_us(15);
w5100_write_reg(W5100_GAR2_REG, 0x00);delay_us(15);
w5100_write_reg(W5100_GAR3_REG, 0x00);delay_us(15);


while(TRUE)
{
while(usb_cdc_connected())
{
usb_task();

// Now read back the GAR registers.
gar0 = w5100_read_reg(W5100_GAR0_REG);delay_us(15);
gar1 = w5100_read_reg(W5100_GAR1_REG);delay_us(15);
gar2 = w5100_read_reg(W5100_GAR2_REG);delay_us(15);
gar3 = w5100_read_reg(W5100_GAR3_REG);delay_us(15);

// Send to Serial port monitor
printf(usb_cdc_putc,"Result: %X %X %X %X \n\r", gar0, gar1, gar2, gar3);
delay_ms(2000);
}
}
learner



Joined: 17 Mar 2010
Posts: 10

View user's profile Send private message

PostPosted: Thu Mar 18, 2010 3:28 pm     Reply with quote

Strangely enough, this is what I get:
Quote:

Read: 02 00 02 00
Read: 01 00 01 00
Read: 02 00 02 00
Read: 02 00 02 00
learner



Joined: 17 Mar 2010
Posts: 10

View user's profile Send private message

PostPosted: Mon Mar 29, 2010 9:56 pm     Reply with quote

I tried putting 10kohm pullup resistors to SDO and SDI pin to see if it would make any difference but it did not. Then I did spi_write(0x55) and checked the SDO and clock on a scope and they looked perfect. I also tried switching out to a different prototype board but with same results. I still cant figure out what's causing the garbage values.

I'm writing out values 0x12, 0x34, 0x56, 0x78 to the 4 registers before while loop and reading them continuously inside the while loop and this is what I'm getting. My project's going nowhere because this is the most basic step to start with.
Quote:

Read: 12 04 00 78
Read: 12 34 56 02
Read: 00 02 00 78
Read: 12 02 00 78
Read: 12 34 56 78
Read: 12 04 00 78
Read: 12 34 56 78
Read: 02 00 00 78
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Mar 30, 2010 1:29 pm     Reply with quote

Wiznet has a tech forum.

Here is one thread, where he is getting some weird data, similar to you,
and the problem is apparently an incorrect SPI mode:
http://www.wiznet.co.kr/Sub_Modules/en/technical/Q_A_View.asp?boardcd=101&PK_NUM=14652&page=22

I wonder if there is a problem with the hardware SPI module on the
18F4455. You could try using software SPI. I'll test if #use spi()
works OK on vs. 4.066 and post the results. If it does, then you
could use it for software SPI. If not, you could still use bit-bang
routines.

I noticed one other thing. On page 60 of the W5100 data sheet,
it shows a pull-up resistor on the SPI_EN pin. Do you have that
installed ?
http://www.sparkfun.com/datasheets/DevTools/WIZnet/W5100_Datasheet_v1_1_8.pdf

I have another question. I was just re-reading that old thread you linked
to in your first post. Do you have the PIC running at +5v and the
Wiznet running at +3.3v ? Do you have a level converter on the SDO
signal coming from the Wiznet module, which goes to the PIC's SDI pin ?
learner



Joined: 17 Mar 2010
Posts: 10

View user's profile Send private message

PostPosted: Wed Mar 31, 2010 12:22 pm     Reply with quote

Spi modes 1 & 3 give no results at all, whereas mode 2 gives me all 00's in result.
The pull up resistor on SPI_EN is already done within the module itself and cant be changed because the board doesnt have an SPI_EN pin.
I do have the PIC running at 5V and Wiznet at 3.3 and yes I am using 74HCT125 between SDO from Wiznet and SDI of PIC.

With regards to #use spi, i tried this simple code. I also used a different compiler version PCH v4.084, 57706.
Code:

#include <18F4455.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN                //needed for USB functionality
#use delay(clock=48000000)    //needed for USB functionality

//#use spi (MASTER, MODE=0, DI=PIN_B4, DO=PIN_C6, CLK=PIN_B5, BITS=8, BAUD=100000)

#use spi (MASTER, MODE=0, SPI1, BITS=8, BAUD=100000)

void main()
{
   while(TRUE)
   {
      spi_xfer(0x55);
      delay_us(50);
   }
}

On the oscilloscope, I can successfully see 8 clocks and 01010101. I can see the same thing if I use the 'commented' #use spi as well, it's just a bit slower than using the uncommented one.

The other thing is, I can see the same thing on oscope if I use setup_spi() instead of #use spi. So I dont know if this test is so reliable.

Now for the functions that do the actual read and write to Wiznet registers, here's what I have so far but they're not working. I suspect I dont have the reads implemented correctly:
Code:

void w5100_write_reg(int16 addr, int8 data)
{
   output_low(W5100_CS);   delay_us(50);
   spi_xfer(W5100_WRITE_CMD); delay_us(150);
   spi_xfer((addr&0xFF00)>> 8); delay_us(150); // Send address msb
   spi_xfer((addr&0x00FF));delay_us(150);       // Send address lsb
   spi_xfer(data);delay_us(150);       // Write data to W5100
   output_high(W5100_CS);delay_us(50);
}

int8 w5100_read_reg(int16 addr)
{
   int8 retval;   
   output_low(W5100_CS);delay_us(50);
   spi_xfer(W5100_READ_CMD);delay_us(150);
   spi_xfer((addr&0xFF00) >> 8); delay_us(150); // Send address msb
   spi_xfer((addr&0x00FF));delay_us(150);       // Send address lsb
   retval = spi_xfer(0);delay_us(150);  // Read data from W5100
   output_high(W5100_CS);delay_us(50);
 
   return(retval);
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Mar 31, 2010 12:41 pm     Reply with quote

To solve your problem, I would have to buy a Wiznet module from
Sparkfun for $24.95 plus tax and shipping. That's too much for me
to spend to solve your problem.
learner



Joined: 17 Mar 2010
Posts: 10

View user's profile Send private message

PostPosted: Wed Mar 31, 2010 12:56 pm     Reply with quote

Confused
it's ok. thanks for all your help. but can u tell me if i am doing the read correctly? is spi_xfer(0) the right way to do it?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Mar 31, 2010 1:37 pm     Reply with quote

I'll show you how to study the problem.

First you make a test program. This is a little program that concentrates
only on the issue that you want to study. In this case, you want to
study the behavior of spi_xfer(), compared to spi_write() and spi_read().
Here is the program:
Code:

#include <18F4455.h>
#fuses XT,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

#use spi (MASTER, MODE=0, SPI1, BITS=8, BAUD=100000)

//======================================
void main(void)
{
int8 result;

spi_write(0x55);

result = spi_read(0x55);

result = spi_xfer(0x55);

while(1);
}


Here's part of the .LST file.
Code:
.................... spi_write(0x55);
003A:  MOVF   FC9,W
003C:  MOVLW  55
003E:  MOVWF  FC9
0040:  RRCF   FC7,W
0042:  BNC   0040
.................... 
.................... result = spi_read(0x55);
0044:  MOVF   FC9,W  // Read SSPBUF
0046:  MOVLW  55
0048:  MOVWF  FC9    // Put 0x55 in SSPBUF
004A:  RRCF   FC7,W  // Test BF bit of SSPSTAT
004C:  BNC   004A    // Wait in loop until BF = 1
004E:  MOVFF  FC9,06 // Read SSPBUF. Put it in 'result' variable
.................... 
.................... result = spi_xfer(0x55);
0052:  MOVLW  55    // Put 0x55 in 07 loc.
0054:  MOVWF  07
0056:  MOVLW  08    // Put 0x08 in 08 loc. (not needed)
0058:  MOVWF  08
005A:  BRA    0004  // Jump to spi_xfer() routine

0004:  MOVF   FC9,W   // Read SSPBUF
0006:  MOVFF  07,FC9  // Put 0x55 in SSPBUF
000A:  BTFSS  FC7.0   // Test BF bit of SSPSTAT
000C:  BRA    000A    // Wait in loop until BF = 1
000E:  MOVFF  FC9,01  // Read SSPBUF. Put it in 01 loc.
0012:  GOTO   005C (RETURN)

005C:  MOVF   01,W    // Put 01 loc. in W. (not needed).
005E:  MOVFF  01,06   // Put 01 loc. in 'result' variable.
.................... 

This shows that spi_xfer() does basically the same thing as spi_read().
However, it also shows that spi_xfer() has a bug. Here is the Errata
sheet for Rev. A3 silicon for the 18F4455:
http://ww1.microchip.com/downloads/en/DeviceDoc/80220j.pdf
On page 8, it says:
Quote:

18. Module: MSSP

When the MSSP is configured for SPI mode, the
Buffer Full bit, BF (SSPSTAT<0>), should not be
polled in software to determine when the transfer
is complete.


But that's exactly what CCS is doing, as shown in bold below.
That's a bug. This is with vs. 4.084. But I installed vs. 4.106
and they're still doing it. I'll email CCS about this.
Quote:

0004: MOVF FC9,W // Read SSPBUF
0006: MOVFF 07,FC9 // Put 0x55 in SSPBUF
000A: BTFSS FC7.0 // Test BF bit of SSPSTAT
000C: BRA 000A // Wait in loop until BF = 1
000E: MOVFF FC9,01 // Read SSPBUF. Put it in 01 loc.
0012: GOTO 005C (RETURN)

In the spi_write() code, CCS rotates the BF bit into the Carry flag
before testing it. So presumably that's OK and satisfies the errata's
suggestion for a work-around.
learner



Joined: 17 Mar 2010
Posts: 10

View user's profile Send private message

PostPosted: Wed Mar 31, 2010 4:47 pm     Reply with quote

wow, quite an observation PCM. so does this mean that setup_spi() would work better than #use spi, since spi_xfer has a bug?

I also have an 18F4553 with me but I've never worked with it before. I tried going over the errata sheets before hooking it up but I was pretty overwhelmed with all the MSSP errors it has reported.

So I tried to hook it up anyway but there are couple of problems. I cant use USB with this chip because the compiler says:
Quote:
#error Unknown PIC device, USB not supported in this library.

Then I wanted to use RS232 instead but noticed that RX and SDO use the same pin on the 18f4553. So I guess I cant use this chip at all, because I want to be able to see the results on the hyperterminal and I cant use RS2323 or USB.
Any suggestions?

EDIT: I also have an 18F4550 but it uses the same datasheet and errata as 18F4455 so cant use it either.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group