准备工作:

1.搭建adbwireless 环境

参考:https://blog.csdn.net/Chhjnavy/article/details/97643584

           https://blog.csdn.net/Chhjnavy/article/details/98845930

2.熟悉使用jni 将C与java互通

参考:https://blog.csdn.net/Chhjnavy/article/details/94721080

目标板:rk3288 android

系统:android7.1.2

1.源码根目录:/kernel/arch\arm/boot/dts  在rk3288-miniarm.dts 文件中添加spi  设备节点

&spi2 {status = "okay";max-freq = <50000000>;spidev@0 {compatible = "rockchip,spi_tinker";reg = <0>;spi-max-frequency = <50000000>;spi-cpha = <1>;};spidev@1 {compatible = "rockchip,spi_tinker";reg = <1>;spi-max-frequency = <50000000>;spi-cpha = <1>;};};

2.make menuconfig  添加驱动模块

 3.kernel 重新编译后,将最终的镜像烧录SD卡,通过终端可以在/dev 下看到spidev2.0  spidev2.1  两个设备节点

 其中 spidev2.0  spidev2.1 中的数字2 表示bus num ,小数点后的0 和 1 分别表示使用的是选通信号cs0 ,cs1

对应的物理引脚如下所示:

使用杜邦线将rk3288 的spi 引脚与flash spi引脚对接 :  GP8B1_SPI2TXD = DI  、  GP8B0_SPI2RXD = DO 

GP8A6_SPI2CLK = CLK 、 GP8A7_SPI2CSN0  = CS   、 GND = GND  

4.通过open 打开spidev2.0 设备(CS 连接的是GP8A7_SPI2CSN0 )获取设备号

/* * unsigned char u8BusIndex 是从UI 中获取的使用spidev2.x  表示使用0 还是 1  * 这里cs 硬件连接的是0 * */int SPI_open(unsigned char u8BusIndex){    char szDev[16] = {0};    int fd,ret;    sprintf(szDev, "/dev/spidev2.%d", u8BusIndex);    fd = open(szDev, O_RDWR);    LOGD("*************************************************fd = %d", fd);    if (fd < 0) {        perror( "can not open SPI device\n" );    }    ret = ioctl(fd, SPI_IOC_WR_MODE,&mode);    if (ret == -1)        LOGD("can't set spi mode");    ret = ioctl(fd, SPI_IOC_RD_MODE,&mode);    if (ret == -1)        LOGD("can't get spi mode");    ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);    if (ret == -1)        LOGD("can't set bits per word");    ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);    if (ret == -1)        LOGD("can't get bits per word");    ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);    if (ret == -1)        LOGD("can't set max speed hz");    ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);    if (ret == -1)        LOGD("can't get max speed hz");    LOGD("spi mode: %d\n", mode);    LOGD("bits per word: %d\n", bits);    LOGD("max speed: %d Hz (%d MHz)\n", speed, speed/1000000);    return fd;}

5.通过 spi  提供的结构体 struct spi_ioc_transfer xfer[7]; 来配置spi 发送时序

/*Command Type MX25L25645GRDID 9Fh Manufacturer ID Memory Type Memory Density            C2              20          19RES ABh Electronic ID            18REMS 90h Manufacturer ID Device ID            C2              18QPIID AFh Manufacturer ID Memory Type Memory Density            C2              20          19*/int SPI_readFlashID(unsigned int u8BusIndex){    int ret;    int fd;    uint8_t readIDCmd[1];    uint8_t readDummy[1];    uint8_t readDummy2[1];    uint8_t readADD[1];    uint8_t dataID[3] = {0};    fd = SPI_open(u8BusIndex);    if(fd < 0){        LOGD("fail open device ==================fd = %d", fd);        return -1;    }    struct spi_ioc_transfer xfer[7];    memset(xfer, 0, sizeof(xfer));    readIDCmd[0]=0x9F;    xfer[0].tx_buf =(unsigned long)readIDCmd;    xfer[0].len = 1;    readDummy[0]=0x00;    xfer[1].tx_buf =(unsigned long)readDummy;    xfer[1].len = 1;    readDummy2[0]=0x00;    xfer[2].tx_buf =(unsigned long)readDummy2;    xfer[2].len = 1;    readADD[0]=0x00;    xfer[3].tx_buf =(unsigned long)readADD;    xfer[3].len = 1;    xfer[4].rx_buf = (unsigned long)dataID;    xfer[4].len = 1;    xfer[5].rx_buf = (unsigned long)(dataID+1);    xfer[5].len = 1;    xfer[6].rx_buf = (unsigned long)(dataID+2);    xfer[6].len = 1;    ret = ioctl(fd, SPI_IOC_MESSAGE(7), xfer);    if (ret < 0)    {        LOGD("********************Error: SPI_IOC_MESSAGE\n");        return -1;    }    LOGD("dataID[0]************************************************* = %x", dataID[0]);    LOGD("dataID[1]************************************************* = %x", dataID[1]);    LOGD("dataID[2]************************************************* = %x", dataID[2]);    return ret;}

6.在jni 中直接调用 函数 int SPI_readFlashID(unsigned int u8BusIndex) 即可打印看到spi ID ,完整code 如下:

#include #include#include #include #include #include #include #include #include #include #include #include #include #include#include #include #include #include #include #include #include #define TAG "myDemo-jni" // 这个是自定义的LOG的标识#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__) // 定义LOGD类型#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__) // 定义LOGI类型#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__) // 定义LOGW类型#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__) // 定义LOGE类型#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__) // 定义LOGF类型#define TAG "myDemo-jni" // 这个是自定义的LOG的标识#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__) // 定义LOGD类型#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__) // 定义LOGI类型#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__) // 定义LOGW类型#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__) // 定义LOGE类型#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__) // 定义LOGF类型#define _Included_com_example_t613_spi_Java_Interfacestatic unsigned char mode=SPI_MODE_0;static unsigned char bits = 8;static unsigned char delay = 10;static unsigned int speed = 2200000;#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))/* * unsigned char u8BusIndex 是从UI 中获取的使用spidev2.x  表示使用0 还是 1 * 这里cs 硬件连接的是0 * */int SPI_open(unsigned char u8BusIndex){    char szDev[16] = {0};    int fd,ret;    sprintf(szDev, "/dev/spidev2.%d", u8BusIndex);    fd = open(szDev, O_RDWR);    LOGD("*************************************************fd = %d", fd);    if (fd < 0) {        perror( "can not open SPI device\n" );    }    ret = ioctl(fd, SPI_IOC_WR_MODE,&mode);    if (ret == -1)        LOGD("can't set spi mode");    ret = ioctl(fd, SPI_IOC_RD_MODE,&mode);    if (ret == -1)        LOGD("can't get spi mode");    ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);    if (ret == -1)        LOGD("can't set bits per word");    ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);    if (ret == -1)        LOGD("can't get bits per word");    ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);    if (ret == -1)        LOGD("can't set max speed hz");    ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);    if (ret == -1)        LOGD("can't get max speed hz");    LOGD("spi mode: %d\n", mode);    LOGD("bits per word: %d\n", bits);    LOGD("max speed: %d Hz (%d MHz)\n", speed, speed/1000000);    return fd;}int SPI_close(int dev_fh){    return close(dev_fh);}/*Command Type MX25L25645GRDID 9Fh Manufacturer ID Memory Type Memory Density            C2              20          19RES ABh Electronic ID            18REMS 90h Manufacturer ID Device ID            C2              18QPIID AFh Manufacturer ID Memory Type Memory Density            C2              20          19*/int SPI_readFlashID(unsigned int u8BusIndex){    int ret;    int fd;    uint8_t readIDCmd[1];    uint8_t readDummy[1];    uint8_t readDummy2[1];    uint8_t readADD[1];    uint8_t dataID[3] = {0};    fd = SPI_open(u8BusIndex);    if(fd < 0){        LOGD("fail open device ==================fd = %d", fd);        return -1;    }    struct spi_ioc_transfer xfer[7];    memset(xfer, 0, sizeof(xfer));    readIDCmd[0]=0x9F;    xfer[0].tx_buf =(unsigned long)readIDCmd;    xfer[0].len = 1;    readDummy[0]=0x00;    xfer[1].tx_buf =(unsigned long)readDummy;    xfer[1].len = 1;    readDummy2[0]=0x00;    xfer[2].tx_buf =(unsigned long)readDummy2;    xfer[2].len = 1;    readADD[0]=0x00;    xfer[3].tx_buf =(unsigned long)readADD;    xfer[3].len = 1;    xfer[4].rx_buf = (unsigned long)dataID;    xfer[4].len = 1;    xfer[5].rx_buf = (unsigned long)(dataID+1);    xfer[5].len = 1;    xfer[6].rx_buf = (unsigned long)(dataID+2);    xfer[6].len = 1;    ret = ioctl(fd, SPI_IOC_MESSAGE(7), xfer);    if (ret < 0)    {        LOGD("********************Error: SPI_IOC_MESSAGE\n");        return -1;    }    LOGD("dataID[0]************************************************* = %x", dataID[0]);    LOGD("dataID[1]************************************************* = %x", dataID[1]);    LOGD("dataID[2]************************************************* = %x", dataID[2]);    return ret;}extern "C"{JNIEXPORT jbyteArray JNICALL Java_com_example_t613_1spi_Java_1Interface_SPI_1read(JNIEnv *env, jobject instance, jbyte u8BusIndex, jint u32RegStart, jint nLen){    int nRet;    unsigned char u8Read[2] = {0};    int szTmp[1] = {-1};    jbyteArray jResult = env->NewByteArray(nLen + 1);    unsigned char *pTmp = (unsigned char*)malloc(nLen + 1);    if(!pTmp) {        env->SetByteArrayRegion(jResult, 0, 1, (jbyte*)szTmp);    }else {        nRet = SPI_readFlashID((unsigned char)u8BusIndex);        for(int i = 0; i < nLen; i++)        {            pTmp[i + 1] = u8Read[i];        }        pTmp[0] = nRet;        if(nRet)        {            env->SetByteArrayRegion(jResult, 0, 1, (jbyte*)pTmp);        }        else        {            env->SetByteArrayRegion(jResult, 0, nLen + 1, (jbyte*)pTmp);        }        free(pTmp);    }    LOGD("=================================================================");    return jResult;}JNIEXPORT jint JNICALL Java_com_example_t613_1spi_Java_1Interface_SPI_1write(JNIEnv *env, jobject instance, jbyte u8BusIndex, jint u32RegStart, jbyteArray _szBufWrite){    jint nRet;    jint nLen = env->GetArrayLength(_szBufWrite);    jbyte *pszWrite = env->GetByteArrayElements(_szBufWrite, NULL);    for(int i = 0; i < nLen; i++)    {        if(nRet) break;    }    env->ReleaseByteArrayElements(_szBufWrite, pszWrite, 0);    return nRet;}}

 注意:

1)通过终端给/dev/spidev2.0  可执行权限 

chmod 777  /dev/spidev2.0

2)jni code 中只是调用一下,UI 中并没有显示出ID, ID 通过logcat 打印看到。

完整app code 链接如下(点击read  即可在android studio logcat 下看到打印的flash ID):https://download.csdn.net/download/chhjnavy/11644546

更多相关文章

  1. Ubuntu 10.04不能连接到HTC G1设备
  2. XML 常见符号的实体定义:用在 Android(安卓)的 strings.xml 中
  3. Android中自定义组件及自定义属性
  4. Android获取定位权限,获取设备所在的经纬度
  5. Android(安卓)RoboGuice2 使用指南(3): Inject 自定义View
  6. mac 下android开发 eclipse中找不到设备
  7. android-自定义Seekbar
  8. Android训练课程)快三如何快速回本稳赢81512073
  9. android之自定义渐变颜色(一)

随机推荐

  1. android layout属性介绍
  2. 【Android】 基于XMPP Smack框架 开发QQ
  3. [Android] 对android:layout_weight的一
  4. Android数据加密之Rsa加密
  5. 一样的Android,不一样的学习
  6. 修改android公共控件和后台服务
  7. Android布局控件属性
  8. Android(安卓)动态加载(二) - 基础篇(二)
  9. Android布局文件中常用的属性
  10. Android(安卓)SDK离线快速安装教程 Andro