; HI2cOut
Gosub SendStart
b0 = $BC Or 0 ; Write bit
Gosub SendByte
Gosub ReadAck
b0 = $xx
Gosub SendByte
Gosub ReadAck
Gosub SendStop
; HI2cIn
Gosub SendStart
b0 = $BC Or 1 ; Read bit
Gosub SendByte
Gosub ReadAck
Gosub ReadByte
Gosub SendAck
Gosub SendStop
Yes that does seem to be the case. Read all registers, 0 to 9, then determine what the 32 bits to be written are. Copy the relevant read register 7 bits into what will be for write register 1, read register 8 for write register 2, read register 9 for write register 3, set the other bits as required, calculate parity, and write those 32-bits to registers 0 through 3.IMHO the User Manual/Data Sheet is fairly specific that the first thing to do (after a Reset) is to Read the contents of the registers (so that the Parity bit can be set/changed to the required value).
; Read registers 0 to 9 to b10 through b19
Gosub SendStart
b0 = $BC Or 1 ; Read bit
Gosub SendByte
Gosub ReadAck
Gosub ReadByte
Gosub SendAck
b10 = b0
Gosub ReadByte
Gosub SendAck
b11 = b0
Gosub ReadByte
Gosub SendAck
b12 = b0
Gosub ReadByte
Gosub SendAck
b13 = b0
Gosub ReadByte
Gosub SendAck
b14 = b0
Gosub ReadByte
Gosub SendAck
b15 = b0
Gosub ReadByte
Gosub SendAck
b16 = b0
Gosub ReadByte
Gosub SendAck
b17 = b0
Gosub ReadByte
Gosub SendAck
b18 = b0
Gosub ReadByte
Gosub SendAck
b19 = b0
Gosub SendStop
; Configure 32-bits in b20 to b23
b20 = %00000000
b21 = %01111000 And b17
b22 = %11111111 And b18
b23 = %00011111 And b19
; Set bits required for configuation
b21 = %00000100 * 0 Or b21 ; INT = 0
b21 = %00000010 * 1 Or b21 ; FAST = 1
b21 = %00000001 * 1 Or b21 ; LOW = 1
b23 = %10000000 * 0 Or b23 ; T = 0 Enabled
b23 = %01000000 * 1 Or b23 ; LP = 1
b23 = %00100000 * 1 Or b23 ; PT = 1
; Count number of bits set
b0 = NOB b20
b0 = NOB b21 + b0
b0 = NOB b22 + b0
b0 = NOB b23 + b0
; Set odd parity
b21 = bit0 ^ 1 << 7 Or b21
; Wtite registers
Gosub SendStart
b0 = $BC Or 0 ; Write bit
Gosub SendByte
Gosub ReadAck
b0 = b20
Gosub SendByte
Gosub ReadAck
b0 = b21
Gosub SendByte
Gosub ReadAck
b0 = b22
Gosub SendByte
Gosub ReadAck
b0 = b23
Gosub SendByte
Gosub ReadAck
Gosub SendStop
; Now read the data
Do
Pause 1000
; Read registers 0 to 6 to b10 through b16
Gosub SendStart
b0 = $BC Or 1 ; Read bit
Gosub SendByte
Gosub ReadAck
Gosub ReadByte
Gosub SendAck
b10 = b0
Gosub ReadByte
Gosub SendAck
b11 = b0
Gosub ReadByte
Gosub SendAck
b12 = b0
Gosub ReadByte
Gosub SendAck
b13 = b0
Gosub ReadByte
Gosub SendAck
b14 = b0
Gosub ReadByte
Gosub SendAck
b15 = b0
Gosub ReadByte
Gosub SendAck
b16 = b0
Gosub SendStop
w0 = b13 >> 4 << 8 + b16
SerTxd( "Temperature = ", #w0, CR, LF )
Loop
_______ ___ _________ ___
SDA \___/ \_/
_____ _____
SCL ___/ \_____ ___/ \_____
__ ____ _________ ___ _________ ___
SDA \_______/ \_/ \_/
_____ _____ _
SCL ___/ \_____ ___/ \_____ _________/ \___
; I2C Address Scanner for Picaxe 20X2
#picaxe 20x2
#no_data
#no_table
#terminal 9600
;
; I2C register
;
symbol sspbuf = $C9
pause 5000 ;chance to start logging.
sertxd (cr,lf,"START PROGRAM")
hi2csetup i2cmaster,2 ,i2cslow, i2cbyte ;Set up I2c. Enable SDA/SCL, set BRG divisor.
for b2 = %00000010 to %11111110 step 2 ;addresses are shifted left one bit, as bit 0 is R/W flag.
hi2cout [b2],(0) ;Just send a 0 as data (this can't be confused with a valid i2c address)
;
; If the address setup sequence is NAK'd, then hi2cout will abort and not send the data byte(0)...
; ...SSPBUF always contains the last data byte sent. If no data was sent, SSPBUF will still contain the address.
;
peeksfr sspbuf,b0 ;so, what was that last byte?
if b0 = 0 then ;if it's zero, it must be data - so the address must have been ACK'd.
b0 = b2 / 2 ;convert address used to 'normal' i2c address
sertxd (cr,lf,"** i2c response @ [",#bit7,#bit6,#bit5,#bit4,"],[",#bit3,#bit2,#bit1,#bit0,"] 0x")
;
; Print in hex too
;
b1 = b0 / 16 + "0" ;get top nybble, convert to ASCII
if b1 > "9" then
b1 = b1 + 7 ;convert 9-15 into A-F
endif
sertxd(b1) ;print it
b1 = b0 & %00001111 + "0" ;get bottom nybble, convert to ASCII
if b1 > "9" then
b1 = b1 + 7 ;convert 9-15 into A-F
endif
sertxd(b1) ;print that too.
else
if b0 <> b2 then
sertxd (cr,lf,"Um...something unexpected happened!",#b2) ; this never appears ;-)
endif
endif
next
sertxd (cr,lf,"END PROGRAM")
end
This could be the case, but I have 1.5 reasons to move this option to the end of the list. One - as in the post above, I believe, pic hardware does receive and understand the ACK. 0.5 - I tried to run the bit-banged code at 64MHz and it runs like a charm. It is still about 50 times slower than i2cslow, though .2) There is a delayed response in setting ACK by the TLV493D. It takes so long to set it that the hardware I2C doesn't see it but the bit-banged I2C executes slowly enough that it has been set by the time the software comes to read the ACK
C1 is there, the GND lines are there and I have experimented with the pull-up resistors, but 1.2k seems to produce the same results as 4.7k or 10k. Using 1.2k helps with the slew rate, so I also tried 720Ohms, but at least according to the scope solution I have, the problem is not the slew rate of ACK pulse. The slew rate of picaxe driven SDA transitions is actually worse than that of the sensor (ACK). C2 and R are optional and provide additional filtering, which does not seem to be my problem. Of course, everything is on a breadboard, which is not optimal, but should work for slow speeds of I2C at this point.6) There is something about the circuit or hardware configuration which prevents the TLV493D from operating as it should. Are all three GND pins connected to 0V ? Are all resistors and capacitors fitted as recommended in the Application Circuit ?
Given slave driven clock stretching is part of I2C standard and used frequently, lets assume they figured they do not need to mention it in the data sheet .1) The TLV493D tried to do clock-stretching but that failed to prevent the rise of SCL. However the datasheet does not describe clock-stretching at all.
Perhaps your PICAXE has been damaged or you are doing something wrong ?Ok, I'm suspicious, because I have another device I was very interested in I'm still struggling to get reliable results from and people with all sorts of ...duinos seem to succeed with no hassle of what so ever. So one starts to think there is something strange with the PIC.
Given they produced one of the most verbose datasheets seen, have described I2C operation in such minute detail, it would seem highly unlikely to me that they would not describe clock-stretching if they were using that.Given slave driven clock stretching is part of I2C standard and used frequently, lets assume they figured they do not need to mention it in the data sheet .
For clock-stretching; the master lets the SCL float high, the device would pull it low to stop it floating high, the master will wait until it can see a high on the bus before continuing.Can we think of anything electrical that might prevent this from succeeding? Since the line is pulled up with a resistor, PIC believes it should release and releases, the device tries to maintain it low but fails to do it alone. Does this mean the device is failing to produce enough current to keep the line low? Higher value pull-up resistor then?
Maybe. I have plenty more picaxes at home, so I will try another one. Perhaps a 20X2 for the fun of it. The current one I'm working with is 40X2, huge piece of IC, B.3 firmware if I remember correctly, but I can look up how to check it and double-check it. Of course, it is highly likely I'm doing something wrong. And much more likely than there being something wrong with pic or picaxe . The interesting thing is not who is to blame, it is to get the thing working. I love picaxe, don't worry.Perhaps your PICAXE has been damaged or you are doing something wrong ?
I am using 720R, but I have also used 1k2 [assembled from three different values] and 4k7 without noticeable difference, but I did not scope SCL for high/low voltage. Will do. It is on AXE091, so full schematic is a bit overwhelming, but a screenshot of the breadboard portion is perfectly possible. Will do.It is possible that the slave device doesn't have a powerful enough open-drain to pull SCL low but that seems unlikely if the design allows for pulling SDA low. Increasing the pull-up may help. A weak pull of SCL low should be observable on an analogue scope, reducing the voltage if not pulling it completely towards 0V.
The datsheet suggests 1K2 resistors for pull-up. What resistors are you using ? Perhaps post your full circuit diagram.
Came from Farnell, UK location specifically, have supplied me with hundreds of working ICs up until now, seem like serious people. This is the second unit I'm testing (discarded one to check if it is not to blame while nothing worked at all) and I have 8 more to 'kill', so, of course, I can test another one. Will do.Of course it could be that your TLV493D is defective or damaged. Did it come from a reputable source or some random outlet ? Do you have another to compare operation with ?
I can't think of anything other than comparing the logic trace with bit-banging which works with that for HI2C which doesn't. You could try slowing down the HI2C by fiddling with the I2CSLOW value to see what effect that has.Is there a further way to debug this?
Hippy, thank you for your reply. This thread describes the battle with the device in question: http://www.picaxeforum.co.uk/showthread.php?29745-BNO055-failureIt might be better to move on to the other I2C device you say also doesn't work. If there is some systemic issue then that might help reveal what it is.