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

I2C + Serial EEPROM (24LC32A)


  • Please log in to reply
7 replies to this topic

#1 demonGeek

demonGeek

    Advanced Member

  • Members
  • PipPipPip
  • 42 posts
  • LocationCanada

Posted 10 March 2011 - 08:34 AM

I'm playing with I2C and a serial EEPROM (24LC32A) on my N+.

I have it working but I've run into a couple of issues that - I think - require more granular I2C control than I can get through the I2CDevice in Microsoft.SPOT.Hardware.

Here are a couple of examples from the 24LC32A datasheet:

  • The datasheet describes an 'Acknowledge Polling Flow' which allows the code to loop while waiting for a write operation on the device to complete. You create a loop to send a control byte to the device and then parse the ACK looking for a zero at which point the device is ready to accept a new operation.
  • The 'Random Read Sequence' which allows a byte to be read from a specified address requires a control sequence that includes a start signal (high to low transition on the SDA line while SCL is high) in the middle like this: START + CONTROL-BYTE + ADDR-HI + ADDR-LO + START + CONTROL-BYTE...STOP

Since the I2CDevice class seems to wrap everything up in an I2CTransaction, it seems that I don't have control over when the start signal gets sent or even the ability to parse the ACK.

Any thoughts/suggestions would be most welcome.

#2 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 10 March 2011 - 04:16 PM

I'm playing with I2C and a serial EEPROM (24LC32A) on my N+.

  • The 'Random Read Sequence' which allows a byte to be read from a specified address requires a control sequence that includes a start signal (high to low transition on the SDA line while SCL is high) in the middle like this: START + CONTROL-BYTE + ADDR-HI + ADDR-LO + START + CONTROL-BYTE...STOP

You'd need 4.1.1 alpha firmware for that (Repeated Start condition support).

#3 demonGeek

demonGeek

    Advanced Member

  • Members
  • PipPipPip
  • 42 posts
  • LocationCanada

Posted 10 March 2011 - 07:35 PM

You'd need 4.1.1 alpha firmware for that (Repeated Start condition support).

Thanks CW2, I have 4.1.1 firmware and the code from this post.

Please correct me if I'm wrong here but I don't think that's what I need. The repeated start condition fix seems to just be adding extra bytes immediately after the initial start signal. I don't see how that lets me generate this control sequence:

START + CONTROL-BYTE + ADDR-HI + ADDR-LO + START + CONTROL-BYTE...STOP

The problem is the (highlighted) start signal in the middle of the sequence - there's no preceding stop so I have to be able to generate a start signal in the middle of the control sequence (transaction). The relevant information from the datasheet is as follows:

To perform a random read operation, first the word address must be set. This is done by sending the word address to the 24LC32A as part of a write operation (R/W bit set to zero). After the word address is sent, the master generates a start condition following the acknowledge. This terminates the write operation, but not before the internal address pointer is set. Then the master issues the control byte again but with the R/W bit set to a one. The 24LC32A will then issue an acknowledge and transmit the 8-bit data word.



Here's the diagram from the datasheet:

Posted Image

I'm an experienced programmer but new to the whole electronics thing so I might have this all wrong - I just got my N+ and wanted to play with I2C; this EEPROM was the only I2C device I had lying around...

When I tested with the 4.1.1 firmware and revised I2C Transaction code I could see the extra bytes on the logic analyzer but I didn't see any extra start signals being generated.

#4 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 10 March 2011 - 07:42 PM

demonGeek, The "internalAddress" from the code you downloaded is the key here. Pass in the address [((0x100 * addressHigh) + addressLow), 2 bytes] as the internalAddress parameter and you should be good to go. Chris

#5 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 10 March 2011 - 08:11 PM

The repeated start condition fix seems to just be adding extra bytes immediately after the initial start signal. I don't see how that lets me generate this control sequence:

START + CONTROL-BYTE + ADDR-HI + ADDR-LO + START + CONTROL-BYTE...STOP

The fix does exactly that (I know this for sure, because I have developed it and I have two working 24LCxx EEPROMs right in front of me ;- ). In order to generate the above sequence, call CreateReadTransaction(..., address, 2) from Chris' example. The address will be written onto the bus as ADDR-HI and ADDR-LO.

When I tested with the 4.1.1 firmware and revised I2C Transaction code I could see the extra bytes on the logic analyzer but I didn't see any extra start signals being generated.

Could you please share the logic analyzer output? (Please note that Start condition is just High -> Low transition on SDA while SCL is High, it is not a bit with duration of the clock signal period).

#6 demonGeek

demonGeek

    Advanced Member

  • Members
  • PipPipPip
  • 42 posts
  • LocationCanada

Posted 10 March 2011 - 08:15 PM

demonGeek,

The "internalAddress" from the code you downloaded is the key here. Pass in the address [((0x100 * addressHigh) + addressLow), 2 bytes] as the internalAddress parameter and you should be good to go.

Chris


Thanks Chris, that was the bit I was missing!

I totally misunderstood what that address was - I thought it was the device address.

It's working fine now.

#7 demonGeek

demonGeek

    Advanced Member

  • Members
  • PipPipPip
  • 42 posts
  • LocationCanada

Posted 10 March 2011 - 08:21 PM

The fix does exactly that (I know this for sure, because I have developed it and I have two working 24LCxx EEPROMs right in front of me ;- ). In order to generate the above sequence, call CreateReadTransaction(..., address, 2) from Chris' example. The address will be written onto the bus as ADDR-HI and ADDR-LO.


Could you please share the logic analyzer output? (Please note that Start condition is just High -> Low transition on SDA while SCL is High, it is not a bit with duration of the clock signal period).



Yeah, sorry CW2 - I misunderstood the internalAddress param on CreateReadTransaction (I thought it was the device address) so the extra Start wasn't getting generated. I fixed up the code and now it works perfectly - the logic analyzer output looks exactly like the datasheet.

Many thanks for your help - I still have a lot to learn but getting great help like this is always appreciated!

#8 demonGeek

demonGeek

    Advanced Member

  • Members
  • PipPipPip
  • 42 posts
  • LocationCanada

Posted 10 March 2011 - 09:12 PM

Having got this to work I thought it might be useful to post the test code I'm using so that others might benefit from it too:

public static void Main()
{
	byte[] buffer = new byte[1];
	int bytesWritten = 0;

	// Create the I2C device (device address: 0x54, clock rate: 50Khz)
	I2CDevice.Configuration i2cConfig = new I2CDevice.Configuration(0x54, 50);
	I2CDevice eeprom = new I2CDevice(i2cConfig);
			
	// Write the letter 'A' (0x41) to address 0x0000 on the eeprom
	I2CDevice.I2CTransaction[] writeTx = new I2CDevice.I2CTransaction[] { CreateWriteTransaction(new byte[] { 0x00, 0x00, 0x41 }, 0, 0) };
	bytesWritten = eeprom.Execute(writeTx, 1000);

	// Read the byte at address 0x0000 on the eeprom
	I2CDevice.I2CTransaction[]  readTx = new I2CDevice.I2CTransaction[] { CreateReadTransaction(buffer, 0x0000, 2) };
	do { bytesWritten = eeprom.Execute(readTx, 1000); } while (bytesWritten == 0);

	Debug.Print(buffer[0].ToString());

	Thread.Sleep(Timeout.Infinite);
}

#region see: http://forums.netduino.com/index.php?/topic/944-i2c-internaladdress-repeated-start-bit-support/

static I2CDevice.I2CWriteTransaction CreateWriteTransaction(byte[] buffer, uint internalAddress, byte internalAddressSize)
{
	I2CDevice.I2CWriteTransaction writeTransaction = I2CDevice.CreateWriteTransaction(buffer);
	Type writeTransactionType = typeof(I2CDevice.I2CWriteTransaction);

	FieldInfo fieldInfo = writeTransactionType.GetField("Custom_InternalAddress", BindingFlags.NonPublic | BindingFlags.Instance);
	fieldInfo.SetValue(writeTransaction, internalAddress);

	fieldInfo = writeTransactionType.GetField("Custom_InternalAddressSize", BindingFlags.NonPublic | BindingFlags.Instance);
	fieldInfo.SetValue(writeTransaction, internalAddressSize);

	return writeTransaction;
}

static I2CDevice.I2CReadTransaction CreateReadTransaction(byte[] buffer, uint internalAddress, byte internalAddressSize)
{
	I2CDevice.I2CReadTransaction readTransaction = I2CDevice.CreateReadTransaction(buffer);
	Type readTransactionType = typeof(I2CDevice.I2CReadTransaction);

	FieldInfo fieldInfo = readTransactionType.GetField("Custom_InternalAddress", BindingFlags.NonPublic | BindingFlags.Instance);
	fieldInfo.SetValue(readTransaction, internalAddress);

	fieldInfo = readTransactionType.GetField("Custom_InternalAddressSize", BindingFlags.NonPublic | BindingFlags.Instance);
	fieldInfo.SetValue(readTransaction, internalAddressSize);

	return readTransaction;
}

#endregion





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.