The IIC (Inter-Integrated Circuit) was proposed by Philips in the 1980's. This interface uses two signal lines to achieve a master-slave communication, one is the bi-directional data line SDA and the other is the clock line SCL. The clock line SCL is connected to the SCL of the bus.
Rockchip I2C controllers support the following features.
The RK3568 supports a maximum of 6 groups of I2C, and the development board leads to two channels, I2C1 and I2C5, located here
The following is an example of how to read and write to I2C by operating an at24c32 under I2C5. 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 of memory. The wiring diagram is as follows
The node "/dev/i2c-*" requires root privileges to perform read/write operations, and root privileges are required to operate i2c using command line or C programs. If you are using ssh or LX terminal, first execute the following command to obtain root privileges.
sudo su
Linux provides i2ctool to manipulate i2c, two of the more useful tools are i2cdetect and i2ctransfer. there are also i2cget and i2cset which are actually simplified versions of i2ctransfer. The system on the board comes with these commands
Detects which devices are under i2c5
i2cdetect -y 5
The at24c32 reads three bytes of data continuously starting from 0x0000. Where w2 represents to write 2 bytes in succession, as the register address is 2 bytes that is 16 bits, 0x50 is its I2C device address, r3 represents to read operation 3 registers in succession
i2ctransfer -f -y 5 w2@0x50 0x00 0x00 r3
Continuously write at24c32 from the beginning of 0x0000 three bytes of data 0x01 0x02 0x03. where w5 represents to write 5 bytes continuously, because 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 5 w5@0x50 0x00 0x00 0x01 0x02 0x03
The result of the operation is as follows
By connecting to the libperipheral_api.a static library, the following interfaces can be called in C to operate the I2C
/**
* @name: user_i2c_open
* @description: open i2c device
* @param i2c_num: i2c number, the i2c induced on the board includes 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 i2c device
* @param fd: file descriptor, user_i2c_open return value
* @param slave_addr: i2c device address
* @param reg_addr: pointer to the register address
* @param addr_len: length of the register address
* @param buf: pointer to read in data
* @param len: length of read data
*
* @return 0 - success ; less than 0 - fail
*/
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 i2c device
* @param fd: file descriptor, user_i2c_open return value
* @param slave_addr: i2c device address
* @param reg_addr: pointer to the register address
* @param addr_len: length of the register address
* @param buf: pointer to write data
* @param len: length of write data
*
* @return 0 - success ; less than 0 - fail
*/
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, user_i2c_open return value
* @return 0 - success ; less than 0 - fail
*/
int user_i2c_close(int fd);
The test demo is as follows, taking the AT24C32 hooked up to I2C5 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(5);
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;
}
The result of the operation is as follows
root@linaro-alip:/home/linaro# ./test
buf_write buf_read same