RK3568平台(平台总线篇)IIC应用编程

一.I2C 硬件框架

IIC就是master/slave模式,通过数据线和时钟线两根线实现主从设备通信,其传输熟虑标准模式下可达100kbit/s,快速模式下可达400kbit/s,高速模式下可达3.4Mbit/s。其主要由两根线组成是SDA、SCL、上拉电阻组成。通信原理是通过对SCL和SDA线高低电平时序的控制,在总线空闲状态时,这两根线一般被上面所接的上拉电阻拉高,保持着高电平。

  • VCC:提供电源
  • GND:接地
  • SDA:串联数据线,传输数据
  • SCL:串联时钟线,起控制作用

二.I2C读写示例

ioctl函数的使用:

原型:struct ioctl(struct file *file,unsigned int cmd,unsigned long arg);

cmd有I2C_SLAVE,I2C_SLAVE_FORCE,I2C_TENBIT,I2C_SET_SPEED几个选项;

I2C_SLAVE:对应的arg取值为I2C从机地址,用来设定I2C从机地址;

I2C_SLAVE_FORCE:对应的arg取值为I2C从机地址,用来修改I2C从机地址;

I2C_TENBIT:对应的arg取值为0:从机地址为7 bit;对应的arg取值为1:从机地址为10bit。用来指定I2C从机地址的位数;

I2C_SET_SPEED:对应的arg取值为I2C总线控制器分频值。用来设置I2C总线控制器时钟频率;

读写示例:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include "Log.h"

#include "i2c.h"
static int cam_fd[FD_NUMBER];
static int bus_cnt[FD_NUMBER];
pthread_mutex_t mutex[FD_NUMBER];

int i2c_init(int bus)
{
	int ret = 0;
	char str[12] = {0};

	if (bus < 0 || bus >= FD_NUMBER)
	{
		pr_err("Invalid bus num %d", bus);
		return -1;
	}
	if (cam_fd[bus] <= 0)
	{
		snprintf(str, sizeof(str), "/dev/i2c-%d", bus);
		cam_fd[bus] = open(str, O_RDWR);
		if (cam_fd[bus] < 0)
		{
			pr_err("open i2c-%d fail\n", bus);
			return -1;
		}
		if (pthread_mutex_init(&mutex[bus], NULL) != 0)
		{
			pr_err("Init metux error.");
			close(cam_fd[bus]);
			cam_fd[bus] = -1;
			return -1;
		}
	}
	bus_cnt[bus]++;
	pr_info("bus %d bus_cnt[bus] %d cam_fd[bus] %d\n",
			bus, bus_cnt[bus], cam_fd[bus]);
	return ret;
}

int i2c_deinit(int bus)
{
	int ret = 0;

	if (bus < 0 || bus >= FD_NUMBER)
	{
		pr_err("Invalid bus num %d", bus);
		return -1;
	}
	bus_cnt[bus]--;
	if (bus_cnt[bus] == 0 && cam_fd[bus] > 0)
	{
		close(cam_fd[bus]);
		cam_fd[bus] = -1;
		pthread_mutex_destroy(&mutex[bus]);
	}

	pr_info("bus %d bus_cnt[bus] %d cam_fd[bus] %d\n",
			bus, bus_cnt[bus], cam_fd[bus]);
	return ret;
}

int i2c_read_reg16_data16(int bus, uint8_t i2c_addr, uint16_t reg_addr)
{
	int ret = 0, value = 0;
	unsigned char wr_data[2];
	unsigned char rdata[2] = {0};
	int val = 0;

	wr_data[0] = (reg_addr >> 8) & 0x00ff;
	wr_data[1] = reg_addr & 0x00ff;

	val = pthread_mutex_lock(&mutex[bus]);
	if (val != 0)
	{
		pr_err("mutex lock error val %d \n", val);
		return -1;
	}
	ret = ioctl(cam_fd[bus], I2C_SLAVE_FORCE, i2c_addr);
	if (ret < 0)
	{
		pr_err("unable open camera with addr 0x%02x ioctl I2C_SLAVE_FORCE error\n", i2c_addr);
		pthread_mutex_unlock(&mutex[bus]);
		return -1;
	}
	ret = write(cam_fd[bus], wr_data, 2);
	if (ret != 2)
	{
		pr_err("write reg16_data16 fail\n");
		pthread_mutex_unlock(&mutex[bus]);
		return -1;
	}
	ret = read(cam_fd[bus], &rdata, 2);
	if (ret != 2)
	{
		pr_err("read reg16_data16 fail\n");
		pthread_mutex_unlock(&mutex[bus]);
		return -1;
	}
	value = (rdata[0] << 8) | rdata[1];
	pr_info("success with value 0x%04x \n", value);
	pthread_mutex_unlock(&mutex[bus]);
	return value;
}

int i2c_read_reg16_data8(int bus, uint8_t i2c_addr, uint16_t reg_addr)
{
	int ret = 0, value = 0;
	unsigned char wr_data[2];
	unsigned char rdata = 0;
	int val = 0;

	wr_data[0] = (reg_addr >> 8) & 0x00ff;
	wr_data[1] = reg_addr & 0x00ff;

	val = pthread_mutex_lock(&mutex[bus]);
	if (val != 0)
	{
		pr_err("mutex lock error val %d \n", val);
		return -1;
	}
	ret = ioctl(cam_fd[bus], I2C_SLAVE_FORCE, i2c_addr);
	if (ret < 0)
	{
		pr_err("unable open camera with addr 0x%02x ioctl I2C_SLAVE_FORCE error\n", i2c_addr);
		pthread_mutex_unlock(&mutex[bus]);
		return -1;
	}
	ret = write(cam_fd[bus], wr_data, 2);
	if (ret != 2)
	{
		pr_err("write reg16_data8 fail\n");
		pthread_mutex_unlock(&mutex[bus]);
		return -1;
	}
	ret = read(cam_fd[bus], &rdata, 1);
	if (ret != 1)
	{
		pr_err("read reg16_data8 fail\n");
		pthread_mutex_unlock(&mutex[bus]);
		return -1;
	}
	value = rdata;
	pthread_mutex_unlock(&mutex[bus]);
	return value;
}

int i2c_read_reg8_data8(int bus, uint8_t i2c_addr, uint16_t reg_addr)
{
	int ret = 0, value = 0;
	unsigned char wr_data;
	unsigned char rdata = 0;
	int val = 0;

	wr_data = reg_addr;
	val = pthread_mutex_lock(&mutex[bus]);
	if (val != 0)
	{
		pr_err("mutex lock error val %d \n", val);
		return -1;
	}
	ret = ioctl(cam_fd[bus], I2C_SLAVE_FORCE, i2c_addr);
	if (ret < 0)
	{
		pr_err("unable open camera with addr 0x%02x ioctl I2C_SLAVE_FORCE error\n", i2c_addr);
		pthread_mutex_unlock(&mutex[bus]);
		return -1;
	}
	ret = write(cam_fd[bus], &wr_data, 1);
	if (ret != 1)
	{
		pr_err("write reg8_data8 fail\n");
		pthread_mutex_unlock(&mutex[bus]);
		return -1;
	}
	ret = read(cam_fd[bus], &rdata, 1);
	if (ret != 1)
	{
		pr_err("read reg8_data8 fail\n");
		pthread_mutex_unlock(&mutex[bus]);
		return -1;
	}
	value = rdata;
	pthread_mutex_unlock(&mutex[bus]);
	return value;
}

int i2c_read_reg8_data16(int bus, uint8_t i2c_addr, uint16_t reg_addr)
{
	int ret = 0, value = 0;
	unsigned char wr_data;
	unsigned char rdata[2] = {0};
	int val = 0;

	wr_data = reg_addr;
	val = pthread_mutex_lock(&mutex[bus]);
	if (val != 0)
	{
		pr_err("mutex lock error val %d \n", val);
		return -1;
	}
	ret = ioctl(cam_fd[bus], I2C_SLAVE_FORCE, i2c_addr);
	if (ret < 0)
	{
		pr_err("unable open camera with addr 0x%02x ioctl I2C_SLAVE_FORCE error\n", i2c_addr);
		pthread_mutex_unlock(&mutex[bus]);
		return -1;
	}
	ret = write(cam_fd[bus], &wr_data, 1);
	if (ret != 1)
	{
		pr_err("write reg8_data16 fail\n");
		pthread_mutex_unlock(&mutex[bus]);
		return -1;
	}
	ret = read(cam_fd[bus], &rdata, 2);
	if (ret != 2)
	{
		pr_err("read reg8_data16 fail\n");
		pthread_mutex_unlock(&mutex[bus]);
		return -1;
	}
	value = (rdata[0] << 8) | rdata[1];
	pthread_mutex_unlock(&mutex[bus]);
	return value;
}

int i2c_write_reg16_data16(int bus, uint8_t i2c_addr,
						   uint16_t reg_addr, uint16_t value)
{
	int ret = 0;
	unsigned char wr_data[4];
	int val = 0;

	val = pthread_mutex_lock(&mutex[bus]);
	if (val != 0)
	{
		pr_err("mutex lock error val %d \n", val);
		return -1;
	}
	ret = ioctl(cam_fd[bus], I2C_SLAVE_FORCE, i2c_addr);
	if (ret < 0)
	{
		pr_err("unable open camera with addr 0x%02x ioctl I2C_SLAVE_FORCE error\n", i2c_addr);
		pthread_mutex_unlock(&mutex[bus]);
		return -1;
	}
	wr_data[0] = (reg_addr >> 8) & 0x00ff;
	wr_data[1] = reg_addr & 0x00ff;
	wr_data[2] = (value >> 8) & 0x00ff;
	wr_data[3] = (value)&0x00ff;

	// pr_debug("0x%x camera reg(0x%04x) with value 0x%02x\n", i2c_addr , reg_addr, wr_data[2]);
	ret = write(cam_fd[bus], wr_data, 4);
	if (ret != 4)
	{
		// pr_err("write_reg16_data16 fail\n");
		pthread_mutex_unlock(&mutex[bus]);
		return -1;
	}
	pthread_mutex_unlock(&mutex[bus]);
	return 0;
}

int i2c_write_reg16_data8(int bus, uint8_t i2c_addr,
						  uint16_t reg_addr, uint8_t value)
{
	int ret = 0;
	unsigned char wr_data[3];
	int val = 0;

	val = pthread_mutex_lock(&mutex[bus]);
	if (val != 0)
	{
		pr_err("mutex lock error val %d \n", val);
		return -1;
	}
	ret = ioctl(cam_fd[bus], I2C_SLAVE_FORCE, i2c_addr);
	if (ret < 0)
	{
		printf("unable open camera with addr 0x%02x ioctl I2C_SLAVE_FORCE error\n", i2c_addr);
		pthread_mutex_unlock(&mutex[bus]);
		return -1;
	}
	wr_data[0] = (reg_addr >> 8) & 0x00ff;
	wr_data[1] = reg_addr & 0x00ff;
	wr_data[2] = value;

	// pr_debug("camera reg(0x%04x) with value 0x%02x ", reg_addr, wr_data[2]);
	ret = write(cam_fd[bus], wr_data, 3);
	if (ret != 3)
	{
		// pr_err("write_reg16_data8 fail\n");
		pthread_mutex_unlock(&mutex[bus]);
		return -1;
	}
	pthread_mutex_unlock(&mutex[bus]);
	return 0;
}

int i2c_write_reg8_data16(int bus, uint8_t i2c_addr,
						  uint16_t reg_addr, uint16_t value)
{
	int ret = 0;
	unsigned char wr_data[3];
	int val = 0;

	val = pthread_mutex_lock(&mutex[bus]);
	if (val != 0)
	{
		pr_err("mutex lock error val %d \n", val);
		return -1;
	}
	ret = ioctl(cam_fd[bus], I2C_SLAVE_FORCE, i2c_addr);
	if (ret < 0)
	{
		pr_err("unable open camera with addr 0x%02x ioctl I2C_SLAVE_FORCE error\n", i2c_addr);
		pthread_mutex_unlock(&mutex[bus]);
		return -1;
	}
	wr_data[0] = reg_addr;
	wr_data[1] = (value >> 8) & 0x00ff;
	wr_data[2] = (value)&0x00ff;

	ret = write(cam_fd[bus], wr_data, 3);
	if (ret != 3)
	{
		// pr_err("write_reg8_data16 fail\n");
		pthread_mutex_unlock(&mutex[bus]);
		return -1;
	}
	pthread_mutex_unlock(&mutex[bus]);
	return 0;
}

int i2c_write_reg8_data8(int bus, uint8_t i2c_addr,
						 uint16_t reg_addr, uint8_t value)
{
	int ret = 0;
	unsigned char wr_data[2];
	int val = 0;

	val = pthread_mutex_lock(&mutex[bus]);
	if (val != 0)
	{
		pr_err("mutex lock error val %d \n", val);
		return -1;
	}

	ret = ioctl(cam_fd[bus], I2C_SLAVE_FORCE, i2c_addr);
	if (ret < 0)
	{
		pr_err("unable open camera with addr 0x%02x ioctl I2C_SLAVE_FORCE error\n", i2c_addr);
		pthread_mutex_unlock(&mutex[bus]);
		return -1;
	}
	wr_data[0] = reg_addr;
	wr_data[1] = value;

	// pr_debug("bus %d i2c_addr 0x%x reg_addr 0x%x value 0x%x\n", bus,
	// i2c_addr, reg_addr, value);
	ret = write(cam_fd[bus], wr_data, 2);
	if (ret != 2)
	{
		// pr_err("write_reg8_data8 fail ret %d 0x%x 0x%x\n", ret, reg_addr, value);
		pthread_mutex_unlock(&mutex[bus]);
		return -1;
	}
	pthread_mutex_unlock(&mutex[bus]);
	return 0;
}

int i2c_write_block(int bus, uint8_t i2c_addr,
					uint16_t reg_addr, uint32_t value, uint8_t cnt)
{
	int ret = 0;
	struct i2c_rdwr_ioctl_data data;
	unsigned char sendbuf[12] = {0};
	unsigned char *ptr;
	int val = 0;

	val = pthread_mutex_lock(&mutex[bus]);
	if (val != 0)
	{
		pr_err("mutex lock error val %d \n", val);
		return -1;
	}
	if (cnt > 4)
		cnt = 4;

	data.msgs = (struct i2c_msg *)calloc(4, sizeof(struct i2c_msg));

	data.nmsgs = cnt;

	ptr = sendbuf;
	data.msgs[0].len = 3;
	data.msgs[0].addr = i2c_addr;
	data.msgs[0].flags = 0;
	data.msgs[0].buf = ptr;
	data.msgs[0].buf[0] = (reg_addr >> 8) & 0xff;
	data.msgs[0].buf[1] = reg_addr & 0xff;
	data.msgs[0].buf[2] = value & 0xff;
	/*
	printf("msg0: buf[0] %x, buf[1] %x, buf[2] %x\n",
	data.msgs[0].buf[0], data.msgs[0].buf[1], data.msgs[0].buf[2]);
	*/

	ptr = sendbuf + 3;
	data.msgs[1].len = 3;
	data.msgs[1].addr = i2c_addr;
	data.msgs[1].flags = 0;
	data.msgs[1].buf = ptr;
	data.msgs[1].buf[0] = ((reg_addr + 1) >> 8) & 0xff;
	data.msgs[1].buf[1] = (reg_addr + 1) & 0xff;
	data.msgs[1].buf[2] = (value >> 8) & 0xff;

	ptr = sendbuf + 6;
	data.msgs[2].len = 3;
	data.msgs[2].addr = i2c_addr;
	data.msgs[2].flags = 0;
	data.msgs[2].buf = ptr;
	data.msgs[2].buf[0] = ((reg_addr + 2) >> 8) & 0xff;
	data.msgs[2].buf[1] = (reg_addr + 2) & 0xff;
	data.msgs[2].buf[2] = (value >> 16) & 0xff;

	ptr = sendbuf + 9;
	data.msgs[3].len = 3;
	data.msgs[3].addr = i2c_addr;
	data.msgs[3].flags = 0;
	data.msgs[3].buf = ptr;
	data.msgs[3].buf[0] = ((reg_addr + 3) >> 8) & 0xff;
	data.msgs[3].buf[1] = (reg_addr + 3) & 0xff;
	data.msgs[3].buf[2] = (value >> 24) & 0xff;

	ret = ioctl(cam_fd[bus], I2C_RDWR, (unsigned long)&data);
	if (ret < 0)
		pr_err("%s failed\n", __func__);
	free(data.msgs);
	pthread_mutex_unlock(&mutex[bus]);
	return 0;
}

int i2c_read_block_reg16(int bus, uint8_t i2c_addr,
						 uint16_t reg_addr, char *buf, uint32_t count)
{
	int ret = 0;
	struct i2c_rdwr_ioctl_data data;
	unsigned char sendbuf[12] = {0};
	int val = 0;

	// pr_info("read_block_reg16 reg_addr 0x%x  count %d\n", reg_addr, count);
	val = pthread_mutex_lock(&mutex[bus]);
	if (val != 0)
	{
		pr_err("mutex lock error val %d \n", val);
		return -1;
	}
	data.msgs = (struct i2c_msg *)calloc(2, sizeof(struct i2c_msg));
	data.nmsgs = 2;

	data.msgs[0].len = 2;
	data.msgs[0].addr = i2c_addr;
	data.msgs[0].flags = 0;
	data.msgs[0].buf = sendbuf;
	data.msgs[0].buf[0] = (reg_addr >> 8) & 0xff;
	data.msgs[0].buf[1] = reg_addr & 0xff;

	data.msgs[1].len = count;
	data.msgs[1].addr = i2c_addr;
	data.msgs[1].flags = 1;
	data.msgs[1].buf = buf;

	ret = ioctl(cam_fd[bus], I2C_RDWR, (unsigned long)&data);
	if (ret < 0)
		pr_err("%s failed\n", __func__);
	free(data.msgs);
	pthread_mutex_unlock(&mutex[bus]);
	return 0;
}

int i2c_read_block_reg8(int bus, uint8_t i2c_addr,
						uint16_t reg_addr, char *buf, uint32_t count)
{
	int ret = 0;
	struct i2c_rdwr_ioctl_data data;
	unsigned char sendbuf[12] = {0};
	int val = 0;

	val = pthread_mutex_lock(&mutex[bus]);
	if (val != 0)
	{
		pr_err("mutex lock error val %d \n", val);
		return -1;
	}
	data.msgs = (struct i2c_msg *)calloc(2, sizeof(struct i2c_msg));
	data.nmsgs = 2;

	data.msgs[0].len = 2;
	data.msgs[0].addr = i2c_addr;
	data.msgs[0].flags = 0;
	data.msgs[0].buf = sendbuf;
	data.msgs[0].buf[0] = reg_addr & 0xff;

	data.msgs[1].len = count;
	data.msgs[1].addr = i2c_addr;
	data.msgs[1].flags = 1;
	data.msgs[1].buf = buf;

	ret = ioctl(cam_fd[bus], I2C_RDWR, (unsigned long)&data);
	if (ret < 0)
		pr_err("%s failed\n", __func__);
	free(data.msgs);
	pthread_mutex_unlock(&mutex[bus]);
	return 0;
}
int i2c_write_block_reg16(int bus, uint8_t i2c_addr,
						  uint16_t reg_addr, char *buf, uint32_t count)
{
	int ret = 0;
	struct i2c_rdwr_ioctl_data data;
	char *sendbuf = NULL;
	int val = 0;

	// pr_info("write_block_reg16 reg_addr 0x%x  count %d\n", reg_addr, count);
	val = pthread_mutex_lock(&mutex[bus]);
	if (val != 0)
	{
		pr_err("mutex lock error val %d \n", val);
		return -1;
	}
	sendbuf = malloc(count + 2);
	if (sendbuf == NULL)
	{
		pr_err("malloc error\n");
		return -1;
	}
	data.msgs = (struct i2c_msg *)calloc(1, sizeof(struct i2c_msg));
	data.nmsgs = 1;

	data.msgs[0].len = 2 + count;
	data.msgs[0].addr = i2c_addr;
	data.msgs[0].flags = 0;
	data.msgs[0].buf = sendbuf;
	sendbuf[0] = (reg_addr >> 8) & 0xff;
	sendbuf[1] = reg_addr & 0xff;
	memcpy(sendbuf + 2, buf, count);

	ret = ioctl(cam_fd[bus], I2C_RDWR, (unsigned long)&data);
	if (ret < 0)
		pr_err("%s failed\n", __func__);
	free(data.msgs);
	free(sendbuf);
	pthread_mutex_unlock(&mutex[bus]);
	return 0;
}

int i2c_write_block_reg8(int bus, uint8_t i2c_addr,
						 uint16_t reg_addr, char *buf, uint32_t count)
{
	int ret = 0;
	struct i2c_rdwr_ioctl_data data;
	unsigned char sendbuf[12] = {0};
	int val = 0;

	val = pthread_mutex_lock(&mutex[bus]);
	if (val != 0)
	{
		pr_err("mutex lock error val %d \n", val);
		return -1;
	}
	data.msgs = (struct i2c_msg *)calloc(2, sizeof(struct i2c_msg));
	data.nmsgs = 2;

	data.msgs[0].len = 2;
	data.msgs[0].addr = i2c_addr;
	data.msgs[0].flags = 0;
	data.msgs[0].buf = sendbuf;
	data.msgs[0].buf[0] = reg_addr & 0xff;

	data.msgs[1].len = count;
	data.msgs[1].addr = i2c_addr;
	data.msgs[1].flags = 0;
	data.msgs[1].buf = buf;

	ret = ioctl(cam_fd[bus], I2C_RDWR, (unsigned long)&data);
	if (ret < 0)
		pr_err("%s failed\n", __func__);

	free(data.msgs);
	pthread_mutex_unlock(&mutex[bus]);
	return 0;
}

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式_笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值