12 KiB
I2C Devices
- I2C Devices
Register I2C Device
int mr_i2c_dev_register(struct mr_i2c_dev *i2c_dev, const char *name, int addr, int addr_bits);
| Parameter | Description |
|---|---|
| i2c_dev | I2C device structure pointer |
| name | Device name |
| addr | Device address |
| addr_bits | Device address bits |
| Return Value | |
=0 |
Registration succeeds |
<0 |
Error code |
name: The I2C device needs to bind to the specified I2C bus, and the name needs to add the bus name, such as:i2c1/dev-name.addr: Device address (the lowest bit is read/write bit, please pass the address shifted to the left).addr_bits: Device address bits:MR_I2C_ADDR_BITS_7: 7-bit address.MR_I2C_ADDR_BITS_10: 10-bit address.
Open I2C Device
int mr_dev_open(const char *name, int oflags);
| Parameter | Description |
|---|---|
| name | Device name |
| oflags | Open device flags |
| Return Value | |
>=0 |
Device descriptor |
<0 |
Error code |
name: The I2C device is bound to the I2C bus and needs to add the bus name, such as:i2cx/dev-name,i2c1/dev-name.oflags: Open device flags, supportMR_OFLAG_RDONLY,MR_OFLAG_WRONLY,MR_OFLAG_RDWR.
Note: When using, the I2C device should be opened separately for different tasks according to the actual situation, and the appropriate oflags should be used for management and permission control to ensure that they will not interfere with each other.
Close I2C Device
int mr_dev_close(int desc);
| Parameter | Description |
|---|---|
| desc | Device descriptor |
| Return Value | |
=0 |
Close successfully |
<0 |
Error code |
Control I2C Device
int mr_dev_ioctl(int desc, int cmd, void *args);
| Parameter | Description |
|---|---|
| desc | Device descriptor |
| cmd | Command code |
| args | Command parameters |
| Return Value | |
=0 |
Setting succeeds |
<0 |
Error code |
cmd: Command code, supports the following commands:MR_CTL_I2C_SET_CONFIG: Set I2C device configuration.MR_CTL_I2C_SET_REG: Set register value.MR_CTL_I2C_SET_RD_BUFSZ: Set read buffer size.MR_CTL_I2C_CLR_RD_BUF: Clear read buffer.MR_CTL_I2C_SET_RD_CALL:Set read callback function.MR_CTL_I2C_GET_CONFIG: Get I2C device configuration.MR_CTL_I2C_GET_REG: Get register value.MR_CTL_I2C_GET_RD_BUFSZ: Get read buffer size.MR_CTL_I2C_GET_RD_DATASZ: Get read buffer data size.MR_CTL_I2C_GET_RD_CALL:Get read callback function.
Set/Get I2C Device Configuration
I2C device configuration:
baud_rate: Baud rate.host_slave: Master/slave mode.reg_bits: Register bits.
/* Set default configuration */
struct mr_i2c_config config = MR_I2C_CONFIG_DEFAULT;
/* Set I2C device configuration */
mr_dev_ioctl(ds, MR_CTL_I2C_SET_CONFIG, &config);
/* Get I2C device configuration */
mr_dev_ioctl(ds, MR_CTL_I2C_GET_CONFIG, &config);
Note:
- If not manually configured, the default configuration is:
- Baud rate:
100000 - Master/slave mode:
MR_I2C_HOST - Register bits:
MR_I2C_REG_BITS_8
- Baud rate:
- When an I2C device on the I2C bus is configured to slave mode, it will continuously occupy the I2C bus. At this point, other I2C devices cannot perform read/write operations until the I2C device in slave mode is reconfigured to master mode.
Set/Get Register Value
The register value will be written first (range: 0 ~ INT32_MAX) before reading and writing data.
/* Set register value */
mr_dev_ioctl(ds, MR_CTL_I2C_SET_REG, MR_MAKE_LOCAL(int, 0x12));
/* Get register value */
uint8_t reg;
mr_dev_ioctl(ds, MR_CTL_I2C_GET_REG, ®);
Note:
- The register value only takes effect in master mode.
- It is not effective if set to a negative number.
- The register value is not included in the read/write size.
Set/Get Read Buffer Size
size_t size = 256;
/* Set read buffer size */
mr_dev_ioctl(ds, MR_CTL_I2C_SET_RD_BUFSZ, &size);
/* Get read buffer size */
mr_dev_ioctl(ds, MR_CTL_I2C_GET_RD_BUFSZ, &size);
Note: If not manually configured, it will use the size configured in Kconfig (default 32Byte). The read buffer is only used in slave mode.
Clear Read Buffer
mr_dev_ioctl(ds, MR_CTL_I2C_CLR_RD_BUF, MR_NULL);
Get Read Buffer Data Size
size_t size = 0;
/* Get read buffer data size */
mr_dev_ioctl(ds, MR_CTL_I2C_GET_RD_DATASZ, &size);
Set/Get Read Callback Function
/* Define callback function */
int call(int desc, void *args)
{
/* Get buffer data size */
ssize_t data_size = *(ssize_t *)args;
/* Handle interrupt */
return MR_EOK;
}
int (*callback)(int, void *args);
/* Set read callback function */
mr_dev_ioctl(ds, MR_CTL_I2C_SET_RD_CALL, &call);
/* Get read callback function */
mr_dev_ioctl(ds, MR_CTL_I2C_GET_RD_CALL, &callback);
Read I2C Device Data
ssize_t mr_dev_read(int desc, void *buf, size_t size);
| Parameter | Description |
|---|---|
| desc | Device descriptor |
| buf | Read data buffer |
| size | Read data size |
| Return Value | |
>=0 |
Read data size |
<0 |
Error code |
uint8_t buf[128];
/* Read I2C device data */
ssize_t size = mr_dev_read(ds, buf, sizeof(buf));
/* Whether the read succeeded */
if (size < 0)
{
}
Note:
- In host mode, data is read synchronously in polling mode. In slave mode, if the read buffer is not set, the data is read synchronously in polling mode. After the read buffer is set, the specified amount of data is read from the read buffer (the size of the actual read data is returned).
- When the register parameter is not negative, the write operation of the register value is inserted before the read operation.
Write I2C Device Data
ssize_t mr_dev_write(int desc, const void *buf, size_t size);
| Parameter | Description |
|---|---|
| desc | Device descriptor |
| buf | Write data buffer |
| size | Write data size |
| Return Value | |
>=0 |
Write data size |
<0 |
Error code |
uint8_t buf[] = {0x01, 0x02, 0x03, 0x04};
/* Write data to I2C device */
ssize_t size = mr_dev_write(ds, buf, sizeof(buf));
/* Whether write succeeds */
if (size < 0)
{
}
Note: When the register parameter is not negative, a register value write operation will be inserted before the write operation.
Usage Example:
#include "include/mr_lib.h"
/* Define I2C devices */
struct mr_i2c_dev host_dev;
struct mr_i2c_dev slave_dev;
/* Define I2C device descriptors */
int host_ds = -1;
int slave_ds = -1;
int i2c_init(void)
{
int ret = MR_EOK;
/* Register I2C-HOST device */
ret = mr_i2c_dev_register(&host_dev, "i2c1/host", 0x62, MR_I2C_ADDR_BITS_7);
if (ret < 0)
{
mr_printf("host i2c device register failed: %d\r\n", mr_strerror(ret));
return ret;
}
/* Register I2C-SLAVE device */
ret = mr_i2c_dev_register(&slave_dev, "i2c2/slave", 0x62, MR_I2C_ADDR_BITS_7);
if (ret < 0)
{
mr_printf("slave i2c device register failed: %d\r\n", mr_strerror(ret));
return ret;
}
/* Open I2C-HOST device */
host_ds = mr_dev_open("i2c1/host", MR_OFLAG_RDWR);
if (host_ds < 0)
{
mr_printf("host i2c device open failed: %d\r\n", mr_strerror(ret));
return ret;
}
/* Set register value */
mr_dev_ioctl(host_ds, MR_CTL_I2C_SET_REG, MR_MAKE_LOCAL(int, 0x12));
/* Open I2C-SLAVE device */
slave_ds = mr_dev_open("i2c2/slave", MR_OFLAG_RDWR);
if (slave_ds < 0)
{
mr_printf("slave i2c device open failed: %d\r\n", mr_strerror(ret));
return ret;
}
/* Set slave mode */
struct mr_i2c_config config = MR_I2C_CONFIG_DEFAULT;
config.host_slave = MR_I2C_SLAVE;
ret = mr_dev_ioctl(slave_ds, MR_CTL_I2C_SET_CONFIG, &config);
if (ret < 0)
{
mr_printf("slave i2c device set config failed: %d\r\n", mr_strerror(ret));
return ret;
}
return MR_EOK;
}
/* Export to auto init (APP level) */
MR_INIT_APP_EXPORT(i2c_init);
int main(void)
{
/* Auto init (i2c_init function will be called automatically here) */
mr_auto_init();
/* Send test data */
uint8_t wr_buf[] = {0x01, 0x02, 0x03, 0x04};
mr_dev_write(host_ds, wr_buf, sizeof(wr_buf));
/* Receive test data */
uint8_t rd_buf[128];
ssize_t ret = mr_dev_read(slave_ds, rd_buf, sizeof(rd_buf));
/* Compare register value */
if (rd_buf[0] == 0x12)
{
/* Compare data */
if (memcmp(wr_buf, (rd_buf + 1), sizeof(wr_buf)) == 0)
{
mr_printf("i2c test success\r\n");
return 0;
}
}
while (1)
{
}
}
Connect I2C1 and I2C2 and perform sending and receiving test. I2C1 works as master and I2C2 works as slave. I2C2 will compare the received data with the sent data. Since the register value is set, the register value will be received first before the data writing.
Software I2C
Note: Software I2C requires enabling PIN device.
Register Software I2C Bus
int mr_soft_i2c_bus_register(struct mr_soft_i2c_bus *soft_i2c_bus, const char *name, int scl_pin, int sda_pin);
| Parameter | Description |
|---|---|
| soft_i2c_bus | Software I2C bus structure pointer |
| name | Bus name |
| scl_pin | SCL pin number |
| sda_pin | SDA pin number |
| Return Value | |
=0 |
Registration succeeds |
<0 |
Error code |
/* Define SCL, SDA pin numbers for software I2C bus */
#define SCL_PIN_NUMBER 0
#define SDA_PIN_NUMBER 1
/* Define software I2C bus */
struct mr_soft_i2c_bus soft_i2c_bus;
/* Register software I2C bus */
mr_soft_i2c_bus_register(&soft_i2c_bus, "i2c1", SCL_PIN_NUMBER, SDA_PIN_NUMBER);
After registration, the software I2C bus will simulate a hardware I2C.
Note: The software I2C bus only supports master mode.