有三种方式实现linux i2c用户态编程,读写i2c外设。

 

1. ioctl

ioctl(file, I2C_RDWR, struct i2c_rdwr_ioctl_data *msgset)

 

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>


#define CHIP   "/dev/i2c-0"
#define I2C_DEVICE_ADDR   0x56	//eeprom addr



static int iic_write(int i2c_fd, int device_addr, unsigned int reg_address ,unsigned int reg_val)
{
	struct i2c_rdwr_ioctl_data work_queue;
	int ret = 0;

	work_queue.nmsgs = 1;
	work_queue.msgs = (struct i2c_msg *)malloc(work_queue.nmsgs * sizeof(struct i2c_msg));
	if(!work_queue.msgs)
	{
		printf("msgs memery alloc error\n");
		close(i2c_fd);
		return -1;
	} 
	if ((work_queue.msgs[0].buf = (unsigned char *)malloc(2 * sizeof(unsigned char))) == NULL)
	{
		printf("buf memery alloc error...\n");
		close(i2c_fd);
		return -1;
	}

	(work_queue.msgs[0]).len = 2;
	(work_queue.msgs[0]).flags = !I2C_M_RD;
	(work_queue.msgs[0]).addr = device_addr;
	(work_queue.msgs[0]).buf[0] = reg_address;
	(work_queue.msgs[0]).buf[1] = reg_val;

	work_queue.nmsgs = 1;

	ret = ioctl(i2c_fd, I2C_RDWR, (unsigned long) &work_queue);
	if(ret < 0)
	{
		printf("Error during I2C_RDWR ioctl with error code: %d\n", ret);
		return -1;
	}
	
	free(work_queue.msgs[0].buf);
	free(work_queue.msgs);
	
	return 0;
}
 
 
static int iic_read(int i2c_fd, int device_addr, unsigned int reg_address)
{
	struct i2c_rdwr_ioctl_data work_queue;
	unsigned char val;
	int ret;

	work_queue.nmsgs = 2;
	work_queue.msgs = (struct i2c_msg *)malloc(work_queue.nmsgs *sizeof(struct i2c_msg));

	if(!work_queue.msgs)
	{
		printf("Memery alloc error\n");
		close(i2c_fd);
		return -1;
	}

	val =(unsigned char)reg_address;

	(work_queue.msgs[0]).len = 1;
	(work_queue.msgs[0]).flags = 0;
	(work_queue.msgs[0]).addr = device_addr;
	(work_queue.msgs[0]).buf = &val;

	(work_queue.msgs[1]).len = 1;
	(work_queue.msgs[1]).flags = 1;
	(work_queue.msgs[1]).addr = device_addr;
	(work_queue.msgs[1]).buf = &val;

	ret = ioctl(i2c_fd, I2C_RDWR, (unsigned long) &work_queue);
	if(ret < 0)
	{
		printf("Error during I2C_RDWR ioctl with error code: %d\n", ret);
		return -1;
	}

	free(work_queue.msgs);

	return val;
}


int main()
{
	printf("hello, this is i2c test\n");
	int ret = 0;

	int fd = open(CHIP, O_RDWR);

	if (fd< 0) {
	   printf("open %s failed\n", CHIP);
	   goto exit;
	}

	if (ioctl(fd, I2C_SLAVE, I2C_DEVICE_ADDR) < 0) { //device addr
	   printf("ioictl: set slave address failed\n");
	   goto close;
	}


	ret = iic_write(fd, I2C_DEVICE_ADDR, 0, 0xaa);
	if(ret)
		printf("write failed\n");
	
	usleep(1000 * 1000 * 0.1);
	
	ret = iic_write(fd, I2C_DEVICE_ADDR, 1, 0xbb);
	if(ret)
		printf("write failed\n");
	
	usleep(1000 * 1000 * 0.1);
	
	ret = iic_read(fd, I2C_DEVICE_ADDR, 0);
	printf("read reg addr:0 data:%x\n", ret);
	ret = iic_read(fd, I2C_DEVICE_ADDR, 1);
	printf("read reg addr:1 data:%x\n", ret);	
	
	close:
	close(fd);

	exit:
	return 0;
}

 

2. write and read

 

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>


#define CHIP   "/dev/i2c-0"
#define I2C_DEVICE_ADDR   0x56	//eeprom addr


int main(int argc, char* argv[])
{
	unsigned char      rddata;
	unsigned char      rdaddr = 0;     /* 将要读取的数据在芯片中的偏移量*/
	unsigned char      wrbuf[2] = {0, 0xaa};      /*要写的数据,第1个字节为偏移量, 第二个字节为写入的数据*/	

	printf("hello,this is i2c test\n");

	int fd =open(CHIP, O_RDWR);

	if (fd< 0) {
	   printf("open %s failed\n", CHIP);
	   goto exit;
	}

	if (ioctl(fd, I2C_SLAVE, I2C_DEVICE_ADDR) < 0) {
	   printf("ioictl:setslave address failed\n");
	   goto close;
	}


	if(argc == 3){
		// write and read reg addr
		wrbuf[0] = atoi(argv[1]);
		rdaddr = wrbuf[0];
		
		// write data, one byte
		wrbuf[1] = atoi(argv[2]);
	}
	
	printf("write addr:0x%x, data:0x%x\n", wrbuf[0], wrbuf[1]);
	write(fd, wrbuf, 2);
	usleep(1000 * 1000 * 0.2);

	write(fd, &rdaddr, 1);      /*读取之前首先设置读取的偏移量*/	
	usleep(1000 * 1000 * 0.2);
	read(fd, &rddata, 1);
	printf("read addr:0x%x, value:0x%x \n", rdaddr, rddata);	
	
	close:
	close(fd);
	exit:
	return 0;
}

 

3. libi2c.so library, i2c_smbus_xxx

https://git.kernel.org/pub/scm/utils/i2c-tools/i2c-tools.git/.

  __s32 i2c_smbus_read_byte(int file);

  __s32 i2c_smbus_write_byte(int file, __u8 value);

......

 

更多推荐