Please note before reading my description below, that I tested the code on an i2c eeprom also connected to the board I'm working on. I visited almost every page on this site, and eventually found this:
Q. My software master I2C code does not read correct data from the SRF08/SRF10, but its works fine with an I2C EEPROM chip. Why is this?
A. The most likely cause is the master code not waiting for the I2C bus hold. This is where the slave can hold the SCL line low until it is ready. When the master releases SCL (remember it's a passive pull-up, not driven high) the slave may still be holding it low. The master code should then wait until it actually does go high before proceeding.
Writing operations seem to succeed, as the led flashes when I send the command to initiate a ranging. Also, when I send the command sequence to change the address of the sensor, the led flashes differently after the next power-up.
When I try to read a value, for example from location 0x1, the sensor does not respond as expected. The SRF02 datasheet states that location 0x1 should return 0x80. Unfortunatly I get 0x8C. So I connected the board to the scope and noticed an inconsistency.
- Code: Select all
0xE0 0x0 0x1 0x0 0xE1 0x0 0x8C 0x0
11100000 0 00000001 0 11100001 0 10001100 0
addr ack loc ack addr+R ack value ack
The clock signal seems fine, until it's receiving the requested value:
- Code: Select all
11100000 0 00000001 0 11100001 0 10001100 0
|
|
+----------------+
|
_ V _ _
| | _ | |
_ _ _ _| |_| |_ _ _| |_ _ _
0 0 0 0 1 0 1 0 0 0 1 1 0 0 0
The clock pulse for this bit only, has exactly half the height of every other clock pulse.
This happens every time, not just a one-time glitch.
If the problem is indeed related the above Q&A item, is there any resolution to solve it with software? I simply can't directly access the SDA or SCL lines, because those are managed by the hardware.
A somewhat unpleasant solution is to take 2 available IO pins and implement the complete I2C protocol in software.
I tried with pull-up resistors, without pull-up resistors, with the pull-up resistors already available on the eeprom circuit and without the pull-up resistors on the eeprom circuit. Every combination has the same result.
Usefull information:
TUSB3210 Electrical diagram: http://tusb3210.com/Oldsite/Docs/TUSB3210V13FEB2006.pdf
TUSB3210 Datasheet: http://tusb3210.com/Oldsite/Docs/Datash ... SB3210.pdf (usefull pages: from 34 to 38).
Current implementation:
- Code: Select all
I2CSTA = 0; // setup I2C
I2CADR = (0x70 << 1); // set address with read bit disabled
I2CDAO = 0x1; // send location (automatically sends start sequence and address first)
while((I2CSTA & TXE) == 0); // wait for succesfull transmission (ACK)
I2CADR = (0x70 << 1) | 0x1; // set address with read bit enabled
I2CDAO = 0x0; // send dummy byte to initiate transfer (see datasheet)
I2CSTA |= SRD; // tell hardware this is our last byte, so the stop sequence should be sent
while((I2CSTA & RXF) == 0); // wait for byte
P1 = ~I2CDAI; // set value on leds (0x8C)

