IIC总线式驱动开发(mpu6050)(二)
目录
六、I2C总线二级外设驱动开发方法
七、I2C总线二级外设驱动开发之名称匹配
1. i2c_register_board_info
2. i2c_new_device:明确二级外设地址的情况下可用
3. i2c_new_probed_device
八、I2C总线二级外设驱动开发之设备树匹配
六、I2C总线二级外设驱动开发方法
1. 查阅原理图以便得知二级外设挂在哪条I2C总线上、二级外设的身份标识(二级外设自身的地址)
2. 参照platform样式搭建二级外设驱动框架
3. 查询二级外设芯片手册以便得知驱动需要用到的寄存器地址
注意:
(1) 此处寄存器是指二级外设内部的寄存器,每个寄存器在芯片手册里有个对应编号(也被称为地址),但不是内存地址,特别提醒此寄存器不是SOC芯片内部参与内存统一编址的寄存器,更不是ARM核-CPU的寄存器
(2)通过调用i2c_tranfer函数完成与相应寄存器的数据交互
4. 参照字符驱动完成其余代码编写
5. 创建对应的i2c_client对象
linux-3.14\Documentation\i2c\instantiating-devices
匹配方式:
1. 名称匹配(id和name差不多)
2. 设备树匹配
3. ACPI匹配
Advanced Configuration and Power Management Interface 高级配置和电源管理接口
PC机平台采用的一种硬件配置接口
(咱们是arm平台这种方式用不了)
i2c二级外设驱动框架:
```c//其它struct file_operations函数实现原理同硬编驱动static int mpu6050_probe(struct i2c_client *pclt,const struct i2c_device_id *pid){//做硬编驱动模块入口函数的活}static int mpu6050_remove(struct i2c_client *pclt){//做硬编驱动模块出口函数的活}/*名称匹配时定义struct i2c_device_id数组*/static struct i2c_device_id mpu6050_ids ={{"mpu6050",0},//.....{}};/*设备树匹配时定义struct of_device_id数组*/static struct of_device_id mpu6050_dts ={{.compatible = "invensense,mpu6050"},//....{}};/*通过定义struct i2c_driver类型的全局变量来创建i2c_driver对象,同时对其主要成员进行初始化*/struct i2c_driver mpu6050_driver ={.driver = {.name = "mpu6050",.owner = THIS_MODULE,.of_match_table = mpu6050_dts,},.probe = mpu6050_probe,.remove = mpu6050_remove,.id_table = mpu6050_ids,};/*以下其实是个宏,展开后相当于实现了模块入口函数和模块出口函数*/module_i2c_driver(mpu6050_driver);MODULE_LICENSE("GPL");```
七、I2C总线二级外设驱动开发之名称匹配
这种匹配方式需要自己创建i2c_client对象
创建i2c_client对象有三种方式:
1. i2c_register_board_info
1.当开发板上电内核跑起来的时候,肯定是架构相关的程序首先运行,也就是mach-xxx.c
2. mach-xxx.c文件里首先会定义i2c_board_info的结构体数组,在mach-xxx.c的初始化函数里调用i2c_register_board_info函数把i2c_board_inifo链接进内核的i2c_board_list链表当中去
3.在驱动i2c目录下和开发板板对应的驱动文件i2c-xxx.c里,创建i2c_adapter对象
4.这种方式严重依赖平台,缺乏灵活性,基本会被遗弃
2. i2c_new_device:明确二级外设地址的情况下可用
i2c二级外设client框架:
```c#include <linux/kernel.h>#include <linux/module.h>#include <linux/i2c.h>static struct i2c_board_info mpu6050_info ={I2C_BOARD_INFO("mpu6050",二级外设地址) };static struct i2c_client *mpu6050_client;static int __init mpu6050_dev_init(void){struct i2c_adapter *padp = NULL;padp = i2c_get_adapter(i2c通道编号);mpu6050_client = i2c_new_device(padp,&mpu6050_info);i2c_put_adapter(padp);return 0;}module_init(mpu6050_dev_init);static void __exit mpu6050_dev_exit(void){i2c_unregister_device(mpu6050_client);}module_exit(mpu6050_dev_exit);MODULE_LICENSE("GPL");```
3. i2c_new_probed_device
i2c二级外设client框架:不明确二级外设地址,但是知道是可能几个值之一的情况下可用
```c#include <linux/kernel.h>#include <linux/module.h>#include <linux/i2c.h>static const unsigned short addr_list[] ={0x68,//.....I2C_CLIENT_END};static struct i2c_client *mpu6050_client;static int __init mpu6050_dev_init(void){struct i2c_adapter *padp = NULL;struct i2c_board_info mpu6050_info = {""};strcpy(mpu6050_info.type,"mpu6050");padp = i2c_get_adapter(i2c通道编号);mpu6050_client = i2c_new_probed_device(padp,&mpu6050_info,addr_list,NULL);i2c_put_adapter(padp);if(mpu6050_client != NULL){return 0;}else{return -ENODEV;}}module_init(mpu6050_dev_init);static void __exit mpu6050_dev_exit(void){i2c_unregister_device(mpu6050_client);}module_exit(mpu6050_dev_exit);MODULE_LICENSE("GPL");```
mpu6050_client.c
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/i2c.h>static struct i2c_board_info mpu6050_info =
{I2C_BOARD_INFO("mpu6050",0x68)
};static struct i2c_client *gpmpu6050_client = NULL;static int __init mpu6050_client_init(void)
{struct i2c_adapter *padp = NULL;padp = i2c_get_adapter(5);gpmpu6050_client = i2c_new_device(padp,&mpu6050_info);i2c_put_adapter(padp);return 0;
}static void mpu6050_client_exit(void)
{i2c_unregister_device(gpmpu6050_client);
}module_init(mpu6050_client_init);
module_exit(mpu6050_client_exit);
MODULE_LICENSE("GPL");
mpu6050_drv.c
#include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/i2c.h> #include <linux/cdev.h> #include <linux/wait.h> #include <linux/sched.h> #include <linux/poll.h> #include <linux/slab.h> #include <linux/mm.h> #include <linux/io.h> #include <asm/uaccess.h> #include <asm/atomic.h>#include "mpu6050.h"#define SMPLRT_DIV 0x19 #define CONFIG 0x1A #define GYRO_CONFIG 0x1B #define ACCEL_CONFIG 0x1C#define ACCEL_XOUT_H 0x3B #define ACCEL_XOUT_L 0x3C #define ACCEL_YOUT_H 0x3D #define ACCEL_YOUT_L 0x3E #define ACCEL_ZOUT_H 0x3F #define ACCEL_ZOUT_L 0x40 #define TEMP_OUT_H 0x41 #define TEMP_OUT_L 0x42 #define GYRO_XOUT_H 0x43 #define GYRO_XOUT_L 0x44 #define GYRO_YOUT_H 0x45 #define GYRO_YOUT_L 0x46 #define GYRO_ZOUT_H 0x47 #define GYRO_ZOUT_L 0x48#define PWR_MGMT_1 0x6Bint major = 11; int minor = 0; int mpu6050_num = 1;struct mpu6050_dev {struct cdev mydev;struct i2c_client *pclt;};struct mpu6050_dev *pgmydev = NULL;int mpu6050_read_byte(struct i2c_client *pclt,unsigned char reg) {int ret = 0;char txbuf[1] = {reg};char rxbuf[1] = {0};struct i2c_msg msg[2] = {{pclt->addr,0,1,txbuf},{pclt->addr,I2C_M_RD,1,rxbuf}};ret = i2c_transfer(pclt->adapter,msg,ARRAY_SIZE(msg));if(ret < 0){printk("ret = %d,in mpu6050_read_byte\n",ret);return ret;}return rxbuf[0]; }int mpu6050_write_byte(struct i2c_client *pclt,unsigned char reg,unsigned char val) {int ret = 0;char txbuf[2] = {reg,val};struct i2c_msg msg[1] = {{pclt->addr,0,2,txbuf},};ret = i2c_transfer(pclt->adapter,msg,ARRAY_SIZE(msg));if(ret < 0){printk("ret = %d,in mpu6050_write_byte\n",ret);return ret;}return 0; }int mpu6050_open(struct inode *pnode,struct file *pfile) {pfile->private_data =(void *) (container_of(pnode->i_cdev,struct mpu6050_dev,mydev));return 0; }int mpu6050_close(struct inode *pnode,struct file *pfile) {return 0; }long mpu6050_ioctl(struct file *pfile,unsigned int cmd,unsigned long arg) {struct mpu6050_dev *pmydev = (struct mpu6050_dev *)pfile->private_data;union mpu6050_data data;switch(cmd){case GET_ACCEL:data.accel.x = mpu6050_read_byte(pmydev->pclt,ACCEL_XOUT_L);data.accel.x |= mpu6050_read_byte(pmydev->pclt,ACCEL_XOUT_H) << 8;data.accel.y = mpu6050_read_byte(pmydev->pclt,ACCEL_YOUT_L);data.accel.y |= mpu6050_read_byte(pmydev->pclt,ACCEL_YOUT_H) << 8;data.accel.z = mpu6050_read_byte(pmydev->pclt,ACCEL_ZOUT_L);data.accel.z |= mpu6050_read_byte(pmydev->pclt,ACCEL_ZOUT_H) << 8;break;case GET_GYRO:data.gyro.x = mpu6050_read_byte(pmydev->pclt,GYRO_XOUT_L);data.gyro.x |= mpu6050_read_byte(pmydev->pclt,GYRO_XOUT_H) << 8;data.gyro.y = mpu6050_read_byte(pmydev->pclt,GYRO_YOUT_L);data.gyro.y |= mpu6050_read_byte(pmydev->pclt,GYRO_YOUT_H) << 8;data.gyro.z = mpu6050_read_byte(pmydev->pclt,GYRO_ZOUT_L);data.gyro.z |= mpu6050_read_byte(pmydev->pclt,GYRO_ZOUT_H) << 8;break;case GET_TEMP:data.temp = mpu6050_read_byte(pmydev->pclt,TEMP_OUT_L);data.temp |= mpu6050_read_byte(pmydev->pclt,TEMP_OUT_H) << 8;break;default:return -EINVAL;}if(copy_to_user((void *)arg,&data,sizeof(data))){return -EFAULT;}return sizeof(data); }void init_mpu6050(struct i2c_client *pclt) {mpu6050_write_byte(pclt,PWR_MGMT_1,0x00);mpu6050_write_byte(pclt,SMPLRT_DIV,0x07);mpu6050_write_byte(pclt,CONFIG,0x06);mpu6050_write_byte(pclt,GYRO_CONFIG,0xF8);mpu6050_write_byte(pclt,ACCEL_CONFIG,0x19); }struct file_operations myops = {.owner = THIS_MODULE,.open = mpu6050_open,.release = mpu6050_close,.unlocked_ioctl = mpu6050_ioctl, };static int mpu6050_probe(struct i2c_client *pclt,const struct i2c_device_id *pid) {int ret = 0;dev_t devno = MKDEV(major,minor);/*申请设备号*/ret = register_chrdev_region(devno,mpu6050_num,"mpu6050");if(ret){ret = alloc_chrdev_region(&devno,minor,mpu6050_num,"mpu6050");if(ret){printk("get devno failed\n");return -1;}major = MAJOR(devno);//容易遗漏,注意}pgmydev = (struct mpu6050_dev *)kmalloc(sizeof(struct mpu6050_dev),GFP_KERNEL);if(NULL == pgmydev){unregister_chrdev_region(devno,mpu6050_num);printk("kmalloc failed\n");return -1;}memset(pgmydev,0,sizeof(struct mpu6050_dev));pgmydev->pclt = pclt;/*给struct cdev对象指定操作函数集*/ cdev_init(&pgmydev->mydev,&myops);/*将struct cdev对象添加到内核对应的数据结构里*/pgmydev->mydev.owner = THIS_MODULE;cdev_add(&pgmydev->mydev,devno,mpu6050_num);init_mpu6050(pgmydev->pclt);return 0; }static int mpu6050_remove(struct i2c_client *pclt) {dev_t devno = MKDEV(major,minor);cdev_del(&pgmydev->mydev);unregister_chrdev_region(devno,mpu6050_num);kfree(pgmydev);pgmydev = NULL;return 0; }struct i2c_device_id mpu6050_ids[] = {{"mpu6050",0},{} };struct i2c_driver mpu6050_driver = {.driver = {.name = "mpu6050",.owner = THIS_MODULE,},.probe = mpu6050_probe,.remove = mpu6050_remove,.id_table = mpu6050_ids, };#if 0 int __init mpu6050_driver_init(void) {i2c_add_driver(&mpu6050_driver); }void __exit mpu6050_driver_exit(void) {i2c_del_driver(&mpu6050_driver); } module_init(mpu6050_driver_init); module_exit(mpu6050_driver_exit); #else module_i2c_driver(mpu6050_driver); #endifMODULE_LICENSE("GPL");
#ifndef MPU_6050_H
#define MPU_6050_Hstruct accel_data
{unsigned short x;unsigned short y;unsigned short z;
};
struct gyro_data
{unsigned short x;unsigned short y;unsigned short z;
};union mpu6050_data
{struct accel_data accel;struct gyro_data gyro;unsigned short temp;
};#define MPU6050_MAGIC 'K'#define GET_ACCEL _IOR(MPU6050_MAGIC,0,union mpu6050_data)
#define GET_GYRO _IOR(MPU6050_MAGIC,1,union mpu6050_data)
#define GET_TEMP _IOR(MPU6050_MAGIC,2,union mpu6050_data)#endif
使用probed也行
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/i2c.h>static unsigned short mpu6050_addr_list[] =
{0x68,0x69,I2C_CLIENT_END
};static struct i2c_client *gpmpu6050_client = NULL;static int __init mpu6050_client_init(void)
{struct i2c_adapter *padp = NULL;struct i2c_board_info mpu6050_info = {""};strcpy(mpu6050_info.type,"mpu6050");padp = i2c_get_adapter(5);gpmpu6050_client = i2c_new_probed_device(padp,&mpu6050_info,mpu6050_addr_list,NULL);i2c_put_adapter(padp);if(gpmpu6050_client != NULL){return 0;}else{return -ENODEV;}
}static void mpu6050_client_exit(void)
{i2c_unregister_device(gpmpu6050_client);
}module_init(mpu6050_client_init);
module_exit(mpu6050_client_exit);
MODULE_LICENSE("GPL");
测试用的APP
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>#include <stdio.h>#include "mpu6050.h"int main(int argc,char *argv[])
{int fd = -1;union mpu6050_data data;if(argc < 2){printf("The argument is too few\n");return 1;}fd = open(argv[1],O_RDONLY);if(fd < 0){printf("open %s failed \n",argv[1]);return 2;}while(1){sleep(2);ioctl(fd,GET_ACCEL,&data);printf("Accel-x=0x%x\n",data.accel.x);printf("Accel-y=0x%x\n",data.accel.y);printf("Accel-z=0x%x\n",data.accel.z);ioctl(fd,GET_GYRO,&data);printf("Gyro-x=0x%x\n",data.gyro.x);printf("Gyro-y=0x%x\n",data.gyro.y);printf("Gyro-z=0x%x\n",data.gyro.z);ioctl(fd,GET_TEMP,&data);printf("Temp=0x%x\n",data.temp);printf("\n");}close(fd);fd = -1;return 0;
}
八、I2C总线二级外设驱动开发之设备树匹配
0x68是从设备号,interrupt是中断
IIC的实现和前面LED不太一样那个使用设备树匹配不需要ip IIC需要有一个IP。
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/i2c.h>
#include <linux/cdev.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/poll.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/io.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>#include "mpu6050.h"#define SMPLRT_DIV 0x19
#define CONFIG 0x1A
#define GYRO_CONFIG 0x1B
#define ACCEL_CONFIG 0x1C#define ACCEL_XOUT_H 0x3B
#define ACCEL_XOUT_L 0x3C
#define ACCEL_YOUT_H 0x3D
#define ACCEL_YOUT_L 0x3E
#define ACCEL_ZOUT_H 0x3F
#define ACCEL_ZOUT_L 0x40
#define TEMP_OUT_H 0x41
#define TEMP_OUT_L 0x42
#define GYRO_XOUT_H 0x43
#define GYRO_XOUT_L 0x44
#define GYRO_YOUT_H 0x45
#define GYRO_YOUT_L 0x46
#define GYRO_ZOUT_H 0x47
#define GYRO_ZOUT_L 0x48#define PWR_MGMT_1 0x6Bint major = 11;
int minor = 0;
int mpu6050_num = 1;struct mpu6050_dev
{struct cdev mydev;struct i2c_client *pclt;};struct mpu6050_dev *pgmydev = NULL;int mpu6050_read_byte(struct i2c_client *pclt,unsigned char reg)
{int ret = 0;char txbuf[1] = {reg};char rxbuf[1] = {0};struct i2c_msg msg[2] = {{pclt->addr,0,1,txbuf},{pclt->addr,I2C_M_RD,1,rxbuf}};ret = i2c_transfer(pclt->adapter,msg,ARRAY_SIZE(msg));if(ret < 0){printk("ret = %d,in mpu6050_read_byte\n",ret);return ret;}return rxbuf[0];
}int mpu6050_write_byte(struct i2c_client *pclt,unsigned char reg,unsigned char val)
{int ret = 0;char txbuf[2] = {reg,val};struct i2c_msg msg[1] = {{pclt->addr,0,2,txbuf},};ret = i2c_transfer(pclt->adapter,msg,ARRAY_SIZE(msg));if(ret < 0){printk("ret = %d,in mpu6050_write_byte\n",ret);return ret;}return 0;
}int mpu6050_open(struct inode *pnode,struct file *pfile)
{pfile->private_data =(void *) (container_of(pnode->i_cdev,struct mpu6050_dev,mydev));return 0;
}int mpu6050_close(struct inode *pnode,struct file *pfile)
{return 0;
}long mpu6050_ioctl(struct file *pfile,unsigned int cmd,unsigned long arg)
{struct mpu6050_dev *pmydev = (struct mpu6050_dev *)pfile->private_data;union mpu6050_data data;switch(cmd){case GET_ACCEL:data.accel.x = mpu6050_read_byte(pmydev->pclt,ACCEL_XOUT_L);data.accel.x |= mpu6050_read_byte(pmydev->pclt,ACCEL_XOUT_H) << 8;data.accel.y = mpu6050_read_byte(pmydev->pclt,ACCEL_YOUT_L);data.accel.y |= mpu6050_read_byte(pmydev->pclt,ACCEL_YOUT_H) << 8;data.accel.z = mpu6050_read_byte(pmydev->pclt,ACCEL_ZOUT_L);data.accel.z |= mpu6050_read_byte(pmydev->pclt,ACCEL_ZOUT_H) << 8;break;case GET_GYRO:data.gyro.x = mpu6050_read_byte(pmydev->pclt,GYRO_XOUT_L);data.gyro.x |= mpu6050_read_byte(pmydev->pclt,GYRO_XOUT_H) << 8;data.gyro.y = mpu6050_read_byte(pmydev->pclt,GYRO_YOUT_L);data.gyro.y |= mpu6050_read_byte(pmydev->pclt,GYRO_YOUT_H) << 8;data.gyro.z = mpu6050_read_byte(pmydev->pclt,GYRO_ZOUT_L);data.gyro.z |= mpu6050_read_byte(pmydev->pclt,GYRO_ZOUT_H) << 8;break;case GET_TEMP:data.temp = mpu6050_read_byte(pmydev->pclt,TEMP_OUT_L);data.temp |= mpu6050_read_byte(pmydev->pclt,TEMP_OUT_H) << 8;break;default:return -EINVAL;}if(copy_to_user((void *)arg,&data,sizeof(data))){return -EFAULT;}return sizeof(data);
}void init_mpu6050(struct i2c_client *pclt)
{mpu6050_write_byte(pclt,PWR_MGMT_1,0x00);mpu6050_write_byte(pclt,SMPLRT_DIV,0x07);mpu6050_write_byte(pclt,CONFIG,0x06);mpu6050_write_byte(pclt,GYRO_CONFIG,0xF8);mpu6050_write_byte(pclt,ACCEL_CONFIG,0x19);
}struct file_operations myops = {.owner = THIS_MODULE,.open = mpu6050_open,.release = mpu6050_close,.unlocked_ioctl = mpu6050_ioctl,
};static int mpu6050_probe(struct i2c_client *pclt,const struct i2c_device_id *pid)
{int ret = 0;dev_t devno = MKDEV(major,minor);/*申请设备号*/ret = register_chrdev_region(devno,mpu6050_num,"mpu6050");if(ret){ret = alloc_chrdev_region(&devno,minor,mpu6050_num,"mpu6050");if(ret){printk("get devno failed\n");return -1;}major = MAJOR(devno);//容易遗漏,注意}pgmydev = (struct mpu6050_dev *)kmalloc(sizeof(struct mpu6050_dev),GFP_KERNEL);if(NULL == pgmydev){unregister_chrdev_region(devno,mpu6050_num);printk("kmalloc failed\n");return -1;}memset(pgmydev,0,sizeof(struct mpu6050_dev));pgmydev->pclt = pclt;/*给struct cdev对象指定操作函数集*/ cdev_init(&pgmydev->mydev,&myops);/*将struct cdev对象添加到内核对应的数据结构里*/pgmydev->mydev.owner = THIS_MODULE;cdev_add(&pgmydev->mydev,devno,mpu6050_num);init_mpu6050(pgmydev->pclt);return 0;
}static int mpu6050_remove(struct i2c_client *pclt)
{dev_t devno = MKDEV(major,minor);cdev_del(&pgmydev->mydev);unregister_chrdev_region(devno,mpu6050_num);kfree(pgmydev);pgmydev = NULL;return 0;
}struct of_device_id mpu6050_dt[] =
{{.compatible = "invensense,mpu6050"},{}
};struct i2c_device_id mpu6050_ids[] =
{{"mpu6050",0},{}
};struct i2c_driver mpu6050_driver =
{.driver = {.name = "mpu6050",.owner = THIS_MODULE,.of_match_table = mpu6050_dt,},.probe = mpu6050_probe,.remove = mpu6050_remove,.id_table = mpu6050_ids,
};#if 0
int __init mpu6050_driver_init(void)
{i2c_add_driver(&mpu6050_driver);
}void __exit mpu6050_driver_exit(void)
{i2c_del_driver(&mpu6050_driver);
}
module_init(mpu6050_driver_init);
module_exit(mpu6050_driver_exit);
#else
module_i2c_driver(mpu6050_driver);
#endifMODULE_LICENSE("GPL");
测试程序和.h程序和上面一样。
相关文章:

IIC总线式驱动开发(mpu6050)(二)
目录 六、I2C总线二级外设驱动开发方法 七、I2C总线二级外设驱动开发之名称匹配 1. i2c_register_board_info 2. i2c_new_device:明确二级外设地址的情况下可用 3. i2c_new_probed_device 八、I2C总线二级外设驱动开发之设备树匹配 六、I2C总线二级外设驱动开…...

盘点一下那些远程办公的神仙公司
其实远程办公已经有50多年的历史了,这几年,这种工作方式越来越受到大家的喜欢,对于员工来说,工作效率可以大幅提高,节省下来的通勤时间和成本,有更多的时间花在工作上。可以更好的平衡工作与生活。对于公司…...

Spring Cloud Alibaba全家桶(四)——微服务调用组件Feign
前言 本文小新为大家带来 微服务调用组件Feign 的相关知识,具体内容包含什么是Feign,Spring Cloud Alibaba快速整合OpenFeign,Spring Cloud Feign的自定义配置及使用(包括:日志配置、契约配置、自定义拦截器实现认证逻…...

安装pytorch
一、在anaconda中创建虚拟环境 打开Anaconda Prompt创建一个虚拟环境。比如要创建一个名字为pytorch的虚拟环境,可以如下输入。其中python3.7指定该虚拟环境的python版本号。 conda create -n pytorch python3.7 二、进入新创建的虚拟环境。 创建好虚拟环境后&a…...

自动化测试 Appium之Python运行环境搭建 Part2
环境部署 1、安装Android SDK 安装好后,配置ANDROID_HOME环境变量,设置为Android SDK安装路径(例中:D:\Program Files (x86)\Android\android-sdk) 2、安装其它SDK相关软件包 安装好Android SDK后,选择打开Android SDK Manager…...

LeetCode 2 - 两数相加
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。 请你将两个数相加,并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外,这两个数都不会以 0 开…...

用Python实现九九乘法表的几种方式,最简单只需一行代码
前言 嗨喽~大家好呀,这里是魔王呐 ❤ ~! 我们在学习Python的过程中需要不断的积累和练习,这样才能够走的更远, 今天一起来学习怎么用Python写九九乘法表~ 更多教程源码资料电子书: 点击此处跳转文末名片获取 第一种方法、for-for 代码&…...

入职外包三个月,我提桶跑路了
有一种打工人的羡慕,叫做“大厂”。 真是年少不知大厂香,错把青春插稻秧。 但是,在深圳有一群比大厂员工更庞大的群体,他们顶着大厂的“名”,做着大厂的工作,还可以享受大厂的伙食,却没有大厂…...

企业邮箱对企业有哪些好处以及便捷性
企业邮箱拥有更专业的办公功能,更适合职场使用。同时,使用企业邮箱还可以帮助企业“公私分明”。一方面保护了公司信息,另一方面也提高了工作效率。加上公司统一邮箱也有助于提升公司形象。使用企业邮箱除了收发邮件方便外,还可以…...

ConvNeXt V2实战:使用ConvNeXt V2实现图像分类任务(一)
文章目录摘要安装包安装timm安装 grad-cam数据增强Cutout和MixupEMA项目结构计算mean和std生成数据集关于不上分的问题摘要 论文:https://arxiv.org/pdf/2301.00808.pdf 论文翻译:https://wanghao.blog.csdn.net/article/details/128541957 官方源码&am…...
3.2 报错整理
报错1: 报错:RuntimeError: DataLoader worker (pid 93789) is killed by signal: Killed.原因:显存不够报错2: 报错:TqdmWarning: IProgress not found. Please update jupyter and ipywidgets.解决:pip i…...

从0开始学python -46
Python CGI编程 什么是CGI CGI 目前由NCSA维护,NCSA定义CGI如下: CGI(Common Gateway Interface),通用网关接口,它是一段程序,运行在服务器上如:HTTP服务器,提供同客户端HTML页面的接口。 网页浏览 为了更好的了解CGI是如何工作…...
JavaScript事件委托机制详解
一、什么是事件委托机制 事件委托机制就是:我们给元素添加click事件时不在该元素上添加,而是委托给某个公共的祖辈元素,告诉祖辈元素如果接收到了click事件,并且这个click事件是由该元素触发的,就执行祖辈元素上委托绑…...
【项目实战】MySQL中union和union all的相同点与不同点
一、union和union all的相同点 在MySQL中,Union和Union All都是用来合并两个或者多个查询结果集的关键字 二、union和union all的不同点 union复杂,union all简单 2.1 自动压缩,自动求并集、去重、排序操作 (1)unio…...

ChatGPT最牛应用,让它帮你更新网站新闻吧!
谁能想到,ChatGPT火了!既能对话入流,又能写诗歌论文、出面试题、编代码,甚至还通过了谷歌面试拿到L3工程师offer,放在一年之前,没人相信这是当前AI能够达到的水平。ChatGPT自面世以来,凭借其极为…...

乌班图安装kvm并配置网络
乌班图22安装KVM 1.安装KVM sudo apt install qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virt-manager virtinstsudo adduser id -un libvirt sudo adduser id -un kvm sudo apt install virtinst qemu-efi sudo systemctl enable --now libvirtd sudo s…...

蓝库云|ERP系统在企业数字化转型中最常用的八大功能
ERP系统和与企业数字化转型 随着数字化发展的兴起,规划和管理已成为企业产生富有成效的成果的关键。许多企业采用了企业资源规划 (ERP) 等先进工具,使企业所有者能够以高效的方式规划和管理其资源和运营。 ERP系统负责整合业务的不同流程并向决策者提供…...
Pytorch学习笔记#1:拟合函数/梯度下降
学习自https://pytorch.org/tutorials/beginner/pytorch_with_examples.html 概念 Pytorch Tensor在概念上和Numpy的array一样是一个nnn维向量的。不过Tensor可以在GPU中进行计算,且可以跟踪计算图(computational graph)和梯度(…...

挑战图像处理100问(24)——伽玛校正
伽马校正(Gamma Correction)是一种图像处理技术,用于校正显示设备的非线性响应。通过对图像进行伽马变换,可以将图像的亮度范围映射到显示设备的亮度范围内,从而提高图像的对比度和细节,改善图像的视觉效果…...
高级信息系统项目管理师(高项)软考论文评分标准(附历年高项论文题目汇总)
1、如果您想了解如何高分通过高级信息系统项目管理师(高项)你可以点击一下链接: 高级信息系统项目管理师(高项)高分通过经验分享_高项经验 2、如果您想了解更多的高级信息系统项目管理(高项 软考)原创论文࿰…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...

USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...