当前位置: 首页 > news >正文

手机建网站制作/百度官网网站

手机建网站制作,百度官网网站,营销策划的步骤有哪些,建材网站开发目录 概述 1 硬件接口 2 添加ICM20608的设备树信息 2.1 使用i.MX Pins Tool v6配置SPI引脚 2.2 配置设备树 2.3 编译.dts 2.4 在板卡中更新设备树 3 编写驱动程序 3.1 创建设备匹配表 3.2 重要函数介绍 3.2.1 初始化函数 3.2.2 写寄存器函数 3.2.3 读寄存器函数 …

目录

概述

1 硬件接口

2 添加ICM20608的设备树信息

2.1 使用i.MX Pins Tool v6配置SPI引脚

2.2 配置设备树

2.3 编译.dts 

2.4 在板卡中更新设备树

3 编写驱动程序

3.1 创建设备匹配表

3.2 重要函数介绍

3.2.1 初始化函数

3.2.2 写寄存器函数

3.2.3 读寄存器函数

3.2.3 完整驱动代码

3.2.3.1 驱动代码程序

3.2.3.1 驱动代码程序Makefile

4 测试驱动安装

4.1 编译驱动程序

4.2 在板卡上安装驱动

 5 验证和测试

5.1 编写测试程序

5.1.1 测试程序源代码

5.1.2 测试程序Makefile 

 5.2 运行测试代码

5.3 结论


概述

        本文详细介绍了如何在Linux platform tree框架下,编写一个基于SPI接口的驱动程序。笔者使用ICM20606芯片,应用SPI工作方式操作该芯片,实现其驱动程序。还编写了一个测试程序,并在板卡上运行测试程序。验证驱动的可靠性。

源代码地址: ICM20608linux环境下的驱动程序资源-CSDN文库

                       ICM20608linux环境下的测试程序资源-CSDN文库

1 硬件接口

     本文主要使用SPI总线驱动ICM20608芯片,如下内容会详细介绍设备树更新,驱动代码的实现等内容。由原理图可得,ICM20608与MCU的对应关系如下:

ICM20608MCU注释
SDO

MX6UL_PAD_UART2_RTS_B__ECSPI3_MISO

主设备输入、从设备输出线
SDI

MX6UL_PAD_UART2_CTS_B__ECSPI3_MOSI

主设备输出、从设备输入线
SCLK

MX6UL_PAD_UART2_RX_DATA__ECSPI3_SCLK

时钟线
CS

MX6UL_PAD_UART2_TX_DATA__GPIO1_IO20

从设备选择线
INTJTAG_MOD_SP_TX中断引脚

板卡上ICM-20608的原理图

2 添加ICM20608的设备树信息

2.1 使用i.MX Pins Tool v6配置SPI引脚

使用i.MX Pins Tool v6配置引脚,配置对应的引脚为SPI,配置参数如下:

		pinctrl_ecspi3: ecspi3grp {fsl,pins = <MX6UL_PAD_UART2_RTS_B__ECSPI3_MISO        0x100b1  /* MISO*/MX6UL_PAD_UART2_CTS_B__ECSPI3_MOSI        0x100b1  /* MOSI*/MX6UL_PAD_UART2_RX_DATA__ECSPI3_SCLK      0x100b1  /* CLK */MX6UL_PAD_UART2_TX_DATA__GPIO1_IO20       0x100b0  /* CS  */>;};

在.dts文件中的位置为:

2.2 配置设备树

配置设备树的目的,是将SPI的工作IO引脚和外围的设备对应起来,方便在驱动程序中匹配该参数信息。在.dts文件中添加如下代码:

&ecspi3 {fsl,spi-num-chipselects = <1>;cs-gpio = <&gpio1 20 GPIO_ACTIVE_LOW>;pinctrl-names = "default";pinctrl-0 = <&pinctrl_ecspi3>;status = "okay";spidev: icm20608@0 {compatible = "atk,icm20608";spi-max-frequency = <8000000>;reg = <0>;};
};

spi的配置参数在.dts文件中的位置为:

2.3 编译.dts 

使用命令编译代码。然后将生成的.dtb文件发送到NFS的共享目录下,方便在板卡使用该文件

make dtbs

编译后,得到了.dtb

2.4 在板卡中更新设备树

1) 将NFS中共享的设备树文件copy到运行目录中

2)reboot板卡后,内核会重新读取.dtb文件。然后在/sys/bus/spi/devices/spi2.0目录下查看板卡device tree,使用如下命令:

cd /sys/bus/spi/devices/spi2.0/
ls -l

得到节点信息如下:

3 编写驱动程序

3.1 创建设备匹配表

其目的是和设备树中参数对应起来

static const struct of_device_id atk_dl6y2c_icm20608[] = {{ .compatible = "atk,icm20608" },{ },
};static const struct spi_device_id icm20608_id[] = {{ "xxxxyyy",  (kernel_ulong_t)NULL },{ /* END OF LIST */ }
};/* 1. 定义platform_driver */
static struct i2c_driver icm20608_driver = {.probe      = icm20608_probe,.remove     = icm20608_remove,.driver     = {.name   = "atk_icm20608",.of_match_table = atk_dl6y2c_icm20608,},.id_table = icm20608_id,
};

在.c 文件中的代码信息如下: 

3.2 重要函数介绍

3.2.1 初始化函数

在初始化函数中,通过调用spi_setup 来初始化spi接口,该函数放在prope接口中完成

3.2.2 写寄存器函数

第148行,写寄存器数据时,寄存器地址信息,bit-7必须为0

3.2.3 读寄存器函数

第111行,读寄存器数据时,必须传递一个寄存器地址信息,且bit-7必须为1

3.2.3 完整驱动代码

3.2.3.1 驱动代码程序
/***************************************************************
Copyright  2024-2029. All rights reserved.
文件名     : drv_17_icm20608.c
作者       : tangmingfei2013@126.com
版本       : V1.0
描述       : icm20608 驱动程序
其他       : 无
日志       : 初版V1.0 2024/1/30  使用方法:
1) 在.dts文件中定义节点信息
&ecspi3 {fsl,spi-num-chipselects = <1>;cs-gpio = <&gpio1 20 GPIO_ACTIVE_LOW>;pinctrl-names = "default";pinctrl-0 = <&pinctrl_ecspi3>;status = "okay";spidev: icm20608@0 {compatible = "atk,icm20608";spi-max-frequency = <8000000>;reg = <0>;};
};2) 在驱动匹配列表 
static const struct of_device_id icm20608_of_match[] = {{ .compatible = "atk,icm20608" },{ } // Sentinel
};
***************************************************************/
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ktime.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of_gpio.h>
#include <linux/semaphore.h>
#include <linux/timer.h>
#include <linux/irq.h>
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/fs.h>
#include <linux/fcntl.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/spi/spi.h>
#include <linux/of.h>
#include <linux/of_address.h>#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#define DEVICE_NAME      "icm20608"     // dev/icm20608/* icm20608dev设备结构体 */
struct icm20608stru_dev{dev_t   devid;                /* 设备号         */struct  cdev cdev;            /* cdev           */struct  class *class;         /* 类             */struct  device *device;       /* 设备           */int     major;                /* 主设备号       */struct  spi_device *spi;
};struct icm20608stru_value{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;           /* 温度原始值            */
};/* read or write icm20608 structure */static struct icm20608stru_dev icm20608dev;/*icm20608 driver 
*/
static int icm20608_read( unsigned char reg, unsigned char *buff, unsigned int len)
{int ret = -1;unsigned char txdata[1];unsigned char * rxdata;struct spi_message spi_msg;struct spi_transfer *spi_t;struct spi_device *spi = icm20608dev.spi;spi_t = kzalloc(sizeof(struct spi_transfer), GFP_KERNEL);if(!spi_t) {return -ENOMEM;}rxdata = kzalloc(sizeof(char) * len, GFP_KERNEL);if(!rxdata) {goto ERROR1;}txdata[0] = reg | 0x80;  // set bit-7 as 1 for read mode spi_t->tx_buf = txdata; spi_t->rx_buf = rxdata; spi_t->len = len+1; spi_message_init(&spi_msg); spi_message_add_tail(spi_t, &spi_msg);ret = spi_sync(spi, &spi_msg);if(ret) {goto ERROR2;}memcpy(buff , rxdata+1, len);ERROR2:kfree(rxdata); ERROR1:    kfree(spi_t);return ret;
}static int icm20608_write( unsigned char reg, unsigned char *buff, unsigned int len)
{int ret = -1;unsigned char *txdata;struct spi_message spi_msg;struct spi_transfer *spi_t;struct spi_device *spi = icm20608dev.spi;spi_t = kzalloc(sizeof(struct spi_transfer), GFP_KERNEL); if(!spi_t) {return -ENOMEM;}txdata = kzalloc(sizeof(char)+len, GFP_KERNEL);if(!txdata) {goto ERROR1;}*txdata = reg & ~0x80;  memcpy(txdata+1, buff, len);  spi_t->tx_buf = txdata; spi_t->len = len+1;spi_message_init(&spi_msg);spi_message_add_tail(spi_t, &spi_msg);ret = spi_sync(spi, &spi_msg);if(ret) {goto ERROR2;}ERROR2:kfree(txdata);
ERROR1:kfree(spi_t);return ret;
}static void icm20608_readdata(struct icm20608stru_value *dev)
{unsigned char data[14] = { 0 };icm20608_read(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 void icm20608_reginit(void)
{unsigned char value = 0;unsigned char buff[1];buff[0] = 0x80;icm20608_write( ICM20_PWR_MGMT_1, buff , 1);mdelay(50);buff[0] = 0x01;icm20608_write( ICM20_PWR_MGMT_1, buff , 1);mdelay(50);icm20608_read(ICM20_WHO_AM_I, &value, 1);printk("ICM20608 ID = %#X\r\n", value);    buff[0] = 0x00;icm20608_write( ICM20_SMPLRT_DIV,    buff, 1);buff[0] = 0x18;icm20608_write( ICM20_GYRO_CONFIG,   buff, 1);buff[0] = 0x18;icm20608_write( ICM20_ACCEL_CONFIG,  buff, 1);buff[0] = 0x04;icm20608_write( ICM20_CONFIG,        buff, 1);buff[0] = 0x04;icm20608_write( ICM20_ACCEL_CONFIG2, buff, 1);buff[0] = 0x00;icm20608_write( ICM20_PWR_MGMT_2,    buff, 1);buff[0] = 0x00;icm20608_write( ICM20_LP_MODE_CFG,   buff, 1);buff[0] = 0x00;icm20608_write( ICM20_FIFO_EN,       buff, 1);
}/*linux driver 驱动接口: 实现对应的open/read/write等函数,填入file_operations结构体
*/
static ssize_t icm20608_drv_read(struct file *file, char __user *buf, size_t size, loff_t *offset)
{int err;signed int data[7];struct icm20608stru_value stru_dev;icm20608_readdata( &stru_dev );data[0] = stru_dev.gyro_x_adc;data[1] = stru_dev.gyro_y_adc;data[2] = stru_dev.gyro_z_adc;data[3] = stru_dev.accel_x_adc;data[4] = stru_dev.accel_y_adc;data[5] = stru_dev.accel_z_adc;data[6] = stru_dev.temp_adc;err = copy_to_user(buf, data, sizeof(data));return err;
}static int icm20608_drv_close(struct inode *node, struct file *file)
{printk(" %s line %d \r\n",  __FUNCTION__, __LINE__);return 0;
}static int icm20608_drv_open(struct inode *inode, struct file *filp)
{icm20608_reginit();return 0;
}/* 定义driver的file_operations结构体
*/
static struct file_operations icm20608_fops = {.owner   = THIS_MODULE,.read    = icm20608_drv_read,.open    = icm20608_drv_open,.release = icm20608_drv_close,
};/* 1. 从platform_device获得GPIO* 2. gpio=>irq* 3. request_irq*/
static int icm20608_probe( struct spi_device *spi )
{printk("icm20608 driver and device was matched!\r\n");/* initial spi port  */spi->mode = SPI_MODE_0; /*MODE0,CPOL=0,CPHA=0*/spi_setup(spi);icm20608dev.spi = spi;/* register file_operations  */icm20608dev.major = register_chrdev( 0, DEVICE_NAME,     /* device name */&icm20608_fops);  /* create the device class  */icm20608dev.class = class_create(THIS_MODULE, "icm20608_class");if (IS_ERR(icm20608dev.class)) {printk("%s line %d\n", __FUNCTION__, __LINE__);unregister_chrdev( icm20608dev.major, DEVICE_NAME);return PTR_ERR( icm20608dev.class );}/*  create device  */device_create( icm20608dev.class, NULL, MKDEV( icm20608dev.major, 0 ), NULL, DEVICE_NAME);        // device name return 0;
}static int icm20608_remove(struct spi_device *spi)
{printk("%s line %d\n", __FUNCTION__, __LINE__);device_destroy( icm20608dev.class, MKDEV( icm20608dev.major, 0));class_destroy(icm20608dev.class);unregister_chrdev(icm20608dev.major, DEVICE_NAME);return 0;
}static const struct of_device_id atk_dl6y2c_icm20608[] = {{ .compatible = "atk,icm20608" },{ },
};static const struct spi_device_id icm20608_id[] = {{ "xxxxyyy",  (kernel_ulong_t)NULL },{ /* END OF LIST */ }
};/* 1. 定义platform_driver */
static struct spi_driver icm20608_driver = {.probe      = icm20608_probe,.remove     = icm20608_remove,.driver     = {.name   = "atk_icm20608",.of_match_table = atk_dl6y2c_icm20608,},.id_table = icm20608_id,
};/* 2. 入口函数: 注册driver 
*/
static int __init icm20608_init(void)
{printk("%s line %d\n",__FUNCTION__, __LINE__);return spi_register_driver(&icm20608_driver);
}/* 3. 出口函数:卸载driver*/
static void __exit icm20608_exit(void)
{printk("%s line %d\n", __FUNCTION__, __LINE__);spi_unregister_driver(&icm20608_driver);
}/*4. 驱动入口和出口函数
*/
module_init(icm20608_init);
module_exit(icm20608_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("tangmingfei2013@126.com");
3.2.3.1 驱动代码程序Makefile
PWD := $(shell pwd)KERNEL_DIR=/home/mftang/linux_workspace/study_atk_dl6y2c/kernel/atk-dl6u2c
ARCH=arm
CROSS_COMPILE=/home/ctools/gcc-linaro-4.9.4-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-export  ARCH  CROSS_COMPILEobj-m:= drv_17_icm20608.oall:$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modulesclean:rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions *.order *.symvers

4 测试驱动安装

4.1 编译驱动程序

在服务器上编译驱动程序,执行make命令后,会生成的.ko,复制该文件到NFS的共享目中,方便在板卡中使用

4.2 在板卡上安装驱动

在板卡上执行: 

insmod drv_17_icm20608.ko

可以看见打印如下信息,说明驱动程序已经安装到内核 

在dev目录下查看该设备驱动:

 5 验证和测试

      完成驱动程序编写后,并不能保证驱动程序是否能够正常工作,这时需要编程一个测试程序来验证其功能是否可靠。

5.1 编写测试程序

5.1.1 测试程序源代码

/***************************************************************
Copyright  2024-2029. All rights reserved.
文件名     : test_17_icm20608.c
作者       : tangmingfei2013@126.com
版本       : V1.0
描述       : 测试icm20608驱动程序
其他       : 无
日志       : 初版V1.0 2024/02/22
***************************************************************/
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/types.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <linux/fs.h>
#include <unistd.h>
#include <errno.h>
#include <assert.h>
#include <string.h>
#include <time.h>#define DEV_FILE                     "/dev/icm20608"struct icm20608stru_value{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;           /* 温度原始值            */
};int main(void)
{int count = 0;int fd, ret;unsigned char databuf[7];struct icm20608stru_value stru_value;float gyro_x_act, gyro_y_act, gyro_z_act;float accel_x_act, accel_y_act, accel_z_act;float temp_act;fd = open(DEV_FILE, O_RDWR);if (fd == -1){printf("can not open file: %s \n", DEV_FILE);return -1;}while (count < 10000 ) {ret = read(fd, databuf, sizeof(databuf));if(ret == 0) {stru_value.gyro_x_adc = databuf[0];stru_value.gyro_y_adc = databuf[1];stru_value.gyro_z_adc = databuf[2];stru_value.accel_x_adc = databuf[3];stru_value.accel_y_adc = databuf[4];stru_value.accel_z_adc = databuf[5];stru_value.temp_adc = databuf[6];/* 计算实际值 */gyro_x_act = (float)(stru_value.gyro_x_adc)  / 16.4;gyro_y_act = (float)(stru_value.gyro_y_adc)  / 16.4;gyro_z_act = (float)(stru_value.gyro_z_adc)  / 16.4;accel_x_act = (float)(stru_value.accel_x_adc) / 2048;accel_y_act = (float)(stru_value.accel_y_adc) / 2048;accel_z_act = (float)(stru_value.accel_z_adc) / 2048;temp_act = ((float)(stru_value.temp_adc) - 25 ) / 326.8 + 25;printf("\r\n %04d count value:\r\n", count);printf("gx = %d, gy = %d, gz = %d\r\n", stru_value.gyro_x_adc,stru_value.gyro_y_adc, stru_value.gyro_z_adc);printf("ax = %d, ay = %d, az = %d\r\n", stru_value.accel_x_adc, stru_value.accel_y_adc, stru_value.accel_z_adc);printf("temp = %d\r\n", stru_value.temp_adc);printf(" %04d  user value: ", count);printf("gx = %.2f°/S, gy = %.2f°/S, gz = %.2f°/S\r\n", gyro_x_act, gyro_y_act, gyro_z_act);printf("ax = %.2fg, ay = %.2fg, az = %.2fg\r\n", accel_x_act, accel_y_act, accel_z_act);printf("temp = %.2f°C\r\n", temp_act);}usleep(100000); /*100ms */count++;}close(fd);return 0;
}

5.1.2 测试程序Makefile 

CFLAGS= -Wall -O2
CC=/home/ctools/gcc-linaro-4.9.4-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc
STRIP=/home/ctools/gcc-linaro-4.9.4-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-striptest_17_icm20608: test_17_icm20608.o$(CC) $(CFLAGS) -o test_17_icm20608 test_17_icm20608.o$(STRIP) -s test_17_icm20608clean:rm -f test_17_icm20608 test_17_icm20608.o

 5.2 运行测试代码

编译测试代码,将生成的可执行文件共享在NF目录中,方便在板卡中执行程序

转动板卡,观察sensor的数据变化

5.3 结论

 通过运行测试程序,App调用驱动程序,能正确的从sensor中读取数据 

相关文章:

实现linux platform tree框架下ICM20608驱动开发(SPI)

目录 概述 1 硬件接口 2 添加ICM20608的设备树信息 2.1 使用i.MX Pins Tool v6配置SPI引脚 2.2 配置设备树 2.3 编译.dts 2.4 在板卡中更新设备树 3 编写驱动程序 3.1 创建设备匹配表 3.2 重要函数介绍 3.2.1 初始化函数 3.2.2 写寄存器函数 3.2.3 读寄存器函数 …...

在前端开发中需要考虑的常见web安全问题和攻击原理以及防范措施

文章目录 一、XSS攻击1、反射型XSS攻击原理2、DOM型XSS攻击原理3、存储型XSS攻击原理 防范措施 二、CSRF攻击攻击原理&#xff1a;防范措施&#xff1a; 三、点击劫持攻击原理&#xff1a;防范措施&#xff1a; 四、项目中如何预防安全问题 随着互联网的发展&#xff0c;Web应用…...

年关将至送大礼 社区适时献爱心

在这个快节奏的时代&#xff0c;社区作为人们生活的重要组成部分&#xff0c;其凝聚力和互助精神显得尤为重要。2024年2月7日&#xff0c;实践队员李若钰有幸参与了社区礼盒分装的活动&#xff0c;这不仅仅是一次简单的劳动&#xff0c;更是一次心灵的洗礼和感悟。 礼盒分装&am…...

singularity容器的技术基础

Singularity容器技术是专为科学计算、数据密集型工作和高性能计算&#xff08;HPC&#xff09;环境设计的。与其他容器技术如Docker相比&#xff0c;Singularity提供了一些独特的特性和设计考虑&#xff0c;使其在科学和研究社区中受到欢迎。以下是Singularity容器技术的一些关…...

jax可微分编程的笔记(2)

jax可微分编程的笔记&#xff08;2&#xff09; 第2章 自动微分 自动微分和符号求导有诸多的相似之处&#xff1a;它们同样依赖于计算图 的构建&#xff0c;同样依赖于求导的递归实现。从某种意义上来说&#xff0c;它们 甚至有完全相同的数据结构。不过&#xff0c;二者的区…...

在Linux服务器上部署一个单机项目

目录 一、jdk安装 二、tomcat安装 三、MySQL安装 四、部署项目 一、jdk安装 1. 上传jdk安装包 jdk-8u151-linux-x64.tar.gz 进入opt目录&#xff0c;将安装包拖进去 2. 解压安装包 这里需要解压到usr/local目录下&#xff0c;在这里我新建一个文件夹保存解压后的文件 [r…...

HTTP概要

文章目录 什么是HTTP?URL的结构请求报文结构请求方法GETHEADPOSTPUTDELETETRACEOPTIONSCONNECTPATCH解释 请求头字段 响应报文结构响应状态响应头字段 HTTP会话3次握手无状态协议 什么是HTTP? HTTP&#xff0c;即Hypertext Transfer Protocol(超文本传输协议) 它是一个”请…...

128 Linux 系统编程6 ,C++程序在linux 上的调试,GDB调试

今天来整理 GDB 调试。 在windows 上我们使用vs2017开发&#xff0c;可以手动的加断点&#xff0c;debug。 那么在linux上怎么加断点&#xff0c;debug呢&#xff1f;这就是今天要整理的GDB调试工具了。 那么有些同学可能会想到&#xff1a;我们在windows上开发&#xff0c;…...

vue2的ElementUI的form表单报错“Error: [ElementForm]unpected width”修复

1. 问题 ElementUI的form表单&#xff0c;当动态切换显示表单时报错 Error: [ElementForm]unpected width。 翻译过来就是form表单的label宽度width出了问题。 2. 分析 参数说明类型可选值默认值label-width表单域标签的宽度&#xff0c;例如 ‘50px’。作为 Form 直接子元…...

Linux 网络命令指南

目录 配置IP地址和子网掩码 网络接口的详细信息 测试与目标主机的连通性 下载文件或内容 远程登录&#xff0c;进行远程管理和协作 CentOS / Red Hat&#xff08;使用 firewalld&#xff09; 关闭防火墙 开启防火墙 配置TCP端口&#xff08;假设使用3306端口&#xff…...

vue3组件间的通信,通过props,emit,provide和inject把数据传递N个层级,expose和ref实现父组件调用子组件方法

文章目录 一、父组件数据传递N个层级的子组件vue3 provide 与 injectA组件名称 app.vueB组件名称 provideB.vueC组件名称 provideCSetup.vue 二、使用v-model指令实现父子组件的双向绑定父组件名称 app.vue子组件名称 v-modelSetup.vue 三、父组件props向子组件传值子组件 prop…...

开源免费的NTFS for mac工具mounty

开源免费的NTFS for mac工具mounty 安装依赖 brew install gromgit/fuse/ntfs-3g-macbrew install --cask macfuse安装mounty 如果已经安装macFUSE和ntfs-3g-mac&#xff0c;可以直接点击下载的dmg安装包&#xff0c;安装升级。第一次启动mounty&#xff0c;你需要接受一系列…...

Sora-OpenAI 的 Text-to-Video 模型:制作逼真的 60s 视频片段

OpenAI 推出的人工智能功能曾经只存在于科幻小说中。 2022年&#xff0c;Openai 发布了 ChatGPT&#xff0c;展示了先进的语言模型如何实现自然对话。 随后&#xff0c;DALL-E 问世&#xff0c;它利用文字提示生成令人惊叹的合成图像。 现在&#xff0c;他们又推出了 Text-t…...

4 buuctf解题

[CISCN 2019 初赛]Love Math1 打开题目 题目源码 <?php error_reporting(0); //听说你很喜欢数学&#xff0c;不知道你是否爱它胜过爱flag if(!isset($_GET[c])){show_source(__FILE__); }else{//例子 c20-1$content $_GET[c];if (strlen($content) > 80) {die("…...

Jmeter基础(3) 发起一次请求

目录 Jmeter 一次请求添加线程组添加HTTP请求添加监听器 Jmeter 一次请求 用Jmeter进行一次请求的过程&#xff0c;需要几个步骤呢&#xff1f; 1、添加线程组2、添加HTTP请求3、添加监听器&#xff0c;查看结果树 现在就打开jmeter看下如何创建一个请求吧 添加线程组 用来…...

视频怎么变成gif动图?一招教你在线转换

MP4是一种常见的视频文件格式&#xff0c;它可以包含音频和视频数据&#xff0c;并支持高质量的视频压缩。MP4视频可以呈现连续的动态效果&#xff0c;可以包含平滑的运动、音频等多媒体元素。而GIF动图是由一系列静态图像组成的&#xff0c;通过快速连续播放这些帧来创造出动态…...

Leetcode2583. 二叉树中的第 K 大层和

Every day a Leetcode 题目来源&#xff1a;2583. 二叉树中的第 K 大层和 解法1&#xff1a;层序遍历 排序 先使用层序遍历计算出树的每一层的节点值的和&#xff0c;保存在数组 levelSum 中。然后将数组进行排序&#xff0c;返回第 k 大的值。需要考虑数组长度小于 k 的边…...

(六)激光线扫描-三维重建

本篇文章是《激光线扫描-三维重建》系列的最后一篇。 1. 基础理论 1.1 光平面 在之前光平面标定的文章中,已经提到过了,是指 激光发射器投射出一条线,形成的一个扇形区域平面就是光平面。 三维空间中平面的公式是: A X + B Y + C Z + D = 0 A X+B Y+C Z+D=0...

CSS 面试题汇总

CSS 面试题汇总 1. 介绍下 BFC 及其应 参考答案&#xff1a; 参考答案&#xff1a; 所谓 BFC&#xff0c;指的是一个独立的布局环境&#xff0c;BFC 内部的元素布局与外部互不影响。 触发 BFC 的方式有很多&#xff0c;常见的有&#xff1a; 设置浮动overflow 设置为 auto、scr…...

定制你的【Spring Boot Starter】,加速开发效率

摘要&#xff1a; 本文将介绍如何创建一个自定义的 Spring Boot Starter&#xff0c;让您可以封装常用功能和配置&#xff0c;并在多个 Spring Boot 项目中共享和重用。 1. 简介 Spring Boot Starter 是 Spring Boot 框架中的一种特殊的依赖项&#xff0c;它用于快速启动和配置…...

Vue源码系列讲解——生命周期篇【二】(new Vue)

目录 1. 前言 2. new Vue()都干了什么 3 . 合并属性 4. callHook函数如何触发钩子函数 5. 总结 1. 前言 上篇文章中介绍了Vue实例的生命周期大致分为4个阶段&#xff0c;那么首先我们先从第一个阶段——初始化阶段开始入手分析。从生命周期流程图中我们可以看到&#xff…...

JavaScript 设计模式之观察者模式

观察者模式 观察者模式又被称为发布-订阅模式&#xff0c;使用一个对象来收集订阅者&#xff0c;在发布时遍历所有订阅者&#xff0c;然后将信息传递给订阅者&#xff0c;可以这样来实现一个简单的模式 const Observable (function () {let __messages {}return {register:…...

数据结构D4作业

1.实现单向循环链表的功能 loop.c #include "loop.h" loop_p create_loop() { loop_p H(loop_p)malloc(sizeof(loop)); if(HNULL) { printf("创建失败\n"); return NULL; } H->len0; H->nextH; ret…...

springboot750人职匹配推荐系统

springboot750人职匹配推荐系统 获取源码——》公主号&#xff1a;计算机专业毕设大全...

【笔记】【开发方案】APN 配置参数 bitmask 数据转换(Android KaiOS)

一、参数说明 &#xff08;一&#xff09;APN配置结构对比 平台AndroidKaiOS文件类型xmljson结构每个<apn>标签是一条APN&#xff0c;包含完成的信息层级数组结构&#xff0c;使用JSON格式的数据。最外层是mcc&#xff0c;其次mnc&#xff0c;最后APN用数组形式配置&am…...

Redis篇之缓存雪崩、击穿、穿透详解

学习材料&#xff1a;https://xiaolincoding.com/redis/cluster/cache_problem.html 缓存雪崩 什么是缓存雪崩 在面对业务量较大的查询场景时&#xff0c;会把数据库中的数据缓存至redis中&#xff0c;避免大量的读写请求同时访问mysql客户端导致系统崩溃。这种情况下&#x…...

【深度学习笔记】3_2线性回归的从零实现

注&#xff1a;本文为《动手学深度学习》开源内容&#xff0c;仅为个人学习记录&#xff0c;无抄袭搬运意图 3.2 线性回归的从零开始实现 在了解了线性回归的背景知识之后&#xff0c;现在我们可以动手实现它了。尽管强大的深度学习框架可以减少大量重复性工作&#xff0c;但若…...

Apache Maven简介

Maven 简介 Apache Maven 是一个用于项目构建、依赖管理和项目信息管理的强大工具。它基于项目对象模型(Project Object Model,POM)进行构建,通过描述项目的结构和依赖关系来管理项目的构建过程。 以下是 Apache Maven 的一些关键原理和工作流程: 项目对象模型(POM)…...

#12解决request中getReader()和getInputStream()只能调用一次的问题

目录 1、背景 2、解决方案 2.1、自定义HttpServletRequestWrapper 2.2、JsonRequestHeaderParamsHelper 2.3、HttpServletRequestReplacedFilter 2.4、使用 1、背景 当前系统Content-Type为application/json&#xff0c;参数接收方式采用RequestBody和RequestParam&#…...

直接插入排序+希尔排序+冒泡排序+快速排序+选择排序+堆排序+归并排序+基于统计的排序

插入排序&#xff1a;直接插入排序、希尔排序 交换排序&#xff1a;冒泡排序、快速排序 选择排序&#xff1a;简单选择排序、堆排序 其他&#xff1a;归并排序、基于统计的排序 一、直接插入排序 #include<stdio.h> #include<stdlib.h> /* 直接插入排序&#…...