I am at a loss as to how to communicate with the wiznet module. The documentation doesn’t really state any commands that need to be sent over SPI to read and write the registers. Let’s say I wanted to write the Source IP Address which has the following register addresses {0x000F, 0x0010, 0x0011, 0x0012}. What byte values would I need to send via SPI.Write(byte[]) to make that happen?
Wiznet already provide a complete driver in C. I would use that and change to C#.
There are a few bytes of bit-mapped prolog that have to be written to tell the wiznet where you want to write those bytes. The bits in that prolog indicate whether it is a read or write, fixed or variable length, and the memory block and offset. It takes a non-trivial excursion through the manuals and/or existing source to get it right (or at least it did for me).
@ Gus - Not a chance I’m porting from C again.
@ mcalsyn - I’m accustomed to non trivial extrusions through manuals; nothing new. I just wasn’t able to figure out how to start communicating with this device. So it’s like this for writing the first number in the source IP address.
What if I just keep sending bytes? Will the write the next address with the subsequent bytes?
```cs]SPI.WriteRead(new byte[] { 0xF0, 0x00, 0x0F, 0xC0, 0xA8, 0x02, 0x01});[/code
Yes, that exactly what you need to do - each byte sent will write to the next location in the memory block. As soon as your writeread completes, then CS is de-asserted and you have to start over with the prefix bytes. It works the same on read. However many bytes you read is how many sequential memory locations will be returned.
@ mcalsyn - So then technically I could setup the commands for an entire socket (e.g. socket 0) by setting the address to 0x04, 0x00 and writing 22 bytes to it (i.e. 0x0416 - 0x0400 = 22). Same thing for read?
Haven’t tried that personally, but I guess I would be surprised if it didn’t work.
it’s an interesting little chip I’ll say. Does the new 5500 work the same way? What’s the main difference that allows it to achieve it’s speed?
I’ve only really worked with the 5500, but I think the main api difference is the per-socket memory layout and management. I’m not sure what other changes or go-juice they applied to make it go faster.
public static void Test() {
reset.Write(false);
Thread.Sleep(10);
reset.Write(true);
byte[] _read = new byte[4];
while (true) {
port.WriteRead(new byte[] { 0x0F, 0x00, 0x17, 0x00 }, _read);
Debug.Print("0x0017 : " + _read[3].ToString());
port.WriteRead(new byte[] { 0x0F, 0x00, 0x18, 0x00 }, _read);
Debug.Print("0x0018 : " + _read[3].ToString());
}
}
So I’ve been running tests with this method because I notice something very strange. I’m constantly asking the device for the values from address 0x17 and 0x18. The default values for those register after reset are 7 and 208 respectively; however most times (about 60%) I get a zero (0) value. It almost as if the Wiznet hasn’t finished putting the register value to the SPI whatever so I get these incorrect values.
@ Gus - Do you have any clue as to what is going on?
why don’t you share more code and others can test (perhaps those who have more diagnostic tools available?) I have Wiz5100 module (Wiz812MJ) and an o’scope that I might be able to help with?
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using System.Threading;
public static class Wiznet5100 {
static OutputPort reset = new OutputPort((Cpu.Pin)FEZCerbuino.Pin.Digital.D9, true);
static InterruptPort interrupt = new InterruptPort((Cpu.Pin)FEZCerbuino.Pin.Digital.D8, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeLevelLow);
static SPI.Configuration config = new SPI.Configuration((Cpu.Pin)FEZCerbuino.Pin.Digital.D10,
false, // Chip Select, active-low
0, // 1 millisecond setup time
0, // 1 millisecond hold time
true, // Clock low on idle
false, // Data valid on falling edge
5000, // 5Mhz Clock Rate
SPI.SPI_module.SPI1);
static SPI port = new SPI(config);
public static void Test() {
reset.Write(false);
Thread.Sleep(10);
reset.Write(true);
byte[] _read = new byte[4];
while (true) {
port.WriteRead(new byte[] { 0x0F, 0x00, 0x17, 0x00 }, _read);
Debug.Print("0x0017 : " + _read[3].ToString());
port.WriteRead(new byte[] { 0x0F, 0x00, 0x18, 0x00 }, _read);
Debug.Print("0x0018 : " + _read[3].ToString());
}
}
}
This is the entire class. To run, I just call Wiznet5100.Test(); in the main program.cs
will test tonight (2h from now). Will use Cerberus as that’s the closest I have
Have a look at page 64 of the datasheet in regards to the reset timing. You need 10ms delay after bringing the reset line back to the HIGH state before the internal clock starts to run and in your code you are trying to communicate with the device as soon as you raise it.
Add a 20mS delay and see if it works better.
@ Dave McLaughlin - Nope, it gives the same problem; values that sould be 7 and 208 are coming back at zero almost half the time.
I’m flabbergasted at this problem and I can only think of one possible reason: That the register data isn’t being moved to the SPI output shift registers fast enough to make it within the next clock cycle. If so then my proposed solution is this:
Set /CS active (active is low)
Send the first 3 bytes
Pause for 1ms
Send the last byte
This of course means a measure of bit banging (sob) but if done in RLP it should be fine. Comments?
P.S. I don’t have test equipment to see whats happening at the logic level; If I had to do it all over again, I would have at minimum purchased a logic analyzer and 4 channel oscilloscope from day 1.
Have you tried this with TRUE?
The datasheet shows the data is valid on the rising edge of the clock in mode 0 (your clock starts low)
@ Dave McLaughlin - I have tried it with true. In that case it doesn’t work at all.
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using System;
using System.Threading;
public static class Wiznet5100 {
static OutputPort reset = new OutputPort((Cpu.Pin)FEZCerbuino.Pin.Digital.D9, true);
static OutputPort chipSelect = new OutputPort((Cpu.Pin)FEZCerbuino.Pin.Digital.D10, true);
static OutputPort clock = new OutputPort((Cpu.Pin)FEZCerbuino.Pin.Digital.D13, false);
static OutputPort mosi = new OutputPort((Cpu.Pin)FEZCerbuino.Pin.Digital.D11, false);
static InputPort miso = new InputPort((Cpu.Pin)FEZCerbuino.Pin.Digital.D12, false, Port.ResistorMode.Disabled);
static InterruptPort interrupt = new InterruptPort((Cpu.Pin)FEZCerbuino.Pin.Digital.D8, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeLevelLow);
//static SPI.Configuration config = new SPI.Configuration((Cpu.Pin)FEZCerbuino.Pin.Digital.D7,
// false, // Chip Select, active-low
// 0, // 1 millisecond setup time
// 0, // 1 millisecond hold time
// true, // Clock low on idle
// false, // Data valid on falling edge
// 5000, // 5Mhz Clock Rate
// SPI.SPI_module.SPI1);
//static SPI port = new SPI(config);
public static void Test() {
reset.Write(false);
Thread.Sleep(20);
reset.Write(true);
byte[] _read = new byte[1];
while (true) {
uint _address17 = 0x0F001700;
uint _address18 = 0x0F001800;
uint _value = 0;
chipSelect.Write(false);
for (int i = 0; i < 32; i++) {
mosi.Write(((_address17 << i) & 0x80000000) == 0x80000000);
clock.Write(true);
_value = _value << 1 | (uint)(miso.Read() ? 1 : 0);
clock.Write(false);
}
chipSelect.Write(true);
Debug.Print("0x0017 :" + (_value & 0xFF).ToString());
_value = 0;
chipSelect.Write(false);
for (int i = 0; i < 32; i++) {
mosi.Write(((_address18 << i) & 0x80000000) == 0x80000000);
clock.Write(true);
_value = _value << 1 | (uint)(miso.Read() ? 1 : 0);
clock.Write(false);
}
chipSelect.Write(true);
Debug.Print("0x0018 :" + (_value & 0xFF).ToString());
}
}
}
Sigh. So bit banging works; this returns the expected value every time. There is something about this chip that the manufacturer isn’t telling.
EDIT: The debug output is like this and repeats
0x0017 :7
0x0018 :208
0x0017 :7
0x0018 :208
0x0017 :7
0x0018 :208
Have you tried the original code but at a lower clock than 5Mhz, say 1Mhz?