SPI驱动icm20608的实验

news/2024/7/7 14:33:12

文章目录

  • 一、设备树
  • 二、驱动程序
  • 三、应用程序
  • 四、测试

一、设备树

在pinctrl节点中添加:

	/* spi驱动  icm20608 */
	pinctrl_ecspi3: icm20608 {
			fsl,pins = <
				MX6UL_PAD_UART2_TX_DATA__GPIO1_IO20 0x10b0 /* CS */   /* 只是一个普通的GPIO */
				MX6UL_PAD_UART2_RX_DATA__ECSPI3_SCLK 0x10b1 /* SCLK */
				MX6UL_PAD_UART2_RTS_B__ECSPI3_MISO 0x10b1 /* MISO */
				MX6UL_PAD_UART2_CTS_B__ECSPI3_MOSI 0x10b1 /* MOSI */
			>;
	};

在这里插入图片描述

在最后添加:

 &ecspi3 {
		fsl,spi-num-chipselects = <1>;   /* 当前片选数量为1  因为只接了一个设备*/
		cs-gpio = <&gpio1 20 GPIO_ACTIVE_LOW>; 
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_ecspi3>;
		status = "okay";

		/* icm20608 */
		icm20608: icm20608@0 {    /* 连接在spi3 的 第0个通道上 */
		compatible = "luatao,icm20608";
		spi-max-frequency = <8000000>;  /* 最大时钟频率为8MHz*/
		reg = <0>;
	};

在这里插入图片描述

二、驱动程序

icm20608.h

#ifndef ICM20608_H
#define ICM20608_H

/* 不同型号的id*/
#define ICM20608G_ID             0xAF     /* ID值 */
#define ICM20608D_ID			0XAE	/* ID值 */


/* 陀螺仪和加速度自测(出产时设置,用于与用户的自检输出值比较) */
#define	ICM20_SELF_TEST_X_GYRO		0x00
#define	ICM20_SELF_TEST_Y_GYRO		0x01
#define	ICM20_SELF_TEST_Z_GYRO		0x02
#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

icm20608.c

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>

#include <linux/errno.h>
#include <linux/gpio.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>

#include <linux/cdev.h>

#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>

#include <linux/of_gpio.h>

#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include "icm20608.h"


/**
 * file name:icm20608
 * date: 2021-08-15  20:11
 * version:1.0
 * author:luatao
 * describe:icm20608 device drive
 */


#define ICM20608_CNT  1     /* 设备号个数 */
#define ICM20608_NAME        "icm20608"      /* 设备名*/


/* 设备结构体 自定义 */
struct icm20608_dev{
    dev_t devid;     /*设备号  */
    struct cdev cdev;  /* cdev */
    struct class *class;  /* 类*/
    struct device *device;  /* 设备 */
    int major;   /* 主设备号 */
    int minor;  /* 次设备号 */

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

    void *private_date;  /* 私有数据 */
    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;        /* 温度原始值 */
 };

/* 定义一个设备结构体 */
static struct icm20608_dev icm20608;   /*icm20608 设备 */

/* 从icm20608读取多个寄存器数据 
 @param - *dev        : ap3216设备 
 @param - reg           : 要读取的寄存器首地址
 @param - *val         : 读取到的数据 
 @param - len          : 要读取的数据长度 
 @return                    :操作结果
*/
static int icm20608_read_regs(struct icm20608_dev *dev, u8 reg, void *val, int len)
{
    int ret = 0;
    unsigned char txdata[len];   /* 发送数据 */
    struct spi_message m;  /* 发送的消息结构体  */
    struct spi_transfer *t;  /* 传输结构体  */
    struct spi_device *client = (struct spi_device *)dev->private_date;  /* 私有数据 */

    gpio_set_value(dev->cs_gpio, 0);  /* 片选拉低 选中icm20608 */
    t = kzalloc(sizeof(struct spi_transfer), GFP_KERNEL);  /* 申请内存 */

    /* 第1次 发送要读取的寄存器地址 */
    txdata[0] = reg | 0x80;  /* 写数据的时候寄存器地址 bit7 要置1 */
    t->tx_buf = txdata;  /* 要发送的数据 */
    t->len = 1;  /* 1个字节 */
    spi_message_init(&m);  /* 初始化 spi_message */
    spi_message_add_tail(t, &m);  /* 将 spi_transfer 添加到spi_message */
    ret = spi_sync(client, &m);  /* 同步发送 */

    /* 第2次 读取数据 */
    txdata[0] = 0xff;  /* 随便一个值, 此处无意义 */
    t->rx_buf = val;  /* 读取到的数据 */
    t->len = len; /* 要读取的数据长度 */
    spi_message_init(&m); /* 初始化 spi_message */
    spi_message_add_tail(t, &m);  /* 将 spi_transfer 添加到spi_message */
    ret = spi_sync(client, &m);  /* 同步发送 */

    kfree(t);  /* 释放内存 */
    gpio_set_value(dev->cs_gpio, 1);  /* 片选拉高 释放icm20608*/

    return ret;
}

/* 从icm20608多个寄存器写入数据 
 @param - *dev        : ap3216设备 
 @param - reg           : 要写入的寄存器首地址
 @param - *buf         : 写入的数据缓冲区
 @param - len          : 要写入的数据长度 
 @return                    :操作结果
*/
static s32 icm20608_write_regs(struct icm20608_dev *dev, u8 reg, void *buf, int len)
{
    int ret = 0;
    unsigned char txdata[len];  /* 发送数据缓冲区*/
    struct spi_message m;  /* 发送的消息结构体  */
    struct spi_transfer *t;  /* 传输结构体  */
    struct spi_device *client = (struct spi_device *)dev->private_date;  /* 私有数据 */

    gpio_set_value(dev->cs_gpio, 0);  /* 片选拉低 选中icm20608 */
    t = kzalloc(sizeof(struct spi_transfer), GFP_KERNEL);  /* 申请内存 */

    /* 第1次 发送要读取的寄存器地址 */
    txdata[0] = reg & ~0x80;  /* 写数据的时候寄存器地址 bit7 要清零 */
    t->tx_buf = txdata;  /* 要发送的数据 */
    t->len = 1;  /* 1个字节 */
    spi_message_init(&m);  /* 初始化 spi_message */
    spi_message_add_tail(t, &m);  /* 将 spi_transfer 添加到spi_message */
    ret = spi_sync(client, &m);  /* 同步发送 */

     /* 第2次 发送要写入的数据 */
    t->tx_buf = buf;  /* 要写入的数据 */
    t->len = len;  /* 写入的字节数  */
    spi_message_init(&m);  /* 初始化 spi_message */
    spi_message_add_tail(t, &m);  /* 将 spi_transfer 添加到spi_message */
    ret = spi_sync(client, &m);  /* 同步发送 */

     kfree(t);  /* 释放内存 */
    gpio_set_value(dev->cs_gpio, 1);  /* 片选拉高 释放icm20608*/

    return ret;
}

/* 从icm20608读取指定寄存器值 读取一个寄存器
 @param - *dev        : ap3216设备 
 @param - reg           : 要读取的寄存器
 @return                    :读取到的寄存器值
*/
static unsigned char  icm20608_read_reg(struct icm20608_dev *dev, u8 reg)
{
    u8 data = 0;
    icm20608_read_regs(dev, reg, &data, 1);
    return data; 
}

/* 向icm20608指定寄存器写入指定的值,写一个寄存器 
 @param - *dev        : ap3216设备 
 @param - reg           : 要写入的寄存器
 @param - data         : 要写入的值 
 @return                    :无
*/
static void icm20608_write_reg(struct icm20608_dev *dev, u8 reg, u8 data)
{
    u8 buf = data;
	icm20608_write_regs(dev, reg, &buf, 1);  /* 调用写入多个寄存器的方法 */
}

/* 读取icm20608的数据 读取原始数据  包括三轴陀螺仪  三轴加速度计 和 内部温度
 @param - *dev        : ap3216设备 
 @return                    :无
*/
static void icm20608_readdata(struct icm20608_dev *dev)
{
	unsigned char buf[14];  /* 读取的数据缓冲区 */

    /* 读取 14 个数据 */
    icm20608_read_regs(dev, ICM20_ACCEL_XOUT_H, buf, 14);

    /* 处理数据 */
    dev->accel_x_adc =  (signed short)((buf[0] << 8) | buf[1]); 
    dev->accel_y_adc =  (signed short)((buf[2] << 8) | buf[3]); 
    dev->accel_z_adc =  (signed short)((buf[4] << 8) | buf[5]); 

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

    dev->gyro_x_adc =  (signed short)((buf[8] << 8) | buf[9]); 
    dev->gyro_y_adc =  (signed short)((buf[10] << 8) | buf[11]); 
    dev->gyro_z_adc =  (signed short)((buf[12] << 8) | buf[13]); 

}

/* 内部寄存器初始化函数 */
void icm20608_reginit(void)
{
    u8 value = 0;

    icm20608_write_reg(&icm20608, ICM20_PWR_MGMT_1, 0x80);
    mdelay(50);
    icm20608_write_reg(&icm20608, ICM20_PWR_MGMT_1, 0x01);
    mdelay(50);

    value = icm20608_read_reg(&icm20608, ICM20_WHO_AM_I);
    printk("ICM20608 ID = %#X\r\n", value);

    icm20608_write_reg(&icm20608, ICM20_SMPLRT_DIV, 0x00);
    icm20608_write_reg(&icm20608, ICM20_GYRO_CONFIG, 0x18);
    icm20608_write_reg(&icm20608, ICM20_ACCEL_CONFIG, 0x18);
    icm20608_write_reg(&icm20608, ICM20_CONFIG, 0x04);
    icm20608_write_reg(&icm20608, ICM20_ACCEL_CONFIG2, 0x04);
    icm20608_write_reg(&icm20608, ICM20_PWR_MGMT_2, 0x00);
    icm20608_write_reg(&icm20608, ICM20_LP_MODE_CFG, 0x00);
    icm20608_write_reg(&icm20608, ICM20_FIFO_EN, 0x00);
}

/* 打开设备 */
static int icm20608_open(struct inode *inode, struct file *filp)
{
    filp->private_data = &icm20608;  /* 设置私有数据 */

    return 0;
}

/* 从设备读取数据 */
static ssize_t icm20608_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{
    signed int  data[7];  /* 存放读取到的数据 */
    long ret = 0;

    struct icm20608_dev *dev = filp->private_data;  // 获取私有数据 

    icm20608_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;

    ret = copy_to_user(buf, data, sizeof(data));  // 发送给用户空间  

    return 0;
}

/* 往设备写数据 */
static ssize_t icm20608_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{
    printk("no write operation!\r\n");
    return 0;
}

/* 释放设备 */
static int icm20608_release(struct inode *inode, struct file *filp)
{
    //printk("icm20608 release!\r\n");
    return 0;
}


/* 设备操作函数结构体  */
static struct file_operations icm20608_fops = {
    .owner = THIS_MODULE,
    .open =icm20608_open,
    .read =icm20608_read,
    .write =icm20608_write,
    .release =icm20608_release,
};

/* spi驱动的probe函数 ,当驱动与设备匹配以后此函数就会执行 */
static int icm20608_probe(struct spi_device *client)
{
    int ret = 0;
    printk("icm20608 driver and device has match!\r\n");  // 提示信息 

    /* 1. 创建设备号 */
    if(icm20608.major){  // 定义了设备号 
        icm20608.devid = MKDEV(icm20608.major, 0 );  // 根据主设备号和次设备号合成设备号 
        register_chrdev_region(icm20608.devid, ICM20608_CNT, ICM20608_NAME);  // 注册设备号 
    }else{  // 没有定义设备号 动态生成 
        alloc_chrdev_region(&icm20608.devid,0,ICM20608_CNT, ICM20608_NAME ); // 申请设备号
        icm20608.major = MAJOR(icm20608.devid);  // 获取主设备号
        icm20608.minor = MINOR(icm20608.devid);  // 获取次设备号
    }
    printk("icm20608 major = %d,minor = %d\r\n",icm20608.major, icm20608.minor);  // 打印主设备号和次设备号

    /* 2. 初始化 cdev */
    icm20608.cdev.owner = THIS_MODULE;  
    cdev_init(&icm20608.cdev, &icm20608_fops);  // 初始化cdev
    /* 3. 添加cdev */
    cdev_add(&icm20608.cdev, icm20608.devid, ICM20608_CNT ); // 向linux系统添加cdev

     /* 自动创建设备节点文件 */
    /* 4. 创建类 */
    icm20608.class = class_create(THIS_MODULE, ICM20608_NAME);  // 创建类 
    if(IS_ERR(icm20608.class)){
        return PTR_ERR(icm20608.class);
    }
    /* 创建设备 */
    icm20608.device = device_create(icm20608.class, NULL, icm20608.devid, NULL, ICM20608_NAME);
      if(IS_ERR(icm20608.device)){
        return PTR_ERR(icm20608.device);
    }


    /* 获取设备树中的 spi  节点*/
     /* 1. 获取设备节点 */
    icm20608.nd = of_find_node_by_path("/soc/aips-bus@02000000/spba-bus@02000000/ecspi@02010000");  // 通过绝对路径查找设备节点
    if(icm20608.nd == NULL){
        printk("ecspi3 node no find!\r\n");
        return -EINVAL;  /* 无效参数 不知道这个返回值是啥意思,我觉得返回一个负数就可以,这个值是23,不知道有没有处理*/
    }

    /* 2. 获取设备树中的gpio属性 得到cs片选所使用的gpio编号 */
    icm20608.cs_gpio = of_get_named_gpio(icm20608.nd, "cs-gpio", 0);  // 最后一个参数用于指定下标
    if(icm20608.cs_gpio < 0 ){
         printk("can't get cs-gpio\r\n");
        return -EINVAL;  /* 无效参数 不知道这个返回值是啥意思,我觉得返回一个负数就可以,这个值是23,不知道有没有处理*/
    }
    printk("cs-gpio num = %d \r\n", icm20608.cs_gpio);  // 打印获取的cs-gpio属性值

    /* 申请 IO */
    ret = gpio_request(icm20608.cs_gpio, "cs0'");
    if(ret < 0){
        printk("request gpio failed!\r\n");
    }
    /* 3. 设置GPIO1_IO03为输出,并且输出高电平,默认关闭cs灯 */
    ret = gpio_direction_output(icm20608.cs_gpio, 1);
    if(ret < 0){
        printk("can't set gpio!\r\n");
    }

    /* 初始化 spi_device*/
    client->mode = SPI_MODE_0;   /* MODE0,  CPOL=0,CPHA=0*/
    spi_setup(client);
    icm20608.private_date = client;  /* 私有数据为当前设备 */

    /* 初始化 icm20608 内部寄存器 */
    icm20608_reginit(); 

    return 0;
}

/* spi驱动后的remove函数 */
static int icm20608_remove(struct spi_device *client)
{

      /*  注销设备驱动 */
    cdev_del(&icm20608.cdev);  /* 删除 cdev */
    unregister_chrdev_region(icm20608.devid, ICM20608_CNT ); /* 注销设备号 */

    device_destroy(icm20608.class, icm20608.devid);  /* 注销设备  */
    class_destroy(icm20608.class);  /* 注销类 */


    printk("icm20608 drive unregsister ok !\r\n");
    return 0;
}

/* 传统匹配方式ID列表 */
static const struct spi_device_id icm20608_id[] = {
    {"luatao,icm20608", 0},
    {}
};
/* 匹配列表 */
static const struct of_device_id icm20608_of_match[] = {
    {.compatible = "luatao,icm20608"},
    {/* Sentinel */}
};

/* spi驱动结构体 */
static struct spi_driver icm20608_driver = {
        .driver = {
            .owner = THIS_MODULE,
            .name = "icm20608",   /* 驱动名字 用于和设备匹配  适用于没有设备树的情况*/
            .of_match_table =icm20608_of_match,  /* 设备树匹配列表 */
        },
        .probe =icm20608_probe,
        .remove =icm20608_remove,
        .id_table = icm20608_id, /* id配置列表 */
};

/* 驱动入口函数 */
static int __init icm20608_init(void)
{
    return spi_register_driver(&icm20608_driver);
}

/* 驱动出口函数 */
static void __exit icm20608_exit(void)
{
   spi_unregister_driver(&icm20608_driver);
}

/* 加载驱动入口和出口函数 */
module_init(icm20608_init);
module_exit(icm20608_exit);

/* LICENSE 和 AUTHOR 信息*/
MODULE_LICENSE("GPL");
MODULE_AUTHOR("luatao");

三、应用程序

icm20608App.c

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>

/**
 * file name:icm20608App
 * date: 2021-08-15  21:21
 * version:1.0
 * author:luatao
 * describe:icm20608测试APP
 * 执行命令:./icm20608App 读取按键值 
 */


/* 主程序 */
int main(int argc, char *argv[])
{
    char *filename;  // 可执行文件名
    int fd,ret = 0;  //  fd: 文件句柄 ret:函数操作返回值
    unsigned short databuf[7];  // 读出来的数据 
    signed int gyro_x_adc, gyro_y_adc, gyro_z_adc,   accel_x_adc, accel_y_adc, accel_z_adc,  temp_adc;  // 实际的数据 
    float gyro_x_act, gyro_y_act, gyro_z_act,   accel_x_act, accel_y_act, accel_z_act,  temp_act;  // 实际的数据 浮点数

    /* 先判断输入的参数 */
    if(argc !=  2){  // 本身文件名带1个 执行文件1个  
       printf("parameter error!\r\n");
       return -1;
    }

    /* 分析参数 ,提取有用的信息 */
    filename = argv[1];  // 可执行文件名 
    
    /* 打开key文件 */
    fd = open(filename, O_RDWR);  // 可读可写 
    if(fd < 0){
        printf("can't open file:%s\r\n",filename);
        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_x_act = (float)(accel_x_adc) / 2048; 
            accel_x_act = (float)(accel_x_adc) / 2048; 

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

            printf("\r\n原始值:\r\n");
			printf("gx = %d, gy = %d, gz = %d\r\n", gyro_x_adc, gyro_y_adc, gyro_z_adc);
			printf("ax = %d, ay = %d, az = %d\r\n", accel_x_adc, accel_y_adc, accel_z_adc);
			printf("temp = %d\r\n", temp_adc);

			printf("实际值:");
			printf("act gx = %.2f°/S, act gy = %.2f°/S, act gz = %.2f°/S\r\n", gyro_x_act, gyro_y_act, gyro_z_act);
			printf("act ax = %.2fg, act ay = %.2fg, act az = %.2fg\r\n", accel_x_act, accel_y_act, accel_z_act);
			printf("act temp = %.2f°C\r\n", temp_act);
        }
        sleep(1);  /* 延时1s*/
    }

    /* 关闭文件 */
    ret = close(fd);
    if(ret < 0){
        printf("can't close file %s \r\n", filename);
        return -1;
    }

    return 0;
}
 

四、测试

加载驱动:
运行程序:
卸载驱动:
在这里插入图片描述
在这里插入图片描述


http://www.niftyadmin.cn/n/2205346.html

相关文章

uniapp picker时间选择器

//第一种 <picker change"bindPickerChange" :value"index" :range"appointList" range- key"centername"><view class"uni-input">{{appointList[index].centername}}</view></picker>bindPickerC…

linux UART(RS232/485)驱动实验

文章目录一、linux下的UART驱动框架1. uart_driver 注册与注销2. uart_port 的添加与移除3. uart_ops 实现二、6u UART驱动分析1. UART 的 的 platform 驱动框架2. uart_driver 初始化3. uart_port 初始化与添加4. imx_pops 结构体变量三、原理图分析四、RS232驱动编写1. UART3…

echarts - ajax请求举例1

let barYData [];topdatasFive.forEach((item) > {barYData.push({name: item.TopName,value: item.TopCount,});});

echarts问题解决tips

legend: {show: true, //是否显示type: "plain", // 图例的类型 plain:普通图例 scroll:可滚动翻页的图例zlevel: 1, // 所有图形的 zlevel 值。icon: "circle",top: "5%", // bottom:"20%" // 组件离容器的距离right: "5%"…

linux下多点电容触摸屏实验

文章目录一、linux下电容触摸屏驱动框架简介1. 多点触摸&#xff08;MT&#xff09;协议详解2. Type A触摸点信息上报时序3. Type B触摸点信息上报时序4. MT其他事件的使用5. 多点触摸所使用的API函数1. input_mt_init_slots 函数2. input_mt_slot 函数3. input_mt_report_slot…

vue数字滚动举例

export{Odometer }import { Odometer } from ../../assets/js/Odometervar num 4321; var odo1 new Odometer(".countup", {num: num, });

好家伙(心态崩了)

好家伙&#xff0c;写一个驱动写了一天&#xff0c; 今天从早上7点多开始就写这个驱动&#xff08;gt911多点触摸&#xff09;&#xff0c;先从网上找代码&#xff0c;然后按照步骤修改设备树&#xff0c;编译驱动&#xff0c;运行&#xff0c;驱动是行了&#xff0c;但是屏幕…

切换:class

<div class"winitem" v-for"(ite,index) in compid" click"changewin(ite.id,index);" :class"activeIndex index ? activeIndex:">{{ite.name}} </div>data&#xff1a; activeIndex: 0,