Main Site Documentation

[FEZ PANDA] i2c read transaction problem


#1

Hi! I’ve got a problem with the I2C read transaction.
When I try to write and read from the 24LC512 EEPROM I’ve got no problem, and I can write and read all the data I want, but if I try to read from a AnalogDevices SigmaDSP, I get in troumble.

The main problem is that when I a read transaction with the command:

xActions[i] = I2CDevice.CreateReadTransaction(myValue);

The transaction stops…and when there is used the Read Address (my device address + 1)… my device doesn’t reply, because it thinks that the i2c transaction is ended. In the figure it is showed the LogicAnalyser transaction Analysis made on the bus…
My device needs (I know this by the datasheet) this kind of the read sequence:

  • START
  • CHIP ADDRESS (0X68)
  • ACK BY SLAVE
  • SUB ADDRESS HIGH
  • ACK BY SLAVE
  • SUB ADDRESS LOW
  • ACK BY SLAVE
  • START (HERE I GET THE WRONG STOP CONDITION I SHOULD CHANGE!!!)
  • CHIP ADDRESS READ (0X69)
  • DATA BYTE 1
  • ACK BY MASTER
  • (OPTIONALLY SOME MORE DATA BYTE AND ACK BY MASTER…)
  • STOP CONDITION

So, is there a way to force the FEZPanda to DO NOT create the STOP condition and continue with a Start Condition, as my needs?

Regards,
Simone


#2

If you have a list of transactions, then FEZ shouldn’t send STOP in between. Can you post few lines of code that demonstrate what you are doing?

Very small example please.


#3

I think the Data sheet has a typo… If the device requires a start condition on the read transaction… stands to reason that a stop should have been sent before hand. You can always use the SPI instead if you’re struggling!

Cheers Ian


#4

Oh, yes…the SPI for me is a much better (and simpler) protocol…but to use it on my device I should make a new boards for the ADAU1701, since I’ve got an evaluation board that don’t permits to use the SPI >:(
Sorry, but…what do you mean for “stands to reason that a stop should have been sent before hand”???

here it is:


using System;
using System.Threading;

using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;

using GHIElectronics.NETMF.FEZ;
using GHIElectronics.NETMF.Hardware;

namespace FEZPandaEEPROMI2C_withDSPclass
{
    public class Program
    {
        /*static i2c_eeprom MyEEprom = new i2c_eeprom(0xA0, 400);*/
        static i2c_adau1701 ad1701I2C = new i2c_adau1701(0xa0, 100);

    public static void Main()
        {
            int i = 0;
            
            // Blink board LED
            bool ledState = false;
            OutputPort led = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.LED, ledState);
            i = 0;

            for (i = 0; i < myDsp.program_data.Length; i++)
            {
                ad1701I2C.Write(i, myDsp.program_data[i]);
                Debug.Print("written " + myDsp.program_data[i].ToString() + " @ address " + i.ToString());
                ledState = !ledState;
                led.Write(ledState);
            }

            for (i = 0; i < myDsp.program_data.Length; i++)
            {
                Debug.Print("read " + ad1701I2C.Read(i).ToString() + " @ address " + i.ToString());
                ledState = !ledState;
                led.Write(ledState);
            }

and the Write and read methods are:


public void Write(int Register, byte data)
        {
            var xActions = new I2CDevice.I2CTransaction[1];
            xActions[0] = I2CDevice.CreateWriteTransaction(new byte[] { (byte)(Register >> 8), (byte)(Register & 0xFF), data });
            I2C.Execute(xActions, 1000);
            Thread.Sleep(5); // Mandatory after each Write transaction !!!
        }

public byte Read(int Address)
        {
            var Data = new byte[1];
            var xActions = new I2CDevice.I2CTransaction[1];
            xActions[0] = I2CDevice.CreateWriteTransaction(new byte[] { (byte)(Address >> 8), (byte)(Address & 0xFF) });
            I2C.Execute(xActions, 1000);
            Thread.Sleep(5);   // Mandatory after each Write transaction !!!
            xActions[0] = I2CDevice.CreateReadTransaction(Data);
            I2C.Execute(xActions, 1000);

            return Data[0];
        }


Thanks for your support
Regards,
Simone


#5

Ahh, I see your problem.

A start is sent at the start of a transaction and an Stop is sent at the end of a transaction.

If you want more than one start before the stop then you must add more commands to the transaction.


public byte Read(int Address)
        {
            var Data = new byte[1];
            var xActions = new I2CDevice.I2CTransaction[1];
            xActions[0] = I2CDevice.CreateWriteTransaction(new byte[] { (byte)(Address >> 8), (byte)(Address & 0xFF) });
            I2C.Execute(xActions, 1000);
            Thread.Sleep(5);   // Mandatory after each Write transaction !!!
            xActions[0] = I2CDevice.CreateReadTransaction(Data);
            I2C.Execute(xActions, 1000);
 
            return Data[0];
        }

Here you create 2 distinct transactions with Starts and Stops.

If you want Start, Restart, Stop then it should look more like this:


        public byte Read(int Address)
        {
            var Data = new byte[1];
            var xActions = new I2CDevice.I2CTransaction[2];
            xActions[0] = I2CDevice.CreateWriteTransaction(new byte[] { (byte)(Address >> 8), (byte)(Address & 0xFF) });
            xActions[1] = I2CDevice.CreateReadTransaction(Data);
            I2C.Execute(xActions, 1000);

            return Data[0];
        }

This creates one transaction with two starts and one stop

Hope this helps…

Thanks,
Errol


#6

See my first response

Like Errol also noted, you have to have all your transaction in one list in order for them to go out with no stop condition in between.


#7

Oh my God!!! Thank you… It was so stupid…ahahahah!!

I’ll try in this way, creating a new Read Method, and see it with my Logic Analyser!

again thank you all!


#8

Hi! I’ve done some modifications:


public byte ReadOneByte(int Address)
        {
            var Data = new byte[1];
            var xActions = new I2CDevice.I2CTransaction[2];
            xActions[0] = I2CDevice.CreateWriteTransaction(new byte[] { (byte)(Address >> 8), (byte)(Address & 0xFF) });
            /*
             * I2C.Execute(xActions, 1000);
             * Thread.Sleep(5);   // Mandatory after each Write transaction !!!
             */
            xActions[1] = I2CDevice.CreateReadTransaction(Data);
            I2C.Execute(xActions, 3000);

            Thread.Sleep(5);
            return Data[0];
            
        }

I have removed the “I2C.Execute(xActions, 1000);” so I have no more Stop condiction…but I 've got another problem!!!

If I use a Slave address of “0xA0” (the EEPROM on the circuit) I can use this new method and it does works well…but if I use the ADAU1701 slave address, 0x68, I can see that the device reply well on the write transaction, but the read device address (that should be 0x69… 0x68+1) becomes 0xE9…
In binary notation I have:

  • 0b11101001, but I should have 0b01101001… what could it be???

#9

Did you try it at a low clock frequency?


#10

it is at 100 kHz… it is the standard low frequency for I2C… can I lower this value??? I’ll give a try anyelse…


#11

I have tried with 50 kHz and 20kHz…but it doesn’t seems to be a timing issue… I get the same report:

  • Start
  • write 0x68
  • ack
  • write 0x04
  • ack
  • write 0x00
  • ack
  • Start
  • write 0xe9, [italic]the wrong word, it should be 0x69[/italic]
  • ack… why do I get an ACK here as there are no devices with this address???
  • write 0x00
  • NACK
  • STOP

and so on…


#12

[quote]- ack… why do I get an ACK here as there are no devices with this address???
[/quote]
What if you use some other address? do you get an ACK back?


#13

If I use the EEPROM Address yes… but if I use some others address, the process stops with a NACK in the write sequence (the first after the start sequence) since there is no device responding…


#14

…can we then assume that the analyzer is wrong? It can’t be the the eeprom and FEZ is wrongly using the wrong address!


#15

I don’t like the way the address handling is coded in the i2c sample; I had a quick look recently but didn’t battle through to conclusion.

You might find you need to explicitly use a 7-bit address, and you are currently using an address that is out of that range. Use the BASE 7-bit address and let the code move it to 8-bit with 0/1 for the read or write as appropriate.

I personally am thinking I’ll make that explicit in my code when I get back to it - only use the 7-bit address, check it’s not out of range, and then the headache should be reduced.


#16

Sorry Brett, I think I didn’t understood your reply…

I’m not using a 10 bit address… I have 2 devices in the I2C line, but I use only 1 of them in my code:

  • I’ve got a EEPROM that uses the 0xA0 address to write, and 0xA1 to read…and it works very well;
  • I’ve got a SigmaDSP ADAU1701 device, that uses the 0x68 address to write (that seems to work well…as the ACK by device are correct), and uses the 0x69 address to read transactions.

The FEZ seems to write well to my ADAU1701 device…but with my logic analyzer it seems to use the 0xE9 address…
It is in binary:11101001 and not 01101001…
I think it could be a timing problem of my logic analyzer, since the ADAU1701 reply with a ACK…but I can’t anyway read the datas I have got written in the internal memory
It is a very strange problem…

I have got a SigmaDSP programmer (USBi) and it could comunicate well with my ADAU1701 device with the 0x68 address (and 0x69 for reading value…), but I can’t read the signals due to too much speed of the programmer…

Thanks for your support


#17

Sorry, let me try to explain. The key is making sure that you’re talking about i2c addresses correctly.

Technically I2C addresses are 7-bits only. You’ve referred to them with 8 bit addresses, which are the valid addresses for your devices (assuming all address pins are taken to GND). The TRUE ADDRESS that anyone reading a data sheet would interpret is a 7-bit address and then the R/W bit; even the netmf real I2C call I2CDevice.Configuration takes a 7-bit address. So I personally would suggest that your constructor takes a 7-bit address and you only refer to devices by their 7-bit address, not the 8-bit read or write address. That is how I intend to have my constructor.

What I initially suspected might have happened is you simply read an address from the data sheet that gave you the 7-bit address while your constructor takes an 8-bit address; I’ve checked the data sheets and don’t believe that is the case (but assume still that you have all address pins tied to GND).

So what seems strange to me is that you have two different I2C devices that each appear to work, but on different devices. That to me makes me think that the LA bits are a mis-read as Gus says, but the 1001 seems to coincidental to be wrong. And why aren’t you

So the only thing I can suggest at this point is stepping back and creating a test app just to make simple reads and writes to your device to prove it does or doesn’t work; make sure you check return codes fully etc. I’d work from a simple starting point that has nothing fancy just code in main() and see whether that works?

good luck on the quest


#18

I have done some measures with a professional equipment of a friend of mine, and I saw a lot of noise in the transactions with the official programmer, and a frequency of 83kHz I2C clock.

Anyway I finally get the things working using a self-booting system for the DSP, and using the FEZ Panda to “command” the DSP to change its own parameters, and it works very well!

Now I’m integrating all the stuffs in a C# class to have all the commands coded…or something similar.

The reading transactions doesn’t works, but I have to inspect some more with a pro equipment to know what is going on… but I think the wrong read address is a logic analyzer error, I’m almost sure of this.

Now I’m getting working on the SD-CARD interface, to have access to a FAT16 partition, and read some files…but it is another stuff (but the same project)

Thank you all and have a nice day!!