RK3288实现JNI对接上层Java和下层的C++。那么我们就要搭建JNI环境,请参考:
https://blog.csdn.net/shao15232/article/details/102501415
这一节我们主要讲JNI如何实现Android stdio实现IIC与从机通信。
首先在JNI中添加iic源文件。如下图:
这里我们添加了编译so库要使用的源文件,就需要设置一下Android.mk
然后就是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 */
到这里我们的材料都备齐了,接下来就是如何把这些原材料用起来了。
在我们新建的类中,创建这两个IIC常用函数。如下图:
然后还是生成头文件,如下图:
然后再次用ndk编译。如下图:
编译完成后。
我们去MainActivity中新建一个IIC读取的线程。
如下图
这里讲解一下我们的code:
这里的 u8BusIndex 是我们要使用的i2c设备端口号是多少。这里我们用的是i2c-1。设备图如下
然后 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 回车
然后输入 adb shell进入RK3288,
再su 进入root 模式,
修改一下i2c-1的权限为777,即可。如下图:
修改成功后,连接一下硬件。
从示波器就可以看到我们读写的数据了。