1.初始化open/close SPI device
#include
#include
#include
#include
#include
#include
#include
#define TAG "terawins" // 这个是自定义的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类型
static unsigned char mode=SPI_MODE_0;
static unsigned char bits = 8;
static unsigned char delay = 10;
static unsigned int speed = 10000000;
#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) {
LOGE( "can not open SPI device\n" );
}
ret = ioctl(fd, SPI_IOC_WR_MODE,&mode);
if (ret == -1)
LOGE("can't set spi mode");
ret = ioctl(fd, SPI_IOC_RD_MODE,&mode);
if (ret == -1)
LOGE("can't get spi mode");
ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if (ret == -1)
LOGE("can't set bits per word");
ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
if (ret == -1)
LOGE("can't get bits per word");
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if (ret == -1)
LOGE("can't set max speed hz");
ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
if (ret == -1)
LOGE("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);
}
2.SPI 单字节写
1)定义tx 长度 cmd + addr + data (6字节);
2).len 表示发送总数据的长度(cmd + addr + data);
3)ioctl(fd, SPI_IOC_MESSAGE(1), &tr); MESSAGE(1)表示:半双工;MESSAGE(2)表示全双工;
4)单字节写 rx 数据长度为与data 长度一致,写了1个字节rx就设定为1(根据实际情况,也不可不设定);
void SPI_write_single(int fd, int addr, unsigned char data) {
int ret;
uint8_t tx[6] = {0};
uint8_t rx[1] = {0};
tx[0] = 0x01;
tx[1] = (unsigned char)(addr >> 24 & 0xFF);
tx[2] = (unsigned char)(addr >> 16 & 0xFF);
tx[3] = (unsigned char)(addr >> 8 & 0xFF);
tx[4] = (unsigned char)(addr & 0xFF);
tx[5] = data;
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long) tx, //定义发送缓冲区指针
.rx_buf = (unsigned long) rx, //定义接收缓冲区指针
.len = ARRAY_SIZE(tx),
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = bits,
};
ret = ioctl(fd, SPI_IOC_MESSAGE(2), &tr);//执行spidev.c中ioctl的default进行数据传输
if (ret < 0) {
LOGD("can't send spi message");
}
}
3.SPI 单字节读
1)定义tx 长度 cmd + addr + Dummy(15字节) ,有些spi slave 读的时候需要发送一些固定数量的空字节之后,才开始读data,该例子的Dummy 数量为10 ,发送了十个0x00,之后rx开始接收数据(rx在第十六个数组rx[15]里存放了接收的数据);
2)tx和rx 的len 读的时候,数组长度设定为一致;
3)ioctl(fd, SPI_IOC_MESSAGE(1), &tr); MESSAGE(1)表示:半双工;MESSAGE(2)表示全双工;
unsigned char SPI_read_single(int fd, int addr) {
int ret,i;
uint8_t tx[16] = {0};
uint8_t rx[16] = {0};
tx[0] = 0x02;
tx[1] = (unsigned char)(addr >> 24 & 0xFF);
tx[2] = (unsigned char)(addr >> 16 & 0xFF);
tx[3] = (unsigned char)(addr >> 8 & 0xFF);
tx[4] = (unsigned char)(addr & 0xFF);
for(i = 5;i < 16;i++){
tx[i] = 0x00;
}
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long) tx, //定义发送缓冲区指针
.rx_buf = (unsigned long) rx, //定义接收缓冲区指针
.len = ARRAY_SIZE(tx),
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = bits,
};
ret = ioctl(fd, SPI_IOC_MESSAGE(2), &tr);//执行spidev.c中ioctl的default进行数据传输
if (ret < 0) {
LOGD("can't send spi message");
}
return rx[15];
}
4.SPI 多字节写
1)定义tx 长度 cmd + addr + data ;
2).len 表示发送总数据的长度(cmd + addr + data);
3)ioctl(fd, SPI_IOC_MESSAGE(1), &tr); MESSAGE(1)表示:半双工;MESSAGE(2)表示全双工;
4)一般tx 缓存区的buffer 限定在4096,如果想每次burst 的data 大于4096 个,就要去修改spidev.c内容,修改后重新编译内核,如下;
static LIST_HEAD(device_list);
static DEFINE_MUTEX(device_list_lock);
static unsigned bufsiz = 4096;//tx 大小
module_param(bufsiz, uint, S_IRUGO);
MODULE_PARM_DESC(bufsiz, "data bytes in biggest supported SPI message");
切记,tx 的大小4096 是总的cmd + addr + data 长度,所以如果每次burst data 数量等于4096,再加上cmd+addr >4096 ,buffer 就会爆掉;burst 指的是只发送一次cmd 和addr ,后面写很多个data;
void SPI_nbytes_write(int fd, int addr, unsigned char *data, unsigned int len) {
int ret,i;
uint8_t tx[4096] = {0};
uint8_t rx[4096] = {0};
tx[0] = 0x01;
tx[1] = (unsigned char)(addr >> 24 & 0xFF);
tx[2] = (unsigned char)(addr >> 16 & 0xFF);
tx[3] = (unsigned char)(addr >> 8 & 0xFF);
tx[4] = (unsigned char)(addr & 0xFF);
for(i = 0;i
5.SPI 多字节读
1)定义tx 长度 cmd + addr + data ,rx 长度和tx一致;
2).len 表示发送总数据的长度(cmd + addr + data);
3)ioctl(fd, SPI_IOC_MESSAGE(1), &tr); MESSAGE(1)表示:半双工;MESSAGE(2)表示全双工;
4)一般tx 缓存区的buffer 限定在4096,如果想每次burst 的data 大于4096 个,就要去修改spidev.c内容,修改后重新编译内核,如下;
static LIST_HEAD(device_list);
static DEFINE_MUTEX(device_list_lock);
static unsigned bufsiz = 4096;//tx 大小
module_param(bufsiz, uint, S_IRUGO);
MODULE_PARM_DESC(bufsiz, "data bytes in biggest supported SPI message");
切记,rx 的大小4096 是总的cmd + addr + data 长度,所以如果每次burst data 数量等于4096,再加上cmd+addr >4096 ,buffer 就会爆掉;burst 指的是只发送一次cmd 和addr ,后面读很多个data;
void SPI_nbyte_read(int fd, int addr, unsigned char *data, unsigned int len) {
int ret,i;
uint8_t tx[4096]={0};
uint8_t rx[4096]={0};
tx[0] = 0x02;
tx[1] = (unsigned char)(addr >> 24 & 0xFF);
tx[2] = (unsigned char)(addr >> 16 & 0xFF);
tx[3] = (unsigned char)(addr >> 8 & 0xFF);
tx[4] = (unsigned char)(addr & 0xFF);
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long) tx, //定义发送缓冲区指针
.rx_buf = (unsigned long) rx, //定义接收缓冲区指针
.len = 15+len,
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = bits,
};
ret = ioctl(fd, SPI_IOC_MESSAGE(2), &tr);//执行spidev.c中ioctl的default进行数据传输
if (ret < 0) {
LOGD("can't send spi message");
}else {
for(i = 0;i < len;i++){
data[i] = rx[15+i];
}
}
}
rk3288 spi硬件连接可参考:https://blog.csdn.net/Chhjnavy/article/details/100158719