Help with i2c code
mynet43
Posts: 644
I'm using a modified i2c routine to communicate with an autofocus camera module.
When doing a read from their register, I supply the clock signal and they return the data, bit by bit.
The data are clocked into the data line on the trailing edge of the clock signal.
I've attached a scope trace that shows the data should be $99. What I'm seeing from the code is $FF instead.
Would someone please take a look at the code below and the scope trace and see if you can figure out what I'm doing wrong.
The scope trace shows the clock in red and the data in blue.
Thank you for your help.
Jim
When doing a read from their register, I supply the clock signal and they return the data, bit by bit.
The data are clocked into the data line on the trailing edge of the clock signal.
I've attached a scope trace that shows the data should be $99. What I'm seeing from the code is $FF instead.
Would someone please take a look at the code below and the scope trace and see if you can figure out what I'm doing wrong.
The scope trace shows the clock in red and the data in blue.
Thank you for your help.
Jim
PUB i2cRead(ackbit)| i2cData ' Read in i2c data, Data byte is output MSB first if i2cStarted == true ' set the SCL to output and the SDA to input dira[i2cSCL]~~ ' SCL -> output dira[i2cSDA]~ ' SDA -> input outa[i2cSCL] := _PinLow ' clock in the byte i2cData := 0 repeat 8 outa[i2cSCL] := _PinHigh waitcnt(cnt+800) ' delay 1/100000 sec outa[i2cSCL] := _PinLow waitcnt(cnt+800) ' delay 1/100000 sec i2cData := (i2cData << 1) | ina[i2cSDA] waitcnt(cnt+800) ' delay 1/100000 sec ' send the ACK or NAK outa[i2cSDA] := ackbit ' init pin B4 dira[ ] dira[i2cSDA]~~ ' SDA -> output waitcnt(cnt+800) ' delay 1/100000 sec outa[i2cSCL] := _PinHigh waitcnt(cnt+800) ' delay 1/100000 sec outa[i2cSCL] := _PinLow ' clock out ackbit waitcnt(cnt+800) ' delay 1/100000 sec ' return the data return i2cData
Comments
How about use a proven i2c object like MinimalI2cDriver. See examples in this thread. You should post the entire code help sort out what you have. $FF may mean it is reading the lines high with no change. Using pullups?
Here is a zipped version I modified to test with my DS1340C using FullDuplexSerial and PST on the PC.
i2cDemoApp_002 - Archive [Date 2012.03.04 Time 08.15].zip
BTW xtal is set to 6.5MHz
The reason I can't use library code is that it's an SCCB protocol (camera), not standard i2c. The input data is not valid when the clock is high, it's set when the clock transitions to low. You can see this from the scope trace.
Thank you for your help.
OK, here's the entire code:
This is the main program:
This is the program i2cObject.spin. Included in the main program.:
Have you tried to do this inline instead of using the counters? It might be easier to get this running first.
I'm not using the counter for the i2c clock, it's used for the pixel clock in the camera, different pin.
The i2c clock is done in-line.
Such as:
outa[i2cSCL] := _PinHigh
Please keep looking I think all of the code of interest is in-line.
Thanks!
Jim
P.S. The code in i2cRead matches the scope traces exactly, except for the ina[i2cSDA].
It seems like the ina[ ] command isn't working. It's always returning a '1'.
I thought this might be caused by the voltage not being low enough. So I changed the program to stop when the data line was low.
When I measured the voltage, it was 0.01V. This is obviously low enough for the ina[ ] to return a '0'. But it always returns a '1'.
Here's the code I used to stop it when the data line was low.
Please let me know if you can see why the ina[ ] is always returning a '1'.
Thank you for your help.
As usual, operator error
The code was not the problem. It was me...
When I measured the data pin voltage, it was at the output of the camera module.
What I didn't take into account was the fact that I had a 10K resistor between the camera and the Prop pin.
Besides this, I had a 10K pullup on the Prop side of the signal. Looking at the circuit, this turned out to be a fine voltage divider. So when the camera dropped the voltage to '0', the resistors dropped the voltage going to the Prop to 3.3/2 or 1.65V. Of course this is high, so the Prop was always seeing a high input. Grrrr...
I replaced the 10K current limiting resistor with a 1K and everything started working. The 'low' input to the Prop is now about 0.3V, which works fine.
Thank you for all your help. It kept me going. If anyone needs a driver for an SCCB camera interface, you're welcome to the code.
Jim