2017年9月,英创在Linux的文件系统中移植了针对嵌入式Linux的JRE(Java Runtime Environment),能够支持Java应用程序的运行。由于Java语言不能直接访问硬件资源,英创提供了Java硬件支持包,主要支持的工控接口有:以太网、串口、CAN、GPIO、SPI、I2C、RTC等。本文主要介绍使用Java语言调用英创Java硬件支持包,操作英创主板SPI接口的过程。
1、SPI简介
SPI(Synchronous Peripheral Interface)是一种同步串行数据通讯总线接口,常用于连接ADCs、EPROMs、Sensors或者是其他一些微控制器,SPI具有两种工作模式:master和slave模式,其中master模式提供时钟信号。
图1 SPI主从设备信号连接
SPI有四种数据传输模式,如表1所示,主要差别在于:输出串行同步时钟极性(CPOL)和相位(CPHA)可以进行配置。
SPI mode | CPOL | CPHA | Comments |
0 | 0 | 0 | 时钟的空闲状态为低电平;上升沿采样 |
1 | 0 | 1 | 时钟的空闲状态为低电平;下降沿采样 |
2 | 1 | 0 | 时钟的空闲状态为高电平;下降沿采样 |
3 | 1 | 1 | 时钟的空闲状态为高电平;上升沿采样 |
表1 SPI四种数据传输模式
2、SPI传输数据结构
英创提供的SPI传输数据结构源文件为emtronix.hardware.SPITransfer.java。每一个SPITransfer类实例代表一次SPI传输,其主要成员变量如下所示:
public class SPITransfer {
/*写数据缓存,只读模式时为null*/
public byte[] tx_buf;
/*读数据缓存,只写模式时为null */
public byte[] rx_buf;
/* 缓存长度
* 全双工时,读写缓存应该长度相同;
* 半双工时,非工作状态的缓存为null
*/
public int len;
/*SPI时钟频率*/
public int speed_hz;
/*两个SPITransfer之间的延时*/
public char delay_usecs;
/*SPI传输字宽*/
public byte bits_per_word;
/*本次传输完成之后,是否改变片选*/
public byte cs_change;
public int pad;
}
SPI传输使用同步时钟,在发送的同时,也在接收数据。因此其传输数据结构要同时拥有写数据缓存tx_buf和读数据缓存rx_buf才能支持这种全双工工作模式,并且两个缓存区域长度都为len字节。当然,如果要使用半双工读/写,只需要让tx_buf/rx_buf等于null就可以了。speed_hz为SPI的时钟频率,esm335x最大时钟频率48MHz,esm6800最大时钟频率60MHz;delay_usecs表示连续传输的Transfer之间的间隔,单位为微秒;bits_per_word表示一个字有几个比特组成,最大32;cs_change表示本次传输完成后是否修改片选信号;pad暂时不用设置,保留。
3、SPI传输接口函数
英创提供的SPI传输接口源文件为emtronix.hardware.SPI.java。用户在实例化SPI类后可以调用Open、SetSPI、Transfer、Close对SPI硬件接口进行操作。SPI类的具体信息如下,其中mFd为设备描述符,用户不用设置,由接口函数自动修改。
public class SPI {
private int mFd;
/**
* 打开spi主设备,返回fd.自动修改mFd
* @param dev "/dev/spidev1.0"
* @return 成功返回spi主设备描述符,失败返回-1
*/
public native int Open(String dev);
/**
* 设置SPI的工作参数
* @param args "S16000000-M1-B16-D100" S为时钟速率,M为数据传输模式(0-3),B为数据位宽,D发送完后的延时
* 四个参数之间不分顺序“M1-D100-B16-S16000000”与之前的相同
* @return 成功返回0;失败返回-1
*/
public native int SetSPI(String args);
/**
* SPI一次传输,trans.tx_buf=null,trans.rx_buf != null, only receive;
* trans.tx_buf!=null,trans.rx_buf=null,only send;
* trans.tx_buf!=null,trans.rx_buf!=null, send&receive
* @param trans, 一次spi传输参数
* @param ntrans, 进行ntrans次spi transfer
* @return 成功返回0;失败返回-1
*/
public native int Transfer(SPITransfer[] trans, int ntrans);
/**
* 关闭SPI主设备
* @return 成功返回0;失败返回-1
*/
public native int Close() ;
}
4、SPI测试程序
SPI传输接口中操作SPI的接口函数声明都有native的前缀,表明其实现部分在本地的库当中。英创将所有英创主板的硬件接口访问函数的实现部分编译成了动态链接库libemtronixhardware.so,放在了文件系统/lib目录下。
在编写SPI传输主程序的时候,首先需要加载该库,如下所示:
public class testSPIMain {
static {
System.loadLibrary("emtronixhardware");
}
public static void main(String[] args) {
...
}
}
然后,就可以在main函数中实例化SPI类,并打开主板的SPI设备:
SPI spi = new SPI();
spi.Open("/dev/spidev1.0");
接着,初始化SPI传输数据结构,发送数据:
int transcnt = 1;
SPITransfer[] trans = new SPITransfer[transcnt];
trans[0] = new SPITransfer();
trans[0].tx_buf = tArray;
trans[0].rx_buf = rArray;
trans[0].len = bytes;
trans[0].speed_hz = speed;
trans[0].bits_per_word = (byte) bitspw;
if(spi.Transfer(trans, transcnt) == 0) {
//传输成功,处理数据
}
其中,transcnt表示SPITransfer的个数,每一个SPITransfer需要用户自己实例化。
最后,使用完毕后关闭SPI设备:
spi.Close();
5、SPI测试程序运行结果
运行SPI传输Java主程序需要把编译结果bin文件中的所有目录文件拷贝到主板/mnt/nandflash,或者通过nfs挂载到主板/mnt/nfs目录下。然后,使用“java 包名.类名”运行,如下图所示:
图2 运行SPI测试程序
以上就是使用Java操作英创主板SPI接口的介绍,感兴趣的客户可以通过电话或者邮件联系英创工程师。我们将提供Java示例程序源码供客户参考。
全部0条评论
快来发表一下你的评论吧 !