IIC (Inter-Integrated Circuit) was introduced by Philips in the 1980's. This interface uses two signal lines to realize a master-multiple-slave communication, one is the bi-directional data line SDA, and the other is the clock line SCL. the serial data SDA of all the devices connected to the I2C bus is connected to SDA of the bus, and the clock line SCL of the devices is connected to SCL of the bus. The clock line SCL is connected to the SCL of the bus.
The Rockchip I2C controller supports the following features.
The following is an example of how to read and write I2C data to and from an at24c32 under I2C3. at24c32 is a 32kbit EEPROM, the I2C address of this device is 0x50, and the registers are 16 bits long. Each register is a byte storage unit. The wiring diagram is as follows
The node "/dev/i2c-*" requires root privileges to read and write operations, and you need root privileges to operate i2c using the command line or a program compiled in C. If you are using ssh or LX terminal, first execute the following command to get root privileges. If you are using ssh or LX terminal, execute the following command to get root privileges.
sudo su
Linux provides i2ctool to operate i2c, two of the more useful tools are i2cdetect and i2ctransfer. i2cget and i2cset are actually simplified versions of i2ctransfer. The system on the board comes with these commands
Detect what devices are under i2c3
i2cdetect -y 3
The result of this operation is shown below
Continuously write at24c32 from 0x0000 beginning three bytes of data 0x03 0x04 0x05. where w5 represents to continuously write 5 bytes, due to the register address is 2 bytes that is 16 bits, and then there are three bytes of data, 0x50 is its I2C device address
i2ctransfer -f -y 3 w5@0x50 0x00 0x00 0x03 0x04 0x05
Continuously read at24c32 from 0x0000 beginning of three bytes of data. Where w2 represents to write 2 bytes consecutively, because the register address is 2 bytes that is 16 bits, 0x50 is its I2C device address, r3 represents to read and operate 3 registers consecutively
i2ctransfer -f -y 5 w2@0x50 0x00 0x00 r3
The result of the operation is shown below
By connecting to the libperipheral_api.a static library, you can use C to call the following interfaces to operate I2C
/**
* @name: user_i2c_open
* @description: Open the i2c device.
* @param i2c_num: i2c number, i2c pinned out on board including 1 5
* @return greater than or equal to 0 - success, return value is file descriptor less than 0 - failure
*/
int user_i2c_open(int i2c_num);
/**
* @name: user_i2c_read
* @description: Read data from an i2c device.
* @param fd: file descriptor, user_i2c_open return value
* @param slave_addr: i2c device address
* @param reg_addr: pointer to register address
* @param addr_len: length of register address
* @param buf: Pointer to the data to be read in.
* @param len: Length of the read data.
* @return equal to 0 - success less than 0 - failure
*/
int user_i2c_read(int fd, unsigned short slave_addr, unsigned char *reg_addr, unsigned char addr_len, unsigned char *buf, unsigned short len);
/**
* @name: user_i2c_read
* @description: Read data from an i2c device.
* @param fd: file descriptor, user_i2c_open return value
* @param slave_addr: i2c device address
* @param reg_addr: pointer to register address
* @param addr_len: length of register address
* @param buf: Pointer to write data to.
* @param len: length of the data to be written
* @return equal to 0 - success less than 0 - failure
*/
int user_i2c_write(int fd, unsigned short slave_addr, unsigned char *reg_addr, unsigned char addr_len, unsigned char *buf, unsigned short len);
/**
* @name: user_i2c_close
* @description: Close i2c.
* @param fd: file descriptor, return value of user_i2c_open.
* @return Always equal to 0, meaningless.
*/
int user_i2c_close(int fd).
The test demo is as follows, taking the AT24C32 hanging under I2C3 as an example
#include "peripheral_api.h"
void i2c_api_test(void)
{
int fd = -1;
int ret = 0;
unsigned char reg[2] = {0x00, 0x00};
unsigned char buf_write[5] = {0x01, 0x02, 0x03, 0x04, 0x05};
unsigned char buf_read[5] = {0};
fd = user_i2c_open(3);
if (fd < 0) {
printf("user_i2c_open fail\n");
return;
}
ret = user_i2c_write(fd, 0x50, reg, 2, buf_write, 5);
if (ret < 0) {
printf("user_i2c_write fail\n");
user_i2c_close(fd);
return;
}
usleep(100 * 1000);
ret = user_i2c_read(fd, 0x50, reg, 2, buf_read, 5);
if (ret < 0) {
printf("user_i2c_read fail\n");
user_i2c_close(fd);
return;
}
user_i2c_close(fd);
if (memcmp(buf_write, buf_read, 5) == 0) {
printf("buf_write buf_read same\n");
} else {
printf("buf_write buf_read diff %d %d %d %d %d\n", buf_read[0], buf_read[1], buf_read[2], buf_read[3], buf_read[4]);
}
return;
}
int main()
{
i2c_api_test();
return 0;
}
Put the peripheral_api.a static library, peripheral_api.h and the test demo source code test.c into the same path, compile the command as follows
aarch64-none-linux-gnu-gcc test.c peripheral_api.a -I. -o i2ctest
The result is as follows
root@linaro-alip:/home/linaro# ./i2ctest
buf_write buf_read same