SPI编程1:用户空间的读写操作

 spi_ioc_transfer

linux中,应用开发常用的结构体主要是struct spi_ioc_transfer:

struct spi_ioc_transfer {
    __u64        tx_buf;
    __u64        rx_buf;
 
    __u32        len;
    __u32        speed_hz;
 
    __u16        delay_usecs;
    __u8        bits_per_word;
    __u8        cs_change;
    __u32        pad;
};

每个 spi_ioc_transfer都可以包含读和写的请求,其中读和写的长度必须相等。所以成员len不是tx_buf和rx_buf缓冲的长度之和,而是它们各自的长度。SPI控制器驱动会先将tx_buf写到SPI总线上,然后再读取len长度的内容到rx_buf。如果只想进行一个方向的传输,把另一个方向的缓冲置为0就可以了。

speed_hz和bits_per_word这两个成员可以为每次通信配置不同的通信速率(必须小于spi_device的max_speed_hz)和字长,如果它们为0的话就会使用spi_device中的配置。

delay_usecs可以指定两个spi_ioc_transfer之间的延时,单位是微妙。一般不用定义。

cs_change指定这个cs_change结束之后是否需要改变片选线。一般针对同一设备的连续的几个spi_ioc_transfer,只有最后一个需要将这个成员置位。这样省去了来回改变片选线的时间,有助于提高通信速率。

 SPI设备的初始化

void spi_Init()
{
    int ret = 0;
 
 
    spifd = open(device, O_RDWR);
    if (spifd < 0)
        pabort("can't open device");
 
    /*
     * spi mode
     */
    ret = ioctl(spifd, SPI_IOC_WR_MODE, &mode);
    if (ret == -1)
        pabort("can't set spi mode");
 
    ret = ioctl(spifd, SPI_IOC_RD_MODE, &mode);
    if (ret == -1)
        pabort("can't get spi mode");
 
    /*
     * bits per word
     */
    ret = ioctl(spifd, SPI_IOC_WR_BITS_PER_WORD, &bits);
    if (ret == -1)
        pabort("can't set bits per word");
 
    ret = ioctl(spifd, SPI_IOC_RD_BITS_PER_WORD, &bits);
    if (ret == -1)
        pabort("can't get bits per word");
 
    /*
     * max speed hz
     */
    ret = ioctl(spifd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
    if (ret == -1)
        pabort("can't set max speed hz");
 
    ret = ioctl(spifd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
    if (ret == -1)
        pabort("can't get max speed hz");
}

首先open打开SPI的设备,然后通过ioctl函数进行数据位、速率、模式进行配置。

SPI的读写

int spi_read()
{
    bt_devide_msg msg;
    unsigned char ucRegVal;
    int ret,i;
    unsigned char tx[20];
    for(i = 0;i<20;i++)
    {
        tx[i] = 0xda;
    }
    unsigned char rx[ARRAY_SIZE(tx)] = {0, };
    struct spi_ioc_transfer tr = {
        .tx_buf = (unsigned long)tx,
        .rx_buf = (unsigned long)rx,
        .len = ARRAY_SIZE(tx),
        .delay_usecs = udelay,
        .speed_hz = speed,
        .bits_per_word = bits,
    };
    
    ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
    if (ret < 1)
    {
        printf("can't read spi message\n");
        return -1;
    }
    
    if(rx[0] !=0xAA)
    {
        printf("read spi data: ");    
        for (ret = 0; ret < ARRAY_SIZE(tx); ret++) 
        {
            printf("%02X ", rx[ret]);
        }
        printf("\n");
    }
    
    ucRegVal = rx[ARRAY_SIZE(tx)-1];
    get_data_process(rx);
                            
  return 1;

write函数和这类似。

测试函数

void main()
{
    spi_init();
    spi_read();
}

猜你喜欢

转载自www.cnblogs.com/xiaojianliu/p/9841677.html
今日推荐