Linux下SPI设备驱动实验:使用内核提供的读写SPI设备中的数据的函数

一. 简介

前面文章的学习,已经实现了 读写SPI设备中数据的功能。文章如下:

Linux下SPI设备驱动实验:验证读写SPI设备中数据的函数功能-CSDN博客

本文来使用内核提供的读写SPI设备中的数据的API函数,来实现读写SPI设备中数据。

二.  Linux下SPI设备驱动实验:使用内核提供的读写SPI设备中的数据的函数

1. 内核提供的读写SPI设备中的数据的函数

所使用内核源码为NXP官方提供。读写SPI设备中的数据的函数所在内核源码路径为:

/linux-imx-rel_imx_4.1.15_2.1.0_ga/include/linux/spi/spi.h

(1)  读取SPI设备中数据的函数

spi_read函数
int spi_read(struct spi_device *spi, void *buf, size_t len)
spi_write_then_read函数
/* this copies txbuf and rxbuf data; for small transfers only! */
int spi_write_then_read(struct spi_device *spi, const void *txbuf, unsigned n_tx,
		void *rxbuf, unsigned n_rx);

(2) 向SPI设备中写数据的函数

int spi_write(struct spi_device *spi, const void *buf, size_t len)

2.  使用内核提供的读写SPI设备中的数据的函数

这里的代码与前一篇文章相比,不同的是 读写SPI设备中数据的函数实现。

读写SPI设备中数据的函数实现如下(spi_icm20608.c文件中):

static int spi_write_regs(struct icm20608_Dev* dev, u8 reg_addr, void* buf, int len)
{
    int ret = 0;
    unsigned char value = 0;
    struct spi_device* spi_dev = (struct spi_device*)dev->private_data;

    value = reg_addr & ~0x80; //最高为位清0(写标志位)
    //发送要写入的寄存器地址
    ret = spi_write(spi_dev, &value, 1); 
    if(ret)
        printk("spi_write_regs: spi_write reg_addr error\n");
    //发送要写入SPI设备中的数据
    ret = spi_write(spi_dev, buf, len); 
    if(ret)
        printk("spi_write_regs: spi_write  data error\n");
    return ret;
}

static int spi_read_regs(struct icm20608_Dev* dev, u8 reg_addr, void* buf, int len)
{
    int ret = 0;
    unsigned char value = 0;
    struct spi_device* spi_dev = (struct spi_device*)dev->private_data;
    
    value = reg_addr | 0x80; //最高为置1(读标志位)
#if  0    //发送要读取的寄存器的地址
    ret = spi_write(spi_dev, &value, 1);
    if(ret < 0)
        printk("spi_read_regs: spi_write reg_addr error\n");
    //接收SPI设备中的数据 
    ret = spi_read(spi_dev, buf, len);
    if(ret)
        printk("spi_read_regs: spi_read data error\n");
#endif
    spi_write_then_read(spi_dev, &value, 1, buf, len);
    return ret;
}

/*ICM20608设备初始化(即SPI设备初始化)*/
static int icm20608_register_init(struct icm20608_Dev* dev)
{
    unsigned char value = 0;

    spi_write_reg_onebyte(&icm20608_dev, ICM20_PWR_MGMT_1, 0x80); /*复位,复位后为0x40,睡眠模式 */
    mdelay(50);
    spi_write_reg_onebyte(&icm20608_dev, ICM20_PWR_MGMT_1, 0x01);  /*关闭睡眠,自动选择时钟 */
    mdelay(50);

    value = spi_read_reg_onebyte(&icm20608_dev,ICM20_WHO_AM_I);
    printk("ICM20_WHO_AM_I: 0x%02X\r\n", value);
    if((value != ICM20608G_ID) && (value != ICM20608D_ID))
    {
        return 1;
    }
    value = spi_read_reg_onebyte(&icm20608_dev,ICM20_PWR_MGMT_1);
    printk("ICM20_PWR_MGMT_1: 0x%02X\r\n", value);

    return 0;
}

可以看出,读SPI设备中数据的实现函数中,有一段屏蔽的代码段,如下代码段:

    ret = spi_write(spi_dev, &value, 1);
    if(ret < 0)
        printk("spi_read_regs: spi_write reg_addr error\n");
    //接收SPI设备中的数据 
    ret = spi_read(spi_dev, buf, len);
    if(ret)
        printk("spi_read_regs: spi_read data error\n");

这里先写了SPI设备的寄存器地址,然后从SPI设备中读取数据。

经过测试,这段代码最后 SPI读取数据是不对的,也就是存在问题。正点原子的左神说是,可能的原因是 在发送寄存器地址前片选信号是拉低的,之后片选信号拉高了,然后在从SPI深圳中读取数据前,片选信号再拉低。这样导致时序混乱。

所以,这里从SPI设备中读取数据调用了 spi_write_then_read函数,不过根据该函数的注释信息,说这个函数只适用于小数量的数据传输!

三.  测试

将 编译的驱动进行编译后,将新生成的驱动模块拷贝到开发板系统中,加载驱动模块如下:

可以看出,寄存器ICM20_PWR_MGMT_1在 ICM20608初始化函数中最后写入了0x01,这里读出来也是 0x01,确定读写SPI设备函数运行正常。

卸载模块:

卸载驱动模块时, remove函数也运行了,也不存在错误的信息。

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值