- Getting Started
- Software Products
- SNAP RF Modules
- IoT Gateways
- Legacy Products
Technically, the correct name for this two-wire serial bus is Inter-IC bus or I2C, though it is sometimes written as I2C. I2C uses two pins:
SCL – Serial Clock Line
SDA – Serial Data line (bidirectional)
Because both the value and direction (input versus output) of the SCL and SDA pins must be rapidly and precisely controlled, dedicated I2C support functions have been added to SNAPpy. Using the following functions, your SNAPpy script can operate as an I2C bus master and can interact with I2C slave devices:
i2cInit()– Prepare IO for I2C operations
i2cWrite()– Send data over I2C to another device
i2cRead()– Read data from I2C device
getI2cResult()– Check the result of the other I2C functions
To allow these functions to be as fast as possible, the IO pins used for I2C SDA and SCL are fixed. The IO pins that are reserved for I2C varies by platform, so refer to SNAP RF Modules. These pins are not dedicated for I2C, so if you are not using the I2C functions, you may use the reserved pins for other functions.
Unlike CBUS and SPI, I2C does not use separate Chip Select pins. The initial data bytes of each I2C transaction specify an I2C address. Only the addressed device will respond, so no additional GPIO pins are needed.
The specifics of which bytes to send to a given I2C slave device (and what the response will look like) depend on the I2C device itself. You will have to refer to the manufacturer’s data sheet for any given device to which you wish to interface.
Usually, I2C read and write commands begin with a hardware handshake sequence referred to as an “I2C Start”
and end with a mirror-image hardware handshake sequence referred to as an “I2C Stop”. The original implementations
i2cWrite() automatically generate these handshake sequences for you.
A typical use case looks something like this:
bytes_to_write = <sets up for the next i2cRead()> addressing_bytes = <address that begins the actual read> i2cWrite(bytes_to_write, retries, ignoreFirstAck) info = i2cRead(addressing_bytes, retries, ignoreFirstAck)
This use case works with a wide variety of I2C chips. However, various manufacturers have introduced new parts that
won’t work with the above code snippet. This is because the “I2C Stop” sequence generated at the end of
i2cWrite() function resets the I2C chip’s internal address registers, thus undoing the setup that was
accomplished by writing
bytes_to_write. Instead of an “I2C Start, I2C Stop, I2C Start, I2C Stop” sequence,
these devices require an “I2C Start, I2C Restart, I2C Stop” sequence.
To determine if your particular I2C device requires an “I2C Restart”, refer to the manufacturer’s datasheet for the I2C part. Some manufacturer data sheets refer to the “I2C Restart” as a “Repeated Start.”
Beginning in SNAP 2.5, an optional
endWithRestart argument was introduced to the
which allows you to interact with these devices natively. Just change the above example to include the new parameter:
i2cWrite(bytes_to_write, retries, ignoreFirstAck, True) # Passing True for endWithRestart info = i2cRead(addressing_bytes, retries, ignoreFirstAck)
Prior to SNAP 2.5, the only way to interface to devices having this “I2C Restart” requirement was to implement a
custom version of the
i2cWrite() functionality in your own SNAPpy script, using the lower-level SNAPpy
For examples of using the new SNAPpy I2C functions to interface to external devices, see the following scripts that are bundled with Portal:
i2cTests.py– This is the overall I2C demo script
synapse.M41T81.py– Example of interfacing to a clock/calendar chip
synapse.CAT24C128.py– Example of interfacing to an external EEPROM
synapse.M41T00CAP.py- Example of interfacing to a real-time clock chip
i2cTests.py imports two of the other scripts and exercises some of the functions within them.