Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

SPI Sends Msb or Lsb


  • Please log in to reply
20 replies to this topic

#1 ajcg1973

ajcg1973

    Advanced Member

  • Members
  • PipPipPip
  • 71 posts

Posted 09 October 2010 - 08:04 AM

I haven't been able to figure this out with my own research...

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 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 09 October 2010 - 02:21 PM

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

#3 ajcg1973

ajcg1973

    Advanced Member

  • Members
  • PipPipPip
  • 71 posts

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):
Posted Image

Here is the pinout diagram for the MRF24J40MA:
Posted Image


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 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 10 October 2010 - 10:52 AM

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

#5 ajcg1973

ajcg1973

    Advanced Member

  • Members
  • PipPipPip
  • 71 posts

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 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

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

#7 ajcg1973

ajcg1973

    Advanced Member

  • Members
  • PipPipPip
  • 71 posts

Posted 10 October 2010 - 01:44 PM

Oh, you are not going to believe this...

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:

Posted Image


Here are the results:

Posted Image


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 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 10 October 2010 - 01:50 PM

ajcg1973,

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 ajcg1973

ajcg1973

    Advanced Member

  • Members
  • PipPipPip
  • 71 posts

Posted 12 October 2010 - 07:05 AM

Chris, Thanks so much for your assistance with this issue, unfortunately I'll have to shelve the development for the MRF24J40MA and SPI on the Netduino for a while. I'm just not getting any kind of predictable result on the reads (and probably the writes) that I can use to build up the interface to send and receive data. I have temporarily moved back to the PIC (at least for the Send/Receive stack). I spent close to 40 hours trying every different variable (hardware and software) that I could think of. The only successful result that I was able to obtain was to do a SPI short address (8bit) read but even then it was only when I had a two byte read buffer and read the second byte. That seemed to work but when I received bytes that had a lot of zero bits in the returned data, it seemed to drop off some of the least significant bits on the data that was being read. After only 6 hours of coding on the PIC, I was able to send an 802.15.4 packet (I don't have the receive working just yet) without issue on the PIC using SPI in the format that we had discussed in previous posts. Not all was lost, the Netduino was able to teach me quite a bit when it came to interfacing with the modules registers. Who knows, I might just create an 8bit brain between the MRF module and the Netduino as a work around. Once again, thanks for all of your responses. I almost thought that I had it there for a while! I'm sure I'll have more questions on something else Netduino related in the future and if this thread still exists and I have a solution, I'll definitely post it! P.S. I'm not giving up on the Netduino. I'm just temporarily giving up on the SPI interfacing with the MRF24J40MA module. I'm still eagerly awaiting the USB HID code! (hehe, I just had to get that in there somewhere)

#10 ajcg1973

ajcg1973

    Advanced Member

  • Members
  • PipPipPip
  • 71 posts

Posted 15 January 2011 - 08:40 AM

Chris, I have bad news... I tested the code on a FEZ Panda and the same code (minus the FEZ pin names) worked just fine. I think there might be an issue with SPI on the Netduino. With all of my research on the forums, I haven't been able to find anyone else reporting problems with SPI. As I said, with the same wiring as above and the same code I was able to talk to the MRF24J40 just fine. I even tried the latest version of the beta firmware 4.1.1.0 a5 with no difference in the results. I haven't tried the code on my Netduino Mini yet but I'm guessing I'll have the same results as my Netdiuno. Any feedback would be appreciated...

#11 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 15 January 2011 - 08:58 AM

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

#12 ajcg1973

ajcg1973

    Advanced Member

  • Members
  • PipPipPip
  • 71 posts

Posted 15 January 2011 - 08:53 PM

Chris,

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 ajcg1973

ajcg1973

    Advanced Member

  • Members
  • PipPipPip
  • 71 posts

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 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

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 ajcg1973

ajcg1973

    Advanced Member

  • Members
  • PipPipPip
  • 71 posts

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 Jan Olof

Jan Olof

    Advanced Member

  • Members
  • PipPipPip
  • 41 posts
  • LocationSweden

Posted 01 February 2011 - 09:39 PM

Hi Just to make sure, is the resistor in series with the chipselect signal? Also what value is it ? /Jan Olof

#17 ajcg1973

ajcg1973

    Advanced Member

  • Members
  • PipPipPip
  • 71 posts

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 Jan Olof

Jan Olof

    Advanced Member

  • Members
  • PipPipPip
  • 41 posts
  • LocationSweden

Posted 01 February 2011 - 11:10 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

#19 ajcg1973

ajcg1973

    Advanced Member

  • Members
  • PipPipPip
  • 71 posts

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 mbyamukama

mbyamukama

    Member

  • Members
  • PipPip
  • 16 posts

Posted 26 July 2011 - 09:01 PM

I am about to test my MRF24J40 on my Device Solutions NETMF development board from Sytech Designs. I have finished writing all the code and have found a great deal of help from here. My problem was trying to get the MRF24J40 to communicate with an XBee module from Digi and all in vain. So, I am going to use two MRF24J40s. One on a PIC and another on a NETMF board. I have also been successful trying to send out an 802.15.4 packet from a PIC (after some time!!) and so far so good. I have not yet programmed the receive yet. Can someone send me code for the receive? I am certain it has got to be an interrupt routine. I will inform on the results I get, that way there can be more information on this post.




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.