[RK3399][Android7.1]应用笔记 - SPI总线操作

平台 内核版本 安卓版本
RK3399 Linux4.4 Android7.1

SPI初始化

首先定义spi工作模式、传输位数、传输速度等:

static const char *device = "/dev/spidev32766.0";
static uint8_t mode = 3; /* SPI通信使用全双工,设置CPOL=1,CPHA=1。 */
static uint8_t bits = 8; /* 8bits读写,MSB first。*/
static uint32_t speed = 24 * 1000 * 1000;/* 设置12M传输速度 */
static uint16_t delay = 0;

接下来就开始操作总线将其初始化,其中重要的IOCTL命令如下:

命令 解析
SPI_IOC_WR_MODE SPI模式设置可写
SPI_IOC_RD_MODE SPI模式设置可读
SPI_IOC_WR_BITS_PER_WORD SPI的bit/word设置可写
SPI_IOC_RD_BITS_PER_WORD SPI的bit/word设置可读
SPI_IOC_WR_MAX_SPEED_HZ SPI的波特率设置可写
SPI_IOC_RD_MAX_SPEED_HZ SPI的波特率设置可读
/**
* 功 能:打开设备 并初始化设备
* 入口参数 :
* 出口参数:
* 返回值:0 表示已打开 0XF1 表示SPI已打开 其它出错
*/
int SPI_Init(void)
{
    int fd;
    int ret = 0;

    //mode=SPI_MODE_0;

    if (g_SPI_Fd != 0) /* 设备已打开 */
    return 0xF1;

    fd = open(device, O_RDWR);
    if (fd < 0)
        pabort("can't open device");
    else
        printf("SPI - Open Succeed. Start Init SPI...\n");

    g_SPI_Fd = fd;
    /*
    * spi mode
    */
    ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
    if (ret == -1)
        pabort("can't set spi mode");


    ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
    if (ret == -1)
        pabort("can't get spi mode");

    /*
    * bits per word
    */
    ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
    if (ret == -1)
        pabort("can't set bits per word");


    ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
    if (ret == -1)
        pabort("can't get bits per word");

    /*
    * max speed hz
    */
    ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
    if (ret == -1)
        pabort("can't set max speed hz");


    ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
    if (ret == -1)
        pabort("can't get max speed hz");


    printf("spi mode: %d\n", mode);
    printf("bits per word: %d\n", bits);
    printf("max speed: %d KHz (%d MHz)\n", speed / 1000, speed / 1000 / 1000);

    return ret;
}

SPI 自发自收测试程序

/**
* 功 能:自发自收测试程序
* 接收到的数据与发送的数据如果不一样 ,则失败
* 说明:
* 在硬件上需要把输入与输出引脚短跑
*/
int SPI_LookBackTest(void)
{
    int ret, i;
    const int BufSize = 16;
    uint8_t tx[BufSize], rx[BufSize];


    bzero(rx, sizeof(rx));
    for (i = 0; i < BufSize; i++)
    tx[i] = i;

    printf("\nSPI - LookBack Mode Test...\n");
    ret = SPI_Transfer(tx, rx, BufSize);
    if (ret > 1)
    {
        ret = memcmp(tx, rx, BufSize);
        if (ret != 0)
        {
            printf("LookBack Mode Test error\n");
        //pabort("error");
        }
        else
            printf("SPI - LookBack Mode OK\n");
    }

    return ret;
}

spi_ioc_transfer(用户层对一些属性消息的封装,和内核中spi_transfer基本一样,少了一些成员)

/**
* 功 能:同步数据传输
* 入口参数 :
* TxBuf -> 发送数据首地址
* len -> 交换数据的长度
* 出口参数:
* RxBuf -> 接收数据缓冲区
* 返回值:0 成功
*/

int SPI_Transfer(const uint8_t *TxBuf, uint8_t *RxBuf, uint32_t len)
{
    int ret;
    int fd = g_SPI_Fd;
    
    struct spi_ioc_transfer tr ={
        .tx_buf = (unsigned long) TxBuf,
        .rx_buf = (unsigned long) RxBuf,
        .len = len,
        .speed_hz = speed,
        .delay_usecs = delay,
        .bits_per_word = bits,
        .cs_change = 0,
        .tx_nbits = 8,
        .rx_nbits = 8,
        .pad = 0,
    };

    ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
    if (ret < 1)
    printf("can't send spi message");
    else
    {
    #if SPI_DEBUG
        int i;
        printf("nsend spi message Succeed");
        printf("nSPI Send [Len:%d]: ", len);
        for (i = 0; i < len; i++)
        {
            if (i % 8 == 0)
            printf("nt");
            printf("0x%02X ", TxBuf[i]);
        }
        printf("n");


        printf("SPI Receive [len:%d]:", len);
        for (i = 0; i < len; i++)
        {
            if (i % 8 == 0)
            printf("nt");
            printf("0x%02X ", RxBuf[i]);
        }
        printf("n");
    #endif
    }
    return ret;
}

SPI读写

/**
* 功 能:发送数据
* 入口参数 :
* TxBuf -> 发送数据首地址
*len -> 发送与长度
*返回值:0 成功
*/
int SPI_Write(uint8_t *TxBuf, int len)
{
    int ret;
  
    ret = write(g_SPI_Fd, TxBuf, len);
    if (ret < 0)
    printf("SPI Write error\n");
#if SPI_DEBUG
    else
    {
        int i;
        printf("nSPI Write [Len:%d]: ", len);
        for (i = 0; i < len; i++)
        {
            if (i % 8 == 0)
            printf("nt");
            printf("0x%02X ", TxBuf[i]);
        }
        printf("\n");

    }
#endif

    return ret;
}
/**
* 功 能:接收数据
* 出口参数:
* RxBuf -> 接收数据缓冲区
* rtn -> 接收到的长度
* 返回值:>=0 成功
*/
int SPI_Read(uint8_t *RxBuf, int len)
{
    int ret;
    int fd = g_SPI_Fd;
    ret = read(fd, RxBuf, len);
    if (ret < 0)
    printf("SPI Read errorn\n");
    else
    {
    #if SPI_DEBUG
        int i;
        printf("SPI Read [len:%d]:", len);
        for (i = 0; i < len; i++)
        {
            if (i % 8 == 0)
            printf("nt");
            printf("0x%02X ", RxBuf[i]);
        }
        printf("\n");
    #endif
    }

    return ret;
}
发布了295 篇原创文章 · 获赞 99 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/qq_33487044/article/details/104752138