I2C with spin: Actively Driving SDA (probable rehash)
tomcrawford
Posts: 1,126
in Propeller 1
I am fiddling with the HT16K33 16 by 8 LED controller. It has an I2C interface. I downloaded Mike Green's Basic I2C Driver . I used I2CStart, I2CStop, and I2CWriteByte. Here is the WriteByte snippet.
The screen grab ActiveHighSDA shows writing data to a LED. The slave address is $E0, the register address is 0, and the data written is $2120 (a nonsense glyph). Everything looks great; got ACKs, Start, Stop. And it functions just fine. Stuff shows up on the LEDs just like it should. But look a little closer (BusCrash.jpg) After the eight data bit of the $21 byte, there is 8.6 (or so) microseconds of the SDA line being about half high.
I believe what's happening is this: The slave device is driving SDA LOW (ACK) while the propellor is still driving SDA HIGH (the "1" in $21). Looking at the snippet above, spin cannot execute the dira[SDA]~ instantly after making the clock LOW. Now, is this really a problem? I think it would shorten the life of the two opposing output stages, and would cause some RFI.
The fix is really simple; be sure there is a pullup on SDA and only ever drive it LOW. Here is a modified WriteByte:
OpenCollSDA.jpg shows the bus with this code.
PUB I2cWriteByte(data) data <<= 24 'align first bit repeat 8 outa[SDA] := (data <-= 1) & 1 'send one bit, msb first outa[SCL]~~ outa[SCL]~ dira[SDA]~ 'allow ack bit outa[SCL]~~ 'ignore ack bit outa[SCL]~ outa[SDA]~ dira[SDA]~~
The screen grab ActiveHighSDA shows writing data to a LED. The slave address is $E0, the register address is 0, and the data written is $2120 (a nonsense glyph). Everything looks great; got ACKs, Start, Stop. And it functions just fine. Stuff shows up on the LEDs just like it should. But look a little closer (BusCrash.jpg) After the eight data bit of the $21 byte, there is 8.6 (or so) microseconds of the SDA line being about half high.
I believe what's happening is this: The slave device is driving SDA LOW (ACK) while the propellor is still driving SDA HIGH (the "1" in $21). Looking at the snippet above, spin cannot execute the dira[SDA]~ instantly after making the clock LOW. Now, is this really a problem? I think it would shorten the life of the two opposing output stages, and would cause some RFI.
The fix is really simple; be sure there is a pullup on SDA and only ever drive it LOW. Here is a modified WriteByte:
PUB I2cWriteByte(data) 'modified to not drive SDA HIGH 'assumes it is driving SDA LOW when enters data <<= 24 'align first bit repeat 8 if ((data <-= 1) & 1) == 0 'extract one bit, msb first dira[SDA]~~ 'drive it low else dira[SDA]~ 'pullup pulls high outa[SCL]~~ outa[SCL]~ dira[SDA]~ 'allow ack bit outa[SCL]~~ 'ignore ack bit outa[SCL]~ outa[SDA]~ dira[SDA]~~
OpenCollSDA.jpg shows the bus with this code.
Comments
-Phil
Thanks.