• 正文
  • 相关推荐
申请入驻 产业图谱

飞凌嵌入式ElfBoard ELF 1板卡-六轴传感器驱动

05/22 16:43
1215
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

例程代码路径:ELF 1开发板资料包3-例程源码3-2 驱动例程源码9_Regmap-icm20607

下面编写一个六轴传感器的驱动,来了解Regmap子系统的具体使用。

一、修改设备树

(一)查看原理图引脚复用表格,确定六轴传感器连接引脚。

(二)在设备树文件arch/arm/boot/dts/imx6ull-elf1-emmc.dts的IOMUX节点下添加子节点:

pinctrl_ecspi1: ecspi1grp {

fsl,pins = <

MX6UL_PAD_LCD_DATA20__ECSPI1_SCLK       0x10b0

MX6UL_PAD_LCD_DATA21__GPIO3_IO26         0x10b0

MX6UL_PAD_LCD_DATA22__ECSPI1_MOSI       0x10b0

MX6UL_PAD_LCD_DATA23__ECSPI1_MISO       0x10b0

>;

};

添加后效果如下:

在arch/arm/boot/dts/imx6ull-elf1-emmc.dts文件中搜索引脚PAD NAME,在&iomux的子节点pinctrl_lcdif_dat节点下搜索到了这几个引脚的复用,我们需要将这些注释掉:

(三)添加设备节点

在arch/arm/boot/dts/imx6ull.dtsi中已经存在了spi接口的相关节点ecspi1-ecspi4,我们只需要在arch/arm/boot/dts/imx6ull-elf1-emmc.dts文件中引用相关节点,并在该节点下添加子节点spidevicm:

&ecspi1 {

pinctrl-names = "default";

pinctrl-0 = <&pinctrl_ecspi1>;

fsl,spi-num-chipselects = <1>;

cs-gpios = <&gpio3 26 GPIO_ACTIVE_LOW>;

status = "okay";

spidevicm: icm20607@0 {

compatible = "icm20607";

spi-max-frequency = <8000000>;

reg = <0>;

};

};

添加后的效果如下:

(四)重新编译设备树,用7.9.4.2节编译好的内核即可:

. /opt/fsl-imx-x11/4.1.15-2.0.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi

elf@ubuntu:~/work/linux-imx-imx_4.1.15_2.0.0_ga$ make dtbs

编译生成的设备树文件为imx6ull-elf1-emmc.dtb,参考《01-0 ELF1、ELF1S开发板_快速启动手册_V1》4.4节单独更新设备树。

二、编写icm20607.c驱动

(一)在驱动中要操作很多芯片相关的寄存器,所以需要先新建一个icm20607.h的头文件,用来定义相关寄存器值。

#ifndef ICM20607_H

#define ICM20607_H

/***************************************************************

文件名 : icm20607.h

描述 : ICM20607寄存器地址描述头文件

***************************************************************/

#define ICM20608G_ID 0XAF /* ID值 */

#define ICM20608D_ID 0XAE /* ID值 */

#define ICM20607_ID 0X05

/* ICM20607寄存器

*复位后所有寄存器地址都为0,除了

*Register 107(0x41) Power Management 1

*Register 117(0x05) WHO_AM_I

*Register 26(0x80) CONFIG

*/

/* 陀螺仪和加速度自测(出产时设置,用于与用户的自检输出值比较) */

/* ICM20607 SELF TEST GYRO Modify 0x ->5x */

#define ICM20_SELF_TEST_X_GYRO 0x50

#define ICM20_SELF_TEST_Y_GYRO 0x51

#define ICM20_SELF_TEST_Z_GYRO 0x52

#define ICM20_SELF_TEST_X_ACCEL 0x0D

#define ICM20_SELF_TEST_Y_ACCEL 0x0E

#define ICM20_SELF_TEST_Z_ACCEL 0x0F

/* 陀螺仪静态偏移 */

#define ICM20_XG_OFFS_USRH 0x13

#define ICM20_XG_OFFS_USRL 0x14

#define ICM20_YG_OFFS_USRH 0x15

#define ICM20_YG_OFFS_USRL 0x16

#define ICM20_ZG_OFFS_USRH 0x17

#define ICM20_ZG_OFFS_USRL 0x18

#define ICM20_SMPLRT_DIV 0x19

#define ICM20_CONFIG 0x1A

#define ICM20_GYRO_CONFIG 0x1B

#define ICM20_ACCEL_CONFIG 0x1C

#define ICM20_ACCEL_CONFIG2 0x1D

#define ICM20_LP_MODE_CFG 0x1E

#define ICM20_ACCEL_WOM_THR 0x1F

#define ICM20_FIFO_EN 0x23

#define ICM20_FSYNC_INT 0x36

#define ICM20_INT_PIN_CFG 0x37

#define ICM20_INT_ENABLE 0x38

#define ICM20_INT_STATUS 0x3A

/* 加速度输出 */

#define ICM20_ACCEL_XOUT_H 0x3B

#define ICM20_ACCEL_XOUT_L 0x3C

#define ICM20_ACCEL_YOUT_H 0x3D

#define ICM20_ACCEL_YOUT_L 0x3E

#define ICM20_ACCEL_ZOUT_H 0x3F

#define ICM20_ACCEL_ZOUT_L 0x40

/* 温度输出 */

#define ICM20_TEMP_OUT_H 0x41

#define ICM20_TEMP_OUT_L 0x42

/* 陀螺仪输出 */

#define ICM20_GYRO_XOUT_H 0x43

#define ICM20_GYRO_XOUT_L 0x44

#define ICM20_GYRO_YOUT_H 0x45

#define ICM20_GYRO_YOUT_L 0x46

#define ICM20_GYRO_ZOUT_H 0x47

#define ICM20_GYRO_ZOUT_L 0x48

#define ICM20_SIGNAL_PATH_RESET 0x68

#define ICM20_ACCEL_INTEL_CTRL 0x69

#define ICM20_USER_CTRL 0x6A

#define ICM20_PWR_MGMT_1 0x6B

#define ICM20_PWR_MGMT_2 0x6C

#define ICM20_FIFO_COUNTH 0x72

#define ICM20_FIFO_COUNTL 0x73

#define ICM20_FIFO_R_W 0x74

#define ICM20_WHO_AM_I 0x75

/* 加速度静态偏移 */

#define ICM20_XA_OFFSET_H 0x77

#define ICM20_XA_OFFSET_L 0x78

#define ICM20_YA_OFFSET_H 0x7A

#define ICM20_YA_OFFSET_L 0x7B

#define ICM20_ZA_OFFSET_H 0x7D

#define ICM20_ZA_OFFSET_L 0x7E

#endif

(二)icm20607.c文件编写

(1)头文件引用

#include <linux/module.h>

#include <linux/init.h>

#include <linux/fs.h>           // 包含文件系统相关函数的头文件

#include <linux/uaccess.h>      // 包含用户空间数据访问函数的头文件

#include <linux/cdev.h>         //包含字符设备头文件

#include <linux/device.h>

#include <linux/delay.h>

#include <linux/spi/spi.h>

#include <linux/regmap.h>

#include <linux/of.h>

#include <linux/of_address.h>

#include <linux/of_gpio.h>

#include "icm20607.h"

(2)创建相关宏定义和变量

#define ICM20607_REG_WHOAMI      0x75

#define ICM20607_WHOAMI_VALUE    0xAF

#define DEVICE_NAME "icm20607"  // 设备名称

static dev_t dev_num;   //分配的设备号

int major;  //主设备号

int minor;  //次设备号

struct icm20607_dev {

struct spi_device *spi_dev; /* spi设备 */

dev_t dev_num; /* 设备号  */

struct cdev cdev; /* cdev */

struct class *class; /* 类 */

struct device *device; /* 设备  */

struct device_node *nd; /* 设备节点 */

int cs_gpio; /* 片选所使用的GPIO编号 */

signed int gyro_x_adc; /* 陀螺仪X轴原始值  */

signed int gyro_y_adc; /* 陀螺仪Y轴原始值 */

signed int gyro_z_adc; /* 陀螺仪Z轴原始值 */

signed int accel_x_adc; /* 加速度计X轴原始值 */

signed int accel_y_adc; /* 加速度计Y轴原始值 */

signed int accel_z_adc; /* 加速度计Z轴原始值 */

signed int temp_adc; /* 温度原始值 */

struct regmap *spi_regmap; /* regmap */

struct regmap_config regmap_config;

};

(3)驱动模块的入口和出口

module_init(icm20607_init);

module_exit(icm20607_exit);

(4)icm20607_init和icm20607_exit实现

static int __init icm20607_init(void)

{

int ret;

ret = spi_register_driver(&icm20607_driver);

if (ret < 0) {

pr_err("Failed to register ICM20607 driver: %dn", ret);

return ret;

}

pr_info("ICM20607 SPI device driver loadedn");

return 0;

}

static void __exit icm20607_exit(void)

{

spi_unregister_driver(&icm20607_driver);

pr_info("ICM20607 SPI device driver unloadedn");

}

在入口函数中调用了spi_register_driver函数,来注册SPI总线驱动程序。在出口函数中调用了spi_unregister_driver函数,来注销驱动程序。

spi_register_driver函数原型如下:

int spi_register_driver(struct spi_driver *drv);

该函数接受一个指向struct spi_driver结构体的指针作为参数,并返回一个整数值,表示注册是否成功。struct spi_driver结构体定义了SPI总线驱动程序的属性和回调函数。

以下是struct spi_driver结构体的常见成员:

driver:struct device_driver类型的成员,描述了驱动程序的基本信息,如名称、总线类型等。

probe:指向驱动程序的探测函数的指针。探测函数在与设备匹配时被调用,用于初始化设备并注册相关资源。

remove:指向驱动程序的移除函数的指针。移除函数在设备被卸载时被调用,用于清理和释放相关资源。

id_table:指向struct spi_device_id数组的指针,用于匹配驱动程序和设备之间的关联关系。

probe_new:指向新版的探测函数的指针。新版探测函数支持更多功能,并可以替代旧版的probe函数。

remove_new:指向新版的移除函数的指针。新版移除函数支持更多功能,并可以替代旧版的remove函数。

通过调用spi_register_driver函数并传入正确配置的struct spi_driver结构体,可以将SPI总线驱动程序注册到Linux内核,使其能够接收和处理SPI设备的相关操作。

(5)spi_driver类型结构体定义

static struct spi_driver icm20607_driver = {

.driver = {

.name = "icm20607",

.owner = THIS_MODULE,

.of_match_table = icm20607_of__match,

},

.probe = icm20607_probe,

.remove = icm20607_remove,

};

(6)icm20607_of__match实现,用来与设备树中的compatible匹配

static const struct of_device_id icm20608_of_match[] = {

{ .compatible = "icm20607" },

{ /* Sentinel */ }

};

(7)remove函数实现,执行icm20607设备的清理操作

static int icm20607_remove(struct spi_device *spi)

{

struct icm20607_dev *icm20607dev = spi_get_drvdata(spi);

// 在此处执行 ICM20607 设备的清理操作

//删除cdev

cdev_del(&icm20607dev->cdev);

//注销设备号

unregister_chrdev_region(icm20607dev->dev_num, 1);

//注销设备

device_destroy(icm20607dev->class, icm20608dev->dev_num);

//注销类

class_destroy(icm20607dev->class);

//删除regmap

regmap_exit(icm20607dev->spi_regmap);

pr_info("ICM20607 SPI device removed successfullyn");

return 0;

}

(8)probe函数实现,此处简略描述regmap注册的过程:

static int icm20607_probe(struct spi_device *spi)

{

int ret;

unsigned int whoami;

struct icm20607_dev *icm20607dev;

//分配icm20607dev对象的空间

icm20607dev = devm_kzalloc(&spi->dev, sizeof(*icm20607dev), GFP_KERNEL);

if(!icm20607dev)

return -ENOMEM;

// 创建 ICM20607 设备的 regmap

icm20608dev->spi_regmap = regmap_init_spi(spi, &spi_regmap_config);

if (IS_ERR(icm20607dev->spi_regmap)) {

dev_err(&spi->dev, "Failed to initialize regmap: %ldn", PTR_ERR(icm20607dev->spi_regmap));

return PTR_ERR(icm20607dev->spi_regmap);

}

......

/*初始化spi_device */

icm20607dev->spi_dev = spi;

spi->mode = SPI_MODE_0;

spi_setup(spi);

/* 初始化ICM20607内部寄存器 */

icm20607_reginit(icm20607dev);

/* 保存icm20607dev结构体 */

spi_set_drvdata(spi, icm20607dev);

pr_info("ICM20607 SPI device probed successfullyn");

return 0;

}

probe函数中首先使用devm_kzalloc函数分配了icm20607dev的结构体空间,然后使用regmap_init_spi函数创建regmap实例,再进行spi控制器的初始化和配置,最后对ICM20607的内部寄存器进行配置。

其中regmap_init_spi函数中传入了“&spi_regmap_config”参数,前边有提到这个是用来配置regmap对象的,下边我们看这个参数是如何定义的。

(9)spi_regmap_config的定义

static const struct regmap_config spi_regmap_config = {

.reg_bits = 8,

.val_bits = 8,

.read_flag_mask = 0x80,

.reg_read = icm20607_spi_read,

.reg_write = icm20607_spi_write,

.max_register = ICM20607_REG_WHOAMI,

};

可以看到这其中规定了寄存器地址的位数,存储寄存器的位数,读寄存器掩码,读寄存器函数,写寄存器函数,最大寄存器地址。

(10)读写寄存器函数实现

static int icm20607_spi_read(struct icm20608_dev *dev, unsigned int reg, unsigned int *val)

{

return regmap_read(dev->spi_regmap, reg, val);

}

static int icm20607_spi_write(struct icm20608_dev *dev, unsigned int reg, unsigned int val)

{

return regmap_write(dev->spi_regmap, reg, val);

}

可以看出读写函数非常简单明了,直接使用regmap_read和regmap_write函数即可。

①regmap_read函数原型如下:

int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val);

该函数用于从给定的寄存器地址(reg)读取数据,并将读取的值存储在val指向的变量中。map参数是一个指向struct regmap的指针,表示寄存器映射对象。返回值为0表示读取成功,否则表示读取失败。

②regmap_write函数原型如下:

int regmap_write(struct regmap *map, unsigned int reg, unsigned int val);

该函数用于向给定的寄存器地址(reg)写入数据(val)。map参数是一个指向struct regmap的指针,表示寄存器映射对象。返回值为0表示写入成功,否则表示写入失败。

三、完整驱动icm20607.c示例源码

#include <linux/module.h>

#include <linux/init.h>

#include <linux/fs.h>           // 包含文件系统相关函数的头文件

#include <linux/uaccess.h>      // 包含用户空间数据访问函数的头文件

#include <linux/cdev.h>         //包含字符设备头文件

#include <linux/device.h>

#include <linux/delay.h>

#include <linux/spi/spi.h>

#include <linux/regmap.h>

#include <linux/of.h>

#include <linux/of_address.h>

#include <linux/of_gpio.h>

#include "icm20607.h"

#define ICM20607_REG_WHOAMI      0x75

#define ICM20607_WHOAMI_VALUE    0xAF

#define DEVICE_NAME "icm20607"  // 设备名称

static dev_t dev_num;   //分配的设备号

int major;  //主设备号

int minor;  //次设备号

struct icm20607_dev {

struct spi_device *spi_dev;     /* spi设备 */

dev_t dev_num;                  /* 设备号*/

struct cdev cdev;               /* cdev */

struct class *class;            /* 类*/

struct device *device;          /* 设备 */

struct device_node      *nd;    /* 设备节点 */

int cs_gpio;                            /* 片选所使用的GPIO编号 */

signed int gyro_x_adc;          /* 陀螺仪X轴原始值*/

signed int gyro_y_adc;          /* 陀螺仪Y轴原始值*/

signed int gyro_z_adc;          /* 陀螺仪Z轴原始值*/

signed int accel_x_adc;         /* 加速度计X轴原始值*/

signed int accel_y_adc;         /* 加速度计Y轴原始值*/

signed int accel_z_adc;         /* 加速度计Z轴原始值*/

signed int temp_adc;            /* 温度原始值*/

struct regmap *spi_regmap;              /* regmap */

struct regmap_config regmap_config;

};

void icm20607_readdata(struct icm20607_dev *dev)

{

u8 ret;

unsigned char data[14];

ret = regmap_bulk_read(dev->spi_regmap, ICM20_ACCEL_XOUT_H, data, 14);/*读多个寄存器的值*/

dev->accel_x_adc = (signed short)((data[0] << 8) | data[1]);

dev->accel_y_adc = (signed short)((data[2] << 8) | data[3]);

dev->accel_z_adc = (signed short)((data[4] << 8) | data[5]);

dev->temp_adc    = (signed short)((data[6] << 8) | data[7]);

dev->gyro_x_adc  = (signed short)((data[8] << 8) | data[9]);

dev->gyro_y_adc  = (signed short)((data[10] << 8) | data[11]);

dev->gyro_z_adc  = (signed short)((data[12] << 8) | data[13]);

}

static int icm20607_spi_read(struct icm20607_dev *dev, unsigned int reg, unsigned int *val)

{

return regmap_read(dev->spi_regmap, reg, val);

}

static int icm20607_spi_write(struct icm20607_dev *dev, unsigned int reg, unsigned int val)

{

return regmap_write(dev->spi_regmap, reg, val);

}

static const struct regmap_config spi_regmap_config = {

.reg_bits = 8,

.val_bits = 8,

.read_flag_mask = 0x80,

.reg_read = icm20607_spi_read,

.reg_write = icm20607_spi_write,

.max_register = ICM20607_REG_WHOAMI,

};

static int device_open(struct inode *inode, struct file *file)

{

// 在这里处理设备打开的操作

printk(KERN_INFO "This is device_open.n");

return 0;

}

static int device_release(struct inode *inode, struct file *file)

{

// 在这里处理设备关闭的操作

printk(KERN_INFO "This is device_release.n");

return 0;

}

static ssize_t device_read(struct file *file, char __user *buffer, size_t length, loff_t *offset)

{

signed int data[7];

long err = 0;

struct cdev *cdev = file->f_path.dentry->d_inode->i_cdev;

struct icm20607_dev *dev = container_of(cdev, struct icm20607_dev, cdev);

icm20607_readdata(dev);

data[0] = dev->gyro_x_adc;

data[1] = dev->gyro_y_adc;

data[2] = dev->gyro_z_adc;

data[3] = dev->accel_x_adc;

data[4] = dev->accel_y_adc;

data[5] = dev->accel_z_adc;

data[6] = dev->temp_adc;

err = copy_to_user(buffer, data, sizeof(data));

return 0;

}

static ssize_t device_write(struct file *file, const char __user *buffer, size_t length, loff_t *offset)

{

// 在这里处理设备写入的操作

printk(KERN_INFO "This is device_write.n");

return 0;

}

void icm20607_reginit(struct icm20607_dev *dev)

{

u8 value = 0;

icm20607_spi_write(dev, ICM20_PWR_MGMT_1, 0x80);

mdelay(50);

icm20607_spi_write(dev, ICM20_PWR_MGMT_1, 0x01);

mdelay(50);

icm20607_spi_read(dev, ICM20_WHO_AM_I,&value);

printk("ICM20607 ID = %#Xrn", value);

icm20607_spi_write(dev, ICM20_SMPLRT_DIV, 0x00);      /* 输出速率是内部采样率*/

icm20607_spi_write(dev, ICM20_GYRO_CONFIG, 0x18);      /* 陀螺仪±2000dps量程 */

icm20607_spi_write(dev, ICM20_ACCEL_CONFIG, 0x18);     /* 加速度计±16G量程*/

icm20607_spi_write(dev, ICM20_CONFIG, 0x04);            /* 陀螺仪低通滤波BW=20Hz */

icm20607_spi_write(dev, ICM20_ACCEL_CONFIG2, 0x04); /* 加速度计低通滤波BW=21.2Hz */

icm20607_spi_write(dev, ICM20_PWR_MGMT_2, 0x00);        /* 打开加速度计和陀螺仪所有轴*/

icm20607_spi_write(dev, ICM20_LP_MODE_CFG, 0x00);       /* 关闭低功耗*/

icm20607_spi_write(dev, ICM20_FIFO_EN, 0x00);           /* 关闭FIFO */

}

static struct file_operations fops = {

.owner = THIS_MODULE,

.open = device_open,

.release = device_release,

.read = device_read,

.write = device_write,

};

static int icm20607_probe(struct spi_device *spi)

{

int ret;

unsigned int whoami;

struct icm20607_dev *icm20607dev;

/* 分配icm20607dev对象的空间 */

icm20607dev = devm_kzalloc(&spi->dev, sizeof(*icm20607dev), GFP_KERNEL);

if(!icm20607dev)

return -ENOMEM;

// 创建 ICM20607 设备的 regmap

icm20607dev->spi_regmap = regmap_init_spi(spi, &spi_regmap_config);

if (IS_ERR(icm20607dev->spi_regmap)) {

dev_err(&spi->dev, "Failed to initialize regmap: %ldn", PTR_ERR(icm20607dev->spi_regmap));

return PTR_ERR(icm20607dev->spi_regmap);

}

// 注册字符设备驱动程序

ret = alloc_chrdev_region(&icm20607dev->dev_num,0,1,DEVICE_NAME);

if (ret < 0) {

printk(KERN_ALERT "Failed to allocate device number: %dn", ret);

return ret;

}

major=MAJOR(icm20607dev->dev_num);

minor=MINOR(icm20607dev->dev_num);

printk(KERN_INFO "major number: %dn",major);

printk(KERN_INFO "minor number: %dn",minor);

icm20607dev->cdev.owner = THIS_MODULE;

cdev_init(&icm20607dev->cdev,&fops);

cdev_add(&icm20607dev->cdev,icm20607dev->dev_num,1);

// 创建设备类

icm20607dev->class = class_create(THIS_MODULE, DEVICE_NAME);

if (IS_ERR(icm20607dev->class)) {

pr_err("Failed to create classn");

return PTR_ERR(icm20607dev->class);

}

// 创建设备节点并关联到设备类

icm20607dev->device = device_create(icm20607dev->class, NULL, MKDEV(major, minor), NULL, DEVICE_NAME);

if (IS_ERR(icm20607dev->device)) {

pr_err("Failed to create devicen");

class_destroy(icm20607dev->class);

return PTR_ERR(icm20607dev->device);

}

/*初始化spi_device */

icm20607dev->spi_dev = spi;

spi->mode = SPI_MODE_0;

spi_setup(spi);

/* 初始化ICM20607内部寄存器 */

icm20607_reginit(icm20607dev);

/* 保存icm20607dev结构体 */

spi_set_drvdata(spi, icm20607dev);

pr_info("ICM20607 SPI device probed successfullyn");

return 0;

}

static int icm20607_remove(struct spi_device *spi)

{

struct icm20607_dev *icm20607dev = spi_get_drvdata(spi);

// 在此处执行 ICM20607 设备的清理操作

//删除cdev

cdev_del(&icm20607dev->cdev);

//注销设备号

unregister_chrdev_region(icm20607dev->dev_num, 1);

//注销设备

device_destroy(icm20607dev->class, icm20607dev->dev_num);

//注销类

class_destroy(icm20607dev->class);

//删除regmap

regmap_exit(icm20607dev->spi_regmap);

pr_info("ICM20607 SPI device removed successfullyn");

return 0;

}

static const struct of_device_id icm20607_of__match[] = {

{ .compatible = "icm20607", },

{},

};

static struct spi_driver icm20607_driver = {

.driver = {

.name = "icm20607",

.owner = THIS_MODULE,

.of_match_table = icm20607_of__match,

},

.probe = icm20607_probe,

.remove = icm20607_remove,

};

static int __init icm20607_init(void)

{

int ret;

ret = spi_register_driver(&icm20607_driver);

if (ret < 0) {

pr_err("Failed to register ICM20607 driver: %dn", ret);

return ret;

}

pr_info("ICM20607 SPI device driver loadedn");

return 0;

}

static void __exit icm20607_exit(void)

{

spi_unregister_driver(&icm20607_driver);

pr_info("ICM20607 SPI device driver unloadedn");

}

module_init(icm20607_init);

module_exit(icm20607_exit);

MODULE_LICENSE("GPL");

MODULE_AUTHOR("Your Name");

MODULE_DESCRIPTION("ICM20607 SPI device driver");

四、编译

Makefile修改如下:

. /opt/fsl-imx-x11/4.1.15-2.0.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi

elf@ubuntu:~/work/test/09_Regmap子系统-icm20607/icm20607$ make

将编译生成的icm20607.ko模块拷贝到开发板。

五、编写测试源码icm20607_app.c

测试源码中循环读取驱动传到用户空间的数据:

#include "stdio.h"

#include "unistd.h"

#include "sys/types.h"

#include "sys/stat.h"

#include "sys/ioctl.h"

#include "fcntl.h"

#include "stdlib.h"

#include "string.h"

#include <poll.h>

#include <sys/select.h>

#include <sys/time.h>

#include <signal.h>

#include <fcntl.h>

#define ICM20607_DEV "/dev/icm20607"

int main(int argc, char *argv[])

{

int fd;

signed int databuf[7];

unsigned char data[14];

signed int gyro_x_adc, gyro_y_adc, gyro_z_adc;

signed int accel_x_adc, accel_y_adc, accel_z_adc;

signed int temp_adc;

float gyro_x_act, gyro_y_act, gyro_z_act;

float accel_x_act, accel_y_act, accel_z_act;

float temp_act;

int ret = 0;

fd = open(ICM20607_DEV, O_RDWR);

if(fd < 0) {

printf("can't open file %srn", ICM20607_DEV);

return -1;

}

while (1) {

ret = read(fd, databuf, sizeof(databuf));

if(ret == 0) { /*读取出原始值 */

gyro_x_adc = databuf[0];

gyro_y_adc = databuf[1];

gyro_z_adc = databuf[2];

accel_x_adc = databuf[3];

accel_y_adc = databuf[4];

accel_z_adc = databuf[5];

temp_adc = databuf[6];

/* 转换为实际值 */

gyro_x_act = (float)(gyro_x_adc)  / 16.4;

gyro_y_act = (float)(gyro_y_adc)  / 16.4;

gyro_z_act = (float)(gyro_z_adc)  / 16.4;

accel_x_act = (float)(accel_x_adc) / 2048;

accel_y_act = (float)(accel_y_adc) / 2048;

accel_z_act = (float)(accel_z_adc) / 2048;

temp_act = ((float)(temp_adc) - 25 ) / 326.8 + 25;

printf("rn");

printf("raw value:rn");

printf("gx = %d, gy = %d, gz = %drn", gyro_x_adc, gyro_y_adc, gyro_z_adc);

printf("ax = %d, ay = %d, az = %drn", accel_x_adc, accel_y_adc, accel_z_adc);

printf("temp = %drn", temp_adc);

printf("rn");

printf("act value:rn");

printf("act gx = %.2f度/S, act gy = %.2f度/S, act gz = %.2f度/Srn", gyro_x_act, gyro_y_act, gyro_z_act);

printf("act ax = %.2fg, act ay = %.2fg, act az = %.2fgrn", accel_x_act, accel_y_act, accel_z_act);

printf("act temp = %.2f摄氏度rn", temp_act);

}

usleep(100000); /*100ms */

}

close(fd);

return 0;

}

六、编译应用

. /opt/fsl-imx-x11/4.1.15-2.0.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi

elf@ubuntu:~/work/test/09_Regmap子系统-icm20607/icm20607_app$ $CC icm20607_app.c -o icm20607_app

将编译好的测试应用拷贝到开发板。

七、测试

root@ELF1:~#:~# insmod elf-icm20607.ko

major number: 249

minor number: 0

ICM20607 ID = 0X0

ICM20607 SPI device probed successfully

ICM20607 SPI device driver loaded

root@ELF1:~#:~# ./icm20607_app

This is device_open.

raw value:

gx = 0, gy = 0, gz = 0

ax = 0, ay = 0, az = 0

temp = 0

act value:

act gx = 0.00度/S, act gy = 0.00度/S, act gz = 0.00度/S

act ax = 0.00g, act ay = 0.00g, act az = 0.00g

act temp = 24.92摄氏度

可以看到测试app将六轴传感器的原始值和转换后的值打印了出来。

相关推荐