RK3288 基于Androidstdio JNI实现 IIC 通信

RK3288实现JNI对接上层Java和下层的C++。那么我们就要搭建JNI环境,请参考:

https://blog.csdn.net/shao15232/article/details/102501415

这一节我们主要讲JNI如何实现Android stdio实现IIC与从机通信。

 

首先在JNI中添加iic源文件。如下图:

RK3288 基于Androidstdio JNI实现 IIC 通信_第1张图片

这里我们添加了编译so库要使用的源文件,就需要设置一下Android.mk

RK3288 基于Androidstdio JNI实现 IIC 通信_第2张图片

然后就是bsp_iic.cpp源码的实现。(注这里是我们用来读取T613作为Slave address)

bsp_iic.cpp源码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include   //这个头文件只有在ndk-16里面有,之前用的ndk-12找不到这个头文件

#define SINGLE_RW_2B_ADDR    0x30
#define MODIFY_BNAK_ADDR     0x31

/**
 *
 * @param u8BusIndex
 * @return
 */
int I2C_open(unsigned char u8BusIndex)
{
	char szDev[16] = {0};
	sprintf(szDev, "/dev/i2c-%d", u8BusIndex);
	return open(szDev, O_RDWR);
}

/**
 *
 * @param dev_fh
 * @return
 */
int I2C_close(int dev_fh)
{
	return close(dev_fh);
}


/**
 *
 * @param u8BusIndex
 * @param u16BankIndex
 * @return
 */

int I2C_modify_bank_index(unsigned char u8BusIndex, int u16BankIndex)
{
	struct i2c_rdwr_ioctl_data i2c_data;
	unsigned char reg_buf[3] = {0};
	int dev_fh = I2C_open(u8BusIndex);
	if (dev_fh < 0) return dev_fh;

	ioctl(dev_fh, I2C_TIMEOUT, 1);
	ioctl(dev_fh, I2C_RETRIES, 2);

	i2c_data.nmsgs = 1;
	i2c_data.msgs=(struct i2c_msg*)malloc(i2c_data.nmsgs*sizeof(struct i2c_msg));

	if (!i2c_data.msgs)
	{
		close(dev_fh);
		return -2;
	}

	reg_buf[0] = (u16BankIndex >> 8) & 0xFF;
	reg_buf[1] = (u16BankIndex     ) & 0xFF;

	(i2c_data.msgs[0]).len = 3;
	(i2c_data.msgs[0]).addr = MODIFY_BNAK_ADDR;
	(i2c_data.msgs[0]).flags = 0; //write
	(i2c_data.msgs[0]).buf = reg_buf;

	int ret = ioctl(dev_fh, I2C_RDWR, (unsigned long)&i2c_data);
	if (ret < 0)
	{
		close(dev_fh);
		free(i2c_data.msgs);
		return -3;
	}
	else
	{
		close(dev_fh);
		free(i2c_data.msgs);
		return 0;
	}
}


/**
 *
 * @param u8BusIndex
 * @param u32Register
 * @param pData
 * @return
 */
int I2C_read_single(unsigned char u8BusIndex, int u32Register, unsigned char* pData)
{
	int nRet;
	//BanKIndex
	int u16BankIndex = (u32Register >> 16) & 0xFFFF;
	nRet = I2C_modify_bank_index(u8BusIndex, u16BankIndex);
	if(nRet < 0) return nRet;
	//
	struct i2c_rdwr_ioctl_data i2c_data;
	unsigned char reg_buf[2] = {0}, read_buf[2]={0};
	int dev_fh = I2C_open(u8BusIndex);
	if (dev_fh < 0)
	{
		return dev_fh;
	}

	ioctl(dev_fh, I2C_TIMEOUT, 1);
	ioctl(dev_fh, I2C_RETRIES, 2);

	i2c_data.nmsgs = 2;
	i2c_data.msgs = (struct i2c_msg*)malloc(i2c_data.nmsgs * sizeof(struct i2c_msg));
	if (!i2c_data.msgs)
	{
		close(dev_fh);
		return -2;
	}

	reg_buf[0] = (u32Register >> 8) & 0xFF;
	reg_buf[1] = (u32Register     ) & 0xFF;

	(i2c_data.msgs[0]).len = 2;
	(i2c_data.msgs[0]).addr = SINGLE_RW_2B_ADDR ;
	(i2c_data.msgs[0]).flags = 0; //write
	(i2c_data.msgs[0]).buf = reg_buf;

	(i2c_data.msgs[1]).len = 1;
	(i2c_data.msgs[1]).addr = SINGLE_RW_2B_ADDR;
	(i2c_data.msgs[1]).flags = 1; //read
	(i2c_data.msgs[1]).buf = read_buf;

	nRet = ioctl(dev_fh, I2C_RDWR, (unsigned long)&i2c_data);
	if (nRet < 0)
	{
		close(dev_fh);
		free(i2c_data.msgs);
		return -3;
	}
	else
	{
		close(dev_fh);
		free(i2c_data.msgs);
		pData[0] = read_buf[0];
		return 0;
	}
}

/**
 *
 * @param u8BusIndex
 * @param u32Register
 * @param u8wrData
 * @return
 */
int I2C_write_single(unsigned char u8BusIndex, int u32Register, unsigned char u8wrData)
{
	int nRet;
	//BanKIndex
	int u16BankIndex = (u32Register >> 16) & 0xFFFF;
	nRet = I2C_modify_bank_index(u8BusIndex, u16BankIndex);
	if(nRet < 0) return nRet;
	//
	struct i2c_rdwr_ioctl_data i2c_data;
	char reg_buf[3] = {0};
	int dev_fh = I2C_open(u8BusIndex);
	if (dev_fh < 0) return dev_fh;

	ioctl(dev_fh, I2C_TIMEOUT, 1);
	ioctl(dev_fh, I2C_RETRIES, 2);

	i2c_data.nmsgs = 1; //I2C restart once
	i2c_data.msgs=(struct i2c_msg*)malloc(i2c_data.nmsgs*sizeof(struct i2c_msg));

	if (!i2c_data.msgs)
	{
		close(dev_fh);
		return -2;
	}

	reg_buf[0] = (u32Register >> 8) & 0xFF;
	reg_buf[1] = (u32Register     ) & 0xFF;
	reg_buf[2] = u8wrData;

	(i2c_data.msgs[0]).len = 3;
	(i2c_data.msgs[0]).addr = SINGLE_RW_2B_ADDR;
	(i2c_data.msgs[0]).flags = 0; //write
	(i2c_data.msgs[0]).buf = (unsigned char*)reg_buf;

	nRet = ioctl(dev_fh, I2C_RDWR, (unsigned long)&i2c_data);
	if (nRet < 0)
	{
		close(dev_fh);
		free(i2c_data.msgs);
		return -3;
	}
	else
	{
		close(dev_fh);
		free(i2c_data.msgs);
		return 0;
	}
}


bsp_iic.h源码:

#ifndef __BSP_IIC_H
#define __BSP_IIC_H

int I2C_read_single(unsigned char u8BusIndex, int u32Register, unsigned char* pData);
int I2C_write_single(unsigned char u8BusIndex, int u32Register, unsigned char u8wrData);

#endif /* __BSP_IIC_H */

注:我原先使用的是android-ndk-r12b,但是这里面会一直报错。找不到

#include ,然后我换成android-ndk-r16b就可以了。原先的版本没有包含这个头文件。

 

到这里我们的材料都备齐了,接下来就是如何把这些原材料用起来了。

在我们新建的类中,创建这两个IIC常用函数。如下图:

RK3288 基于Androidstdio JNI实现 IIC 通信_第3张图片

然后还是生成头文件,如下图:

RK3288 基于Androidstdio JNI实现 IIC 通信_第4张图片

然后再次用ndk编译。如下图:

RK3288 基于Androidstdio JNI实现 IIC 通信_第5张图片

编译完成后。

我们去MainActivity中新建一个IIC读取的线程。

如下图

RK3288 基于Androidstdio JNI实现 IIC 通信_第6张图片

这里讲解一下我们的code:

这里的  u8BusIndex  是我们要使用的i2c设备端口号是多少。这里我们用的是i2c-1。设备图如下RK3288 基于Androidstdio JNI实现 IIC 通信_第7张图片

 

然后  u32Register 就是我们要写入的寄存器地址,我们这里用的是0x10000001。

有的同学会疑惑,slave address去哪里了。集成在我们底层cpp的code里面了。

然后最后的参数就是 read/write 数据了。

 

跑到这里,工作还没做完。

接下来我们要设置设备端口的执行权限。

我们来到Android stdio的terminal中。前提要保证RK3288和我们的PC在同一个网关下。

找到RK3288的IPv4 IP:192.168.2.168(这个是我的IP,每个人的都不一样)

输入指令: adb connect 192.168.2.168:5555 回车

RK3288 基于Androidstdio JNI实现 IIC 通信_第8张图片

然后输入 adb shell进入RK3288,

再su  进入root 模式,

修改一下i2c-1的权限为777,即可。如下图:

RK3288 基于Androidstdio JNI实现 IIC 通信_第9张图片

修改成功后,连接一下硬件。

从示波器就可以看到我们读写的数据了。

 

 

你可能感兴趣的:(RK3288)