[linux/应用]SPI通讯应用

linux系统SPI通讯测试

源码

#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
 
#include "Debug.h"

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

unsigned char r_buf[256];
unsigned char w_buf[256];

static void pabort(const char *s)
{
    perror(s);
    abort();
}
 
int SPI_Transfer(const uint8_t *TxBuf, uint8_t *RxBuf, int 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 = 0,

            .delay_usecs = delay,
            .bits_per_word = 2
    };
 
    ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
    if (ret < 1)
        pr_err("can't send spi message");
    else
    {
#if SPI_DEBUG
        int i;
        pr_debug("\nsend spi message Succeed");
        pr_debug("\nSPI Send [Len:%d]: ", len);
        for (i = 0; i < len; i++)
        {
            if (i % 8 == 0)
            printf("\n\t");
            printf("0x%02X ", TxBuf[i]);
        }
        printf("\n");
 
        pr_debug("SPI Receive [len:%d]:", len);
        for (i = 0; i < len; i++)
        {
            if (i % 8 == 0)
            printf("\n\t");
            printf("0x%02X ", RxBuf[i]);
        }
        printf("\n");
#endif
    }
    return ret;
}
 

int SPI_Write(uint8_t *TxBuf, int len)
{
    int ret;
    int fd = g_SPI_Fd;
 
    ret = write(fd, TxBuf, len);
    if (ret < 0)
        pr_err("SPI Write error\n");
    else
    {
#if SPI_DEBUG
        int i;
        pr_debug("\nSPI Write [Len:%d]: ", len);
        for (i = 0; i < len; i++)
        {
            if (i % 8 == 0)
            printf("\n\t");
            printf("0x%02X ", TxBuf[i]);
        }
        printf("\n");
 
#endif
    }
 
    return ret;
}
 
int SPI_Read(uint8_t *RxBuf, int len)
{
    int ret;
    int fd = g_SPI_Fd;
    ret = read(fd, RxBuf, len);
    if (ret < 0)
        pr_err("SPI Read error\n");
    else
    {
#if SPI_DEBUG
        int i;
        pr_debug("SPI Read [len:%d]:", len);
        for (i = 0; i < len; i++)
        {
            if (i % 8 == 0)
            printf("\n\t");
            printf("0x%02X ", RxBuf[i]);
        }
        printf("\n");
#endif
    }
 
    return ret;
}
 
int SPI_Open_(const char* device)
{
    int fd;
    int ret = 0;
 
    if (g_SPI_Fd != 0) /* 设备已打开 */
        return 0xF1;
 
    fd = open(device, O_RDWR);
    if (fd < 0)
        pabort("can't open device");
    else
        pr_debug("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");
 
    pr_debug("spi mode: %d\n", mode);
    pr_debug("bits per word: %d\n", bits);
    pr_debug("max speed: %d KHz (%d MHz)\n", speed / 1000, speed / 1000 / 1000);
 
    return ret;
}
 

int SPI_Close(void)
{
    int fd = g_SPI_Fd;
 
    if (fd == 0) /* SPI是否已经打开*/
        return 0;
    close(fd);
    g_SPI_Fd = 0;
 
    return 0;
}
 
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;
 
    pr_debug("\nSPI - LookBack Mode Test...\n");
    ret = SPI_Transfer(tx, rx, BufSize);
    if (ret > 1)
    {
        ret = memcmp(tx, rx, BufSize);
        if (ret != 0)
        {
            pr_err("LookBack Mode Test error\n");
//            pabort("error");
        }
        else
            pr_debug("SPI - LookBack Mode  OK\n");
    }
 
    return ret;
}

note

  • 使用write/read测试SPI通讯只能半双工工作
  • 使用ioctl就可以全双工工作,并且可以按照需求修改SPI配置
    • 可以参考内核源: kernel/linux-5.15/tools/spi/spidev_test.c
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值