SPI Sends Msb or Lsb
#1
Posted 09 October 2010 - 08:04 AM
I'm attempting to interface Microchip's MRF24J40MA 802.15.4 module (http://www.microchip...ocName=en535967) with the Netduino using SPI with not a lot of luck just yet. I'm curious as to how the SPI port sends data out. Is it sent in order of most significant bit or least significant bit? Thanks.
#2
Posted 09 October 2010 - 02:21 PM
#3
Posted 10 October 2010 - 08:43 AM
I believe that SPI sends bits in most significant bit order (2^7...2^0). Someone will correct me if I'm wrong
Are you using a shield or directly wiring the module up to your Netduino? Are you using a CS line? If you post a Fritzing diagram and a sources sample, someone might be able to spot what is going on...
Chris
Chris,
I'm not using a shield, just a breadboard. I know the modules work because they are part of a development kit from Microchip and I'm able to move them from the Netduino circuit to development boards from Microchip (with firmware in C) and they initialize and communicate just fine...
I'm using Pin 10 as the Chip Select line and I know from the MRF24J40 datasheet that CS needs to be driven low to active the transfer.
Here is a picture of my circuit (sorry the picture is little ugly, I'm new to Fritzing):
Here is the pinout diagram for the MRF24J40MA:
As far as code goes, here is the meat and potatoes snippet:
public static SPI.Configuration spi_config; public static SPI spi_port; spi_config = new SPI.Configuration( Pins.GPIO_PIN_D10, // Chip select port false, // IC is accessed when chip select is low 0, // Setup time 0 ms 0, // Hold chip select 0 ms after transfer false, // Clock line is low if device is not selected true, // Data is sampled at rising edge of clock 1000, // Clock rate SPI_Devices.SPI1 // Use first SPI port ); spi_port = new SPI(spi_config); // Using SPI, query the Transmit Status Bit (Low Val) byte tempTXSTBL = GetShortRAMAddr(0x2E); // TXSTBL = 0x2E // Function to send a short address byte read command to the MRF24J40MA module and return the value. // The packet format is as follows: // bit1 = 0 - Zero for a read // bit2 = A5 - Most Significant bit of the address to read // bit3 = A4 - Next address bit // bit4 = A3 - Next address bit // bit5 = A2 - Next address bit // bit6 = A1 - Next address bit // bit7 = A0 - Least Significan bit of the address to read // bit8 = 0 - Zero for read // Read the returned 8 bits as the data stored in the address location public static byte GetShortRAMAddr(byte address) { byte readAddress = 0; readAddress = (byte)((address << 1) & 0x7E); // Shift the address bits over one to the left to fit properly in the data packet byte[] writeBuff = new byte[] { readAddress }; byte[] readBuff = new byte[1]; spi_port.WriteRead(writeBuff, readBuff); return readBuff[0]; }
My problem is that the byte that returns from the GetShortRAMAddr function is always a zero. I don't have an oscilloscope to hook up to either the Netduino or the MRF24J40MA to see what the pins are doing on either end signal wise.
Any suggestions from anyone would be great. I'm a little worried that the Netduino might actually have too fast of an SPI clock for the module but without an oscilloscope I'm not sure how I'm going to verify that.
Of course I'll keep playing with it and if I'm able to get it working, I will share anything that I find with the community.
#4
Posted 10 October 2010 - 10:52 AM
#5
Posted 10 October 2010 - 01:01 PM
ajcg1973, that's a great first-time Fritzing diagram, actually
A few things:
1. Have you tied the RESET line on your module high? It appears to have a reset line that needs to be held high... You can probably use an OutputPort set to 'true' on the Netduino if you don't have a circuit for this...
2. Is your module 3.3V compatible? [I'm not sure what voltage you're running your Microchip module at.]
3. Have you tried slower SPI clock rates? Also, have you tried changing the sampling point (edge)?
A logic analyzer or oscilloscope will definitely help you see what is going on...
Chris
Chris, you must never sleep!
1. The RESET on the module is actually disabled by default on power on, you have to set the module up to listen for the reset (if that is what you want) in order to use the RESET line (seems a little unconventional I know).
2. The module is 3.3V compatible (I had to double check that as well).
3. The night before I played with the clock rates quite a bit going from a high of 15MHz down to 1KHz (although I read another post that the minimum clock time as read by an oscillator by another user was actually around 200KHz regardless of entered rate). The data sheet for the module was very specific about the reading data on the raising edge although I did try it to see if I could get a different result but I didn't. In fact the only time that I have seen data returned other than 0x00 was when I reversed the SDO/SDI lines to see what might happen and instead of reading 0x00, I read 0xFF.
As far as an oscilloscope, I'd rather save my pennies for what you have hinted on regarding future products from Secret Labs but if I'm unable to figure this out sooner than later I might have to take the plunge...
#6
Posted 10 October 2010 - 01:06 PM
As far as an oscilloscope, I'd rather save my pennies for what you have hinted on regarding future products from Secret Labs but if I'm unable to figure this out sooner than later I might have to take the plunge...
For figuring out what's going on with digital signals like SPI, let me give you my personal $150 recommendation. This is what I use at home, and it's a pretty fantastic yet inexpensive piece of hardware.
http://www.saleae.com/logic/
It won't give you as full of a range of details as a really nice oscilloscope+logic analyzer unit, but it's amazing what $150 will do. If you're going to play a lot with electronics, a logic analyzer is a great investment.
Chris
- Gutworks likes this
#7
Posted 10 October 2010 - 01:44 PM
I found the issue (or trick depending on how you look at it). The data was coming in on the second byte!
Here is an excerpt from the MRF24J40 datasheet on what should be coming back for the register that I'm going after:
Here are the results:
It looks like (and I'm not sure why yet) the value that I was looking for is in the second returned byte instead of in the expected first returned byte. After putting on my Edison hat and trying 1,000 different ways to fail, I decided to expand the read buffer and sure enough the value that I was looking for (b0001 1100 = 0x1C) was there, probably all along but I couldn't ever see it.
Thanks again for your assistance on this. I now need to figure out why I'm getting an extra zero byte so I don't have a negative impact on the rest of my coding.
#8
Posted 10 October 2010 - 01:50 PM
I had the exact same issue when I first started using SPI in .NET MF.
Here's what is happening...The WriteRead(...) function writes data from the provided write array while reading in data to populate the provided read array. While WriteRead(...) is sending the byte in the write array (readAddress), it reads a byte into the read array. Then it's reading the second byte into the read array (your data byte).
In essence, SPI conducts write and read transactions _at the same time_. So if you need to write a byte before reading a byte, you'll want to: [a] write the byte; [b] write dummy byte(s) while reading your data.
Does that make sense? So something along the lines of...
byte[] addressData = new byte[] { readAddress }; spi_port.Write(addressData); byte[] readBuff = new byte[1]; spi_port.WriteRead(new byte[] { 0 }, readBuff);To cut down on garbage collection and increase performance, you may want to create the write/read buffers as class-level variables--and then reuse the same pre-allocated buffers each time.
Chris
#9
Posted 12 October 2010 - 07:05 AM
#10
Posted 15 January 2011 - 08:40 AM
#11
Posted 15 January 2011 - 08:58 AM
#12
Posted 15 January 2011 - 08:53 PM
I was able to read a short address register but I was never able to write any information to the MFR24J40 chip using SPI.
Here is the code for the main function:
public class Program { static AjbMrf24J40 mrf; public static void Main() { mrf = new AjbMrf24J40((Cpu.Pin)FEZ_Pin.Digital.Di10); // Set the PANID Low and High bytes to zero... mrf.SetShortRAMAddr(AjbMrf24J40.PANIDL, 0x00); mrf.SetShortRAMAddr(AjbMrf24J40.PANIDH, 0x00); // Read the PANID Low and High bytes to see if they return zero... byte tempBefore = mrf.GetShortRAMAddr(AjbMrf24J40.PANIDL); byte tempBefore2 = mrf.GetShortRAMAddr(AjbMrf24J40.PANIDH); // Ok set the PANID Low and High bytes to the real value... mrf.SetShortRAMAddr(AjbMrf24J40.PANIDL, AjbMrf24J40.PANID_LSB); mrf.SetShortRAMAddr(AjbMrf24J40.PANIDH, AjbMrf24J40.PANID_MSB); // Read the PANID Low and High bytes to see if they return the real values... byte tempAfter = mrf.GetShortRAMAddr(AjbMrf24J40.PANIDL); byte tempAfter2 = mrf.GetShortRAMAddr(AjbMrf24J40.PANIDH); // Blink a LED or something... OutputPort led = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.LED, false); while (true) { // Sleep for 500 milliseconds Thread.Sleep(500); // toggle LED state led.Write(!led.Read()); } }
And Here is the code for the MRF24J40MA module:
using System; using System.Threading; using Microsoft.SPOT; using Microsoft.SPOT.Hardware; namespace AJB_NetMF_Classes { public class AjbMrf24J40 { #region Constants //MRF24J40_DEFS public const byte PANID_LSB = 0xFE; public const byte PANID_MSB = 0xCA; public const byte PANIDL = 0x01; public const byte PANIDH = 0x02; // Code shortened for easier posting...the rest of the CONSTs aren't needed for demonstration #endregion private SPI spi_port; private SPI.Configuration spi_config; public AjbMrf24J40(Cpu.Pin CS) { spi_config = new SPI.Configuration( CS, // The chip select port. false, // The active state for the chip select port. If true, the chip select port will be set to // high when accessing the chip; if false, the chip select port will be set to // low when accessing the chip. 0, // The setup time for the chip select port. In other words, this parameter specifies the amount // of time that will elapse between the time at which the device is // selected and the time at which the clock and the clock data transmission will start. 0, // The hold time for the chip select port. In other words, this parameter specifies the amount of // time that the chip select port must remain in the active state before // the device is unselected, or the amount of time that the chip select will remain in the active // state after the data read/write transaction has been completed. false, // The idle state of the clock. If true, the SPI clock signal will be set to high while the device is idle; // if false, the SPI clock signal will be set to low while the // device is idle. The idle state occurs whenever the chip is not selected. true, // The sampling clock edge. If true, data is sampled on the SPI clock rising edge; if false, the data is // sampled on the SPI clock falling edge. 500, // The SPI clock rate in KHz. SPI.SPI_module.SPI1 // The SPI bus used for the transaction. ); spi_port = new SPI(spi_config); } public byte GetShortRAMAddr(byte address) { byte readAddress = (byte)((address << 1) & 0x7E); byte[] writeBuff = new byte[] { readAddress }; byte[] readBuff = new byte[2]; spi_port.WriteRead(writeBuff, readBuff); return readBuff[1]; } public void SetShortRAMAddr(byte address, byte data) { byte writeAddress = (byte)(((address << 1) & 0x7F) | 0x01); byte[] writeBuff = new byte[] { writeAddress, data }; spi_port.Write(writeBuff); } } }
To recap, I was getting data back but not all 8 bits of the data. So if the data returned back only used the 6 Least Significant bits I would have not known that the data was incorrect (as we saw in a previous post with my success message). I have also been able to change the clock rate on the Panda and it is still works.
If you would like me to try anything (including different firmware) let me know and I'll give it a shot. As I said before, I haven't tried to use the MRF24J40 module with the Netduino Mini because it is a little harder to wire up and I'm thinking I will get the same results but if you think I should let me know and I'll give it a shot. Thanks.
#13
Posted 01 February 2011 - 05:20 PM
Hi ajcg1973,
Could you please post the code to a small program which is working on other .NET MF boards but not on the Netduino?
Also, weren't you getting data back properly previously? Sorry, I didn't realize there was something still amiss.
Chris
I was actually able to get it working by accident. I updated my Netduino with v4.1.0.6 RC1 and the SPI still didn't work but I was getting different results (the WriteRead returned different bits) when I kept the code the same and just changed the Chip Select Pin. At one time, out of frustration, I unplugged the CS pin with the Netduino powered on and it magically started to work just fine?!?! I plugged the CS pin back into the board and tried it again it stopped working. I had to have the pin touching my finger at a special point in time during the configuration in order for the code to work. This got me thinking, I must need a resistor on the CS pin. After putting in resistor between the CS pin and the Netduino, everything works just great now! The code is working exactly the same as it did on the FEZ Panda!
I'm not sure why the Netduino needs a resistor while the Panda doesn't? Any thoughts? I might go back to v4.1.0.5 firmware just to see if it was the resistor all along...
#14
Posted 01 February 2011 - 06:46 PM
After putting in resistor between the CS pin and the Netduino, everything works just great now!
Hi ajcg1973,
If you change the CS pin to another digital pin, does it work without a resistor? What if you change the CS pin to digital pin 4?
Chris
#15
Posted 01 February 2011 - 09:00 PM
Hi ajcg1973,
If you change the CS pin to another digital pin, does it work without a resistor? What if you change the CS pin to digital pin 4?
Chris
No still need the resistor, I have tried just about every pin that was available without success (including the Analog Pins). I did back it down to v4.1.0.5 firmware (not that I needed to but I wanted to test it to see if there was a difference) and it still is working fine (as long as I use a resistor). I also switched the CS pin to D9 and it works just fine with the resistor. So it still is looking like the resistor is key. I honestly don't understand why. Without the resistor I don't get all of the bits in the byte (I do get data back on the read - just not the correct data).
That brings up another interesting point, I always get the same incorrect data back. For instance sending 0xCA always returns 0xC0. If I send 0xFE I always get 0xFE back. Why one byte works and another one doesn't I don't know. These are without the resistor on the CS pin. So this tells me that it isn't random noise, there just seems to be a disconnect in the timings between the two chips. I have also tried to lower and raise the SPI speed and that hasn't had any impact on the results.
#16
Posted 01 February 2011 - 09:39 PM
#17
Posted 01 February 2011 - 10:24 PM
Hi
Just to make sure, is the resistor in series with the chipselect signal?
Also what value is it ?
/Jan Olof
Yes, it is in series and it is a 220Ω resistor. Have you had issues with SPI as well?
#18
Posted 01 February 2011 - 11:10 PM
#19
Posted 01 February 2011 - 11:38 PM
No I have not tried out SPI yet, but I have an BMA180 that I want to use so I am following SPI discussions on the forum.
I am trying to understand what your resistor will do. The only thing that come to mind is that it will delay the
rising edge of the CS signal as the pullup is a rather high value resistor.
You could test with an small capacitor to gnd instead of the resistor perhaps 1 or 4.7 nF.
You could perhaps use an other pin and manipulate the CS signal yourself, all this just to verify it is an timing issue
as I think.
/Jan Olof
I do need to figure out what the resistor is doing to make it work, my guess also is that any value of the resistor will work although I haven't tried it. I've seen resistors added before with some microcontroller circuits but I don't have any examples handy. The reason that I'm not too concerned with the resistor is because the same code and the same circuit works just fine on the FEZ Panda without the resistor.
I have tried all of the pins at one time including driving my own CS pin and hardwiring the CS pin to ground to always select to no avail. Like I said the same circuit works on the FEZ Panda without doing anything different.
That is why I was asking you about SPI. I was curious if anyone else was having an issue with SPI.
I will find some time to do a little more research and I will post any findings to this thread.
#20
Posted 26 July 2011 - 09:01 PM
0 user(s) are reading this topic
0 members, 0 guests, 0 anonymous users