I2C¶
Only a single I2C driver can be used for the time being. If you use the bitbang driver then you cannot use target builtin I2C driver. Nor can you use two different builtin drivers.
Configuration¶
Enable I2C module¶
To enable I2C, flag USE_I2C must be defined globally.
In Makefile:
USE += I2C
From command line when compiling:
make use=i2c
Master drivers¶
X86, RPI and other linux based systems¶
Linux based systems use /dev/i2c interface:
contextfori2c_master_open()must be an absolute path, i.e."/dev/i2c-13".- rest of the parameters after
contextdo not matter
Opening multiple masters is supported.
AVR¶
AVR’s have only single I2C interface as far as I know so:
frequencymust be valid fori2c_master_open()or use 0 to fallback to default 100 kHz- closest available bitrate register value will then be calculated using \((F\_CPU / frequency - 16) / 2\)
- negative results are rounded up to zero
rest of the parameters do not matter, even
mastercan beNULL
Bitbang driver¶
Bitbang driver is available on all targets that are GPIO capable.
Static mode¶
Mostly for optimizations sake on small targets, the bitbang driver requires clock and data pins to be defined in compile time as defines.
Because of this none of the parameters to i2c_master_open() matter.
To enable static bitbang driver with I2C, following conditions must be met:
- enable bitbang driver by defining
USE_I2C_BITBANGglobally withUSE_I2CandUSE_GPIO - define I2C clock and data pins using
I2C_BITBANG_SCLandI2C_BITBANG_SDA
In Makefile:
USE += GPIO I2C I2C_BITBANG
# define target specific pins
DEFINES_AVR += I2C_BITBANG_SCL=<PIN> I2C_BITBANG_SDA=<PIN>
DEFINES_PIC8 += I2C_BITBANG_SCL=<PIN> I2C_BITBANG_SDA=<PIN>
From command line when compiling:
make use="gpio i2c i2c_bitbang" defines="I2C_BITBANG_SCL=<PIN> I2C_BITBANG_SDA=<PIN>"
Dynamic mode¶
I2C bitbang driver can also be configured to use dynamic run-time values for clock and data pins.
This mode should not be used on smaller targets. It is slow and compiles ineffectively as a large piece of code example on targets AVR and PIC8.
On the other hand, you can open multiple masters using different GPIO pins in this mode.
To enable dynamic bitbang driver with I2C, following conditions must be met:
- enable bitbang driver by defining
USE_I2C_BITBANGglobally withUSE_I2CandUSE_GPIO - set bitbang driver into dynamic mode with
USE_I2C_BITBANG_DYNAMIC - call
i2c_master_open()with valid values formaster,frequency,scl_pinandsda_pin
In Makefile:
USE += GPIO I2C I2C_BITBANG USE_I2C_BITBANG_DYNAMIC
Frequency¶
As default the frequency will be set using a delay according to following rules:
- If dynamic mode is enabled using
USE_I2C_BITBANG_DYNAMIC, then delay is frequency given toi2c_master_open()and implemented asos_sleepf(1 / master->frequency / 2)which is very inaccurate on smaller targets - If target is AVR then
_delay_loop1(F_CPU / 200000 / 3)is used to achieve an inaccurate approximate of 100 kHz - On other targets
os_delay_us(4)is used to achieve an inaccurate approximate of 100 kHz
Bitbang driver also supports custom delay. This can be defined using I2C_BITBANG_DELAY_FUNC macro.
Remember that delay function should create a delay half of the actual frequency since it is called twice
per clock cycle to generate the clock for I2C.
In Makefile:
DEFINES += I2C_BITBANG_DELAY_FUNC=your_delay_func_or_macro()
Functions¶
-
int8_t
i2c_master_open(struct i2c_master *master, void *context, uint32_t frequency, uint8_t scl_pin, uint8_t sda_pin)¶ Parameters: - master (struct i2c_master *) – pointer to preallocated memory
- context (void *) – driver specific context
- frequency (uint32_t) – I2C frequency, used only if driver supports setting frequency
- scl_pin (uint8_t) – I2C clock GPIO, used only if driver supports changing scl
- sda_pin (uint8_t) – I2C data GPIO, used only if driver supports changing sda
Returns: 0 on success, negative value on errors
Open I2C driver in master mode.
-
void
i2c_master_close(struct i2c_master *master)¶ Parameters: - master (struct i2c_master *) – previously opened master
Close I2C driver.
-
int8_t
i2c_open(struct i2c_device *dev, struct i2c_master *master, uint8_t address)¶ Parameters: - dev (struct i2c_device *) – pointer to preallocated memory
- master (struct i2c_master *) – previously opened master
- address (uint8_t) – device address
Returns: - 0 on success
- -1 if device did not respond
Try to open I2C device connected to master.
-
void
i2c_close(struct i2c_device *dev)¶ Parameters: - dev (struct i2c_device *) – previously opened i2c device
Close I2C device.
-
int8_t
i2c_read(struct i2c_device *dev, void *data, int8_t size)¶ Parameters: - dev (struct i2c_device *) – previously opened i2c device
- data (void *) – pointer to a buffer where to save read data
- size (int8_t) – count of bytes to read
Returns: - 0 on success
- -1 if device did not respond
Read data from I2C device.
-
int8_t
i2c_write(struct i2c_device *dev, void *data, int8_t size)¶ Parameters: - dev (struct i2c_device *) – previously opened i2c device
- data (void *) – pointer to data to be written
- size (int8_t) – count of bytes to write
Returns: - 0 on success
- -1 if device did not respond
Write data to I2C device. Setting
data = NULLandsize = 0can be used to detect if there is a device connected to the address used by device. This is done automatically when callingi2c_open().
-
int8_t
i2c_write_byte(struct i2c_device *dev, uint8_t value)¶ Parameters: - dev (struct i2c_device *) – previously opened i2c device
- value (uint8_t) – value to write
Returns: 1 on success
Write single byte to I2C device.
-
int8_t
i2c_write_reg_byte(struct i2c_device *dev, uint8_t reg, uint8_t value)¶ Parameters: - dev (struct i2c_device *) – previously opened i2c device
- reg (uint8_t) – register to write
- value (uint8_t) – value to write
Returns: 0 on success
Write register value to I2C device. This is same as writing two bytes to I2C device, in this case
regfollowed byvalue.
-
uint8_t
i2c_read_reg_byte(struct i2c_device *dev, uint8_t reg)¶ Parameters: - dev (struct i2c_device *) – previously opened i2c device
- reg (uint8_t) – register to read
Returns: - register value on success
- 255 on errors, which can be also a valid value read from a register
Read register from I2C device. This is same as writing a single byte to device and then reading a single byte from it.