荔枝派nano(f1c100s)基于I2C子系统的BME280驱动

硬件环境:
1、荔枝派nano(f1c100s)
2、使用f1c100s的i2c0,PE11和PE12引脚
软件环境:
1、Linux 4.15
2、BME280使用介绍

文章目录

  • 一、I2C子系统
    • 1、应用层访问i2c设备
    • 2、驱动层访问i2c设备
      • 2.1、i2c总线设备驱动模型
      • 2.2、i2c_client 和 i2c_driver
  • 二、程序编写
    • 1、驱动程序
    • 2、i2c_client实现
    • 3、测试应用程序
  • 三、总结

一、I2C子系统

对i2c设备的访问,有两种方法:
1、在应用层直接访问i2c设备;
2、编写i2c设备的驱动程序,也就是在驱动层访问;

1、应用层访问i2c设备

在这里插入图片描述

  • 在应用层可以通过i2c-dev.c驱动程序访问芯片内部i2c控制器的驱动adapter_driver,进而实现访问i2c控制器下的i2c设备。也就是可以在应用程序中直接使用内核提供的i2c-dev.c提供的API函数对i2c设备进行读写操作,不用再去编写该设备的驱动程序。i2ctools就是基于i2c-dev.c实现的在应用层访问i2c设备的工具;

2、驱动层访问i2c设备

在这里插入图片描述

  • 所谓的驱动层访问i2c设备,就是需要我们真正编写某个i2c设备的驱动程序;

2.1、i2c总线设备驱动模型

在这里插入图片描述

  • 可以看到这很像Linux下的platform总线设备驱动模型,但platform总线设备驱动模型是虚拟的,而i2c总线设备驱动模型是真实存在的;
  • 当有新的i2c_client时,i2c总线会匹配其对应的i2c_driver;当有新的i2c_driver注册时,就会匹配还未匹配驱动的i2c_client;一旦匹配成功,i2c_driver的probe函数就被调用;

2.2、i2c_client 和 i2c_driver

  • i2c_client
    i2c_client结构体会存放设备地址(addr)、名字(name)、挂载在哪个i2c控制器下(adapter),等相关硬件信息;

  • i2c_driver
    i2c_driver结构体实现相关的probe、remove等函数;

二、程序编写

程序以访问BME280传感器为例,访问其它i2c设备也是类似的;重在框架;
本驱动程序读取BME280修正参数及温湿度值和大气压值,在应用程序计算最终的温湿度值和大气压值,BME280相关介绍可以参考BME280使用介绍;

1、驱动程序

驱动程序编写大致流程:
1、先定义i2c_driver结构体;
2、实现probe和remove函数;
3、实现file_operations结构体的open和read等函数、比如在open函数里初始化i2c设备,read函数里读寄存器;

驱动程序定义i2c_driver结构体:

static const struct of_device_id of_match_ids_bme280[] = {
	{ .compatible = "bosch,bme280",		.data = NULL },
	{ /* END OF LIST */ },
};

static const struct i2c_device_id bme280_ids[] = {
	{ "bme280",	(kernel_ulong_t)NULL },
	{ /* END OF LIST */ }
};

static struct i2c_driver bme280_driver = {
	.driver = {
		.name = "bme280",
		.of_match_table = of_match_ids_bme280,
	},
	.probe_new = bme280_probe,		//匹配成功后的probe函数
	.remove = bme280_remove,
	.id_table = bme280_ids,
};

实现probe和remove函数:

static struct file_operations bme280_ops = {
	.owner = THIS_MODULE,
	.open  = bme280_open,
	.read  = bme280_read,
};

static int bme280_probe(struct i2c_client *client)
{
	printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	bme280_client = client;		//保存client,里面有设备地址,后续要用

	major = register_chrdev(0, "bme280", &bme280_ops);

	bme280_class = class_create(THIS_MODULE, "bme280_class");
	device_create(bme280_class, NULL, MKDEV(major, 0), NULL, "bme280"); /* /dev/bme280 */
	
	return 0;
}

static int bme280_remove(struct i2c_client *client)
{	
	printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);

	device_destroy(bme280_class, MKDEV(major, 0));
	class_destroy(bme280_class);

	unregister_chrdev(major, "bme280");
	
	return 0;
}

实现open和read函数:

static ssize_t bme280_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{
	int err;

	if(size != sizeof(struct bme280_parameter))
		return 0;

	bme280_refresh();
	bme280_read_temp();
	bme280_read_press();
	bme280_read_humi();
	
	err = copy_to_user(buf, &bme280_para, size);
	return size;
}

static int bme280_open (struct inode *node, struct file *file)
{
	/* 在open函数中初始化BME280 */
	/* init bme280 */
	i2c_smbus_write_byte_data(bme280_client, BME280_REGISTER_CTRL_MEAS, 0x55);
	i2c_smbus_write_byte_data(bme280_client, BME280_REGISTER_CONFIG, 0x10);
	
	/* 读取修正参数 */
	/* read bme280 parameter */
	bme280_read_parameter();

	printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	
	return 0;
}

完整的驱动程序:

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/mod_devicetable.h>
#include <linux/bitops.h>
#include <linux/jiffies.h>
#include <linux/property.h>
#include <linux/acpi.h>
#include <linux/i2c.h>
#include <linux/nvmem-provider.h>
#include <linux/regmap.h>
#include <linux/pm_runtime.h>
#include <linux/gpio/consumer.h>
#include <linux/uaccess.h>
#include <linux/fs.h>

/* BME280 REGISTER */
#define BME280_REGISTER_ID             (0xD0)
#define BME280_REGISTER_RESET          (0xE0)
#define BME280_REGISTER_STATUS         (0xF3)
#define BME280_REGISTER_CTRL_MEAS      (0xF4)
#define BME280_REGISTER_CONFIG         (0xF5)
#define BME280_REGISTER_PRESS_MSB      (0xF7)
#define BME280_REGISTER_PRESS_LSB      (0xF8)
#define BME280_REGISTER_PRESS_XLSB     (0xF9)
#define BME280_REGISTER_TEMP_MSB       (0xFA)
#define BME280_REGISTER_TEMP_LSB       (0xFB)
#define BME280_REGISTER_TEMP_XLSB      (0xFC)
#define BME280_REGISTER_HUMI_MSB       (0xFD)
#define BME280_REGISTER_HUMI_LSB       (0xFE)

struct bme280_parameter{
    unsigned short int T1;
    short int T2;
    short int T3;
    unsigned short int P1;
    short int P2;
    short int P3;
    short int P4;
    short int P5;
    short int P6;
    short int P7;
    short int P8;
    short int P9;
    unsigned char H1;
    short int H2;
    unsigned char H3;
    short int H4;
    short int H5;
    unsigned char H6;
    int adc_T;
    int adc_P;
    int adc_H;
    int t_fine;
};

static int major;
static struct class *bme280_class;
static struct i2c_client *bme280_client;
static struct bme280_parameter bme280_para;

static void bme280_read_parameter (void)
{
	unsigned char tmp;
	
	//dig_T1
    bme280_para.T1 = i2c_smbus_read_byte_data(bme280_client, 0x89);
    bme280_para.T1 <<= 8;
    bme280_para.T1 |= i2c_smbus_read_byte_data(bme280_client, 0x88);

    //dig_T2
    bme280_para.T2 = i2c_smbus_read_byte_data(bme280_client, 0x8B);
    bme280_para.T2 <<= 8;
    bme280_para.T2 |= i2c_smbus_read_byte_data(bme280_client, 0x8A);

    //dig_T3
    bme280_para.T3 = i2c_smbus_read_byte_data(bme280_client, 0x8D);
    bme280_para.T3 <<= 8;
    bme280_para.T3 |= i2c_smbus_read_byte_data(bme280_client, 0x8C);

    //dig_P1
    bme280_para.P1 = i2c_smbus_read_byte_data(bme280_client, 0x8F);
    bme280_para.P1 <<= 8;
    bme280_para.P1 |= i2c_smbus_read_byte_data(bme280_client, 0x8E);

    //dig_P2
    bme280_para.P2 = i2c_smbus_read_byte_data(bme280_client, 0x91);
    bme280_para.P2 <<= 8;
    bme280_para.P2 |= i2c_smbus_read_byte_data(bme280_client, 0x90);

    //dig_P3
    bme280_para.P3 = i2c_smbus_read_byte_data(bme280_client, 0x93);
    bme280_para.P3 <<= 8;
    bme280_para.P3 |= i2c_smbus_read_byte_data(bme280_client, 0x92);

    //dig_P4
    bme280_para.P4 = i2c_smbus_read_byte_data(bme280_client, 0x95);
    bme280_para.P4 <<= 8;
    bme280_para.P4 |= i2c_smbus_read_byte_data(bme280_client, 0x94);

    //dig_P5
    bme280_para.P5 = i2c_smbus_read_byte_data(bme280_client, 0x97);
    bme280_para.P5 <<= 8;
    bme280_para.P5 |= i2c_smbus_read_byte_data(bme280_client, 0x96);

    //dig_P6
    bme280_para.P6 = i2c_smbus_read_byte_data(bme280_client, 0x99);
    bme280_para.P6 <<= 8;
    bme280_para.P6 |= i2c_smbus_read_byte_data(bme280_client, 0x98);

    //dig_P7
    bme280_para.P7 = i2c_smbus_read_byte_data(bme280_client, 0x9B);
    bme280_para.P7 <<= 8;
    bme280_para.P7 |= i2c_smbus_read_byte_data(bme280_client, 0x9A);

    //dig_P8
    bme280_para.P8 = i2c_smbus_read_byte_data(bme280_client, 0x9D);
    bme280_para.P8 <<= 8;
    bme280_para.P8 |= i2c_smbus_read_byte_data(bme280_client, 0x9C);

    //dig_P9
    bme280_para.P9 = i2c_smbus_read_byte_data(bme280_client, 0x9F);
    bme280_para.P9 <<= 8;
    bme280_para.P9 |= i2c_smbus_read_byte_data(bme280_client, 0x9E);

    //dig_H1
    bme280_para.H1 = i2c_smbus_read_byte_data(bme280_client, 0xA1);

    //dig_H2
    bme280_para.H2 = i2c_smbus_read_byte_data(bme280_client, 0xE2);
    bme280_para.H2 <<= 8;
    bme280_para.H2 |= i2c_smbus_read_byte_data(bme280_client, 0xE1);

    //dig_H3
    bme280_para.H3 = i2c_smbus_read_byte_data(bme280_client, 0xE3);

    //dig_H4
    bme280_para.H4 = i2c_smbus_read_byte_data(bme280_client, 0xE4);
    bme280_para.H4 <<= 4;
    tmp = i2c_smbus_read_byte_data(bme280_client, 0xE5);
    tmp &= 0x0f;
    bme280_para.H4 |= tmp;

    //dig_H
    bme280_para.H5 = i2c_smbus_read_byte_data(bme280_client, 0xE6);
    bme280_para.H5 <<= 4;
    tmp = i2c_smbus_read_byte_data(bme280_client, 0xE5);
    tmp &= 0xf0;
    tmp >>= 4;
    bme280_para.H5 |= tmp;

    //dig_H6
    bme280_para.H6 = i2c_smbus_read_byte_data(bme280_client, 0xE7);
}

static void bme280_refresh (void)
{
	int err;

    // refresh before read data
    err = i2c_smbus_write_byte_data(bme280_client, BME280_REGISTER_CTRL_MEAS, 0x55);
    msleep(45);
}

static void bme280_read_temp (void)
{
	int ret;

    // read temp data
    ret = i2c_smbus_read_byte_data(bme280_client, BME280_REGISTER_TEMP_MSB);
    bme280_para.adc_T = ret;
    bme280_para.adc_T <<= 8;

    ret = i2c_smbus_read_byte_data(bme280_client, BME280_REGISTER_TEMP_LSB);
    bme280_para.adc_T |= ret;
    bme280_para.adc_T <<= 8;

    ret = i2c_smbus_read_byte_data(bme280_client, BME280_REGISTER_TEMP_XLSB);
    bme280_para.adc_T |= ret;
    bme280_para.adc_T >>= 4;
}

static void bme280_read_press (void)
{
	int ret;

	// read press data
	ret = i2c_smbus_read_byte_data(bme280_client, BME280_REGISTER_PRESS_MSB);
	bme280_para.adc_P = ret;
	bme280_para.adc_P <<= 8;

	ret = i2c_smbus_read_byte_data(bme280_client, BME280_REGISTER_PRESS_LSB);
	bme280_para.adc_P |= ret;
	bme280_para.adc_P <<= 8;

	ret = i2c_smbus_read_byte_data(bme280_client, BME280_REGISTER_PRESS_XLSB);
	bme280_para.adc_P |= ret;
	bme280_para.adc_P >>= 4;
}

static void bme280_read_humi (void)
{
	int ret;

	// read humi data
	ret = i2c_smbus_read_byte_data(bme280_client, BME280_REGISTER_HUMI_MSB);
	bme280_para.adc_H = ret;
	bme280_para.adc_H <<= 8;

	ret = i2c_smbus_read_byte_data(bme280_client, BME280_REGISTER_HUMI_LSB);
	bme280_para.adc_H |= ret;
}

static ssize_t bme280_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{
	int err;

	if(size != sizeof(struct bme280_parameter))
		return 0;

	bme280_refresh();
	bme280_read_temp();
	bme280_read_press();
	bme280_read_humi();
	
	err = copy_to_user(buf, &bme280_para, size);
	return size;
}

static int bme280_open (struct inode *node, struct file *file)
{
	/* init bme280 */
	i2c_smbus_write_byte_data(bme280_client, BME280_REGISTER_CTRL_MEAS, 0x55);
	i2c_smbus_write_byte_data(bme280_client, BME280_REGISTER_CONFIG, 0x10);
	
	/* read bme280 parameter */
	bme280_read_parameter();

	printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	
	return 0;
}

static struct file_operations bme280_ops = {
	.owner = THIS_MODULE,
	.open  = bme280_open,
	.read  = bme280_read,
};

static const struct of_device_id of_match_ids_bme280[] = {
	{ .compatible = "bosch,bme280",		.data = NULL },
	{ /* END OF LIST */ },
};

static const struct i2c_device_id bme280_ids[] = {
	{ "bme280",	(kernel_ulong_t)NULL },
	{ /* END OF LIST */ }
};

static int bme280_probe(struct i2c_client *client)
{
	printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	bme280_client = client;

	major = register_chrdev(0, "bme280", &bme280_ops);

	bme280_class = class_create(THIS_MODULE, "bme280_class");
	device_create(bme280_class, NULL, MKDEV(major, 0), NULL, "bme280"); /* /dev/bme280 */
	
	return 0;
}

static int bme280_remove(struct i2c_client *client)
{	
	printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);

	device_destroy(bme280_class, MKDEV(major, 0));
	class_destroy(bme280_class);

	unregister_chrdev(major, "bme280");
	
	return 0;
}

static struct i2c_driver bme280_driver = {
	.driver = {
		.name = "bme280",
		.of_match_table = of_match_ids_bme280,
	},
	.probe_new = bme280_probe,
	.remove = bme280_remove,
	.id_table = bme280_ids,
};

static int __init bme280_driver_init(void)
{
	printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	return i2c_add_driver(&bme280_driver);
}

static void __exit bme280_driver_exit(void)
{
	i2c_del_driver(&bme280_driver);
}

module_init(bme280_driver_init);
module_exit(bme280_driver_exit);

MODULE_AUTHOR("Cohen0415");
MODULE_LICENSE("GPL");

2、i2c_client实现

我们知道i2c_driver是靠编写程序实现,但没说i2c_client怎么实现;i2c_client也可以通过程序实现,但在这我们通过设备树来实现,i2c控制器驱动程序会自动把设备树中的i2c节点转成i2c_client(个人理解)
本次使用f1c100s的i2c0,引脚PE11(CK)、PE12(DA),只列出部分设备树的定义,如下:
suniv.dtsi:
在这里插入图片描述
在这里插入图片描述
suniv-f1c100s-licheepi-nano.dts:
在i2c节点下添加你的i2c设备
在这里插入图片描述

3、测试应用程序

应用程序比较简单,直接列出完整程序:

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

struct bme280_parameter{
    unsigned short int T1;
    short int T2;
    short int T3;
    unsigned short int P1;
    short int P2;
    short int P3;
    short int P4;
    short int P5;
    short int P6;
    short int P7;
    short int P8;
    short int P9;
    unsigned char H1;
    short int H2;
    unsigned char H3;
    short int H4;
    short int H5;
    unsigned char H6;
    int adc_T;
    int adc_P;
    int adc_H;
    int t_fine;
};

struct bme280_parameter bme280;

float compute_temp()	//通过修正参数计算最终温度值
{
    int var1, var2, T;

    var1 = ((((bme280.adc_T>>3) - (bme280.T1<<1))) * bme280.T2) >> 11;
    var2 = (((((bme280.adc_T>>4)-bme280.T1) * (bme280.adc_T>>4)-bme280.T1) >> 12) * bme280.T3) >> 14;

    bme280.t_fine = var1 + var2;

    T = (bme280.t_fine * 5 + 128) >> 8;
    return (float)T/100;
}

float compute_press()	//通过修正参数计算最终压力值,修正算法来自BME280手册
{
    int64_t var1, var2, p;

    var1 = ((int64_t)bme280.t_fine) - 128000;
    var2 = var1 * var1 * (int64_t)bme280.P6;
    var2 = var2 + ((var1 * (int64_t)bme280.P5) << 17);
    var2 = var2 + (((int64_t)bme280.P4) << 35);
    var1 = ((var1 * var1 * (int64_t)bme280.P3) >> 8) +((var1 * (int64_t)bme280.P2) << 12);
    var1 =(((((int64_t)1) << 47) + var1)) * ((int64_t)bme280.P1) >> 33;

    if (var1 == 0)
    {
        return 0;
    }
    else
    {
        p = 1048576 - bme280.adc_P;
        p = (((p << 31) - var2) * 3125) / var1;
        var1 = (((int64_t)bme280.P9) * (p >> 13) * (p >> 13)) >> 25;
        var2 = (((int64_t)bme280.P8) * p) >> 19;
        p = ((p + var1 + var2) >> 8) + (((int64_t)bme280.P7) << 4);

        return (float)p/256;
    }
}

float compute_humi()	//通过修正参数计算最终湿度值
{
    double var_H;

    var_H = (((double)bme280.t_fine) - 76800.00);
    var_H = (bme280.adc_H - (((double)bme280.H4) * 64.0 + ((double)bme280.H5) / 16384.0 * var_H)) * (((double)bme280.H2) / 65536.0 * (1.0 + ((double)bme280.H6) / 67108864.0 * var_H * (1.0 + ((double)bme280.H3) / 67108864.0 * var_H)));
    var_H = var_H * (1.0 - ((double)bme280.H1) * var_H / 524288.0);

    if(var_H > 100.0)
    {
        var_H = 100.0;
    }
    else if(var_H < 0.0)
    {
        var_H = 0.0;
    }

    return var_H;
}

int main(int argc, char **argv)
{
	int fd;
	int len;

	float temp = 0, press = 0, humi = 0;
	
	fd = open("/dev/bme280", O_RDWR);
	if (fd == -1)
	{
		printf("can not open file /dev/bme280\n");
		return -1;
	}

	while(1)
	{
		len = read(fd, &bme280, sizeof(struct bme280_parameter));	
		
		temp = compute_temp();
		press = compute_press();
		humi = compute_humi();
		
		printf("temp=%.2f press=%.2f humi=%.2f\n", temp, press, humi);
		sleep(1);
	}
	
	close(fd);
	
	return 0;
}

三、总结

1、以上出现的专业术语或名词解释或个人理解有不妥,恳请指出!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/280329.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Matlab:K-means算法

K-means算法是一种常见的聚类算法&#xff0c;它将一组数据划分为K个不同的簇&#xff0c;以最小化每个簇内部数据点与簇中心之间的平方距离的总和为目标实现聚类。 1、基本步骤&#xff1a; 1.选择要划分的簇数K&#xff1b; 2.选择K个数据点作为初始的聚类中心&#xff1b…

链表精选题集

目录 1 链表翻转 题目链接&#xff1a; 解题&#xff1a; 试错版&#xff1a; 2 找中间节点 题目链接: 题解&#xff1a; 3 找倒数第k个节点 题目链接&#xff1a; 题解&#xff1a; 4 将两个升序链表合并为一个升序链表 题目链接&#xff1a; 题解&#xff1a; …

数据结构与算法 - 查找

文章目录 第1关&#xff1a;实现折半查找第2关&#xff1a;实现散列查找 第1关&#xff1a;实现折半查找 代码如下&#xff1a; /*************************************************************date: April 2009copyright: Zhu EnDO NOT distribute this code. ***********…

文章解读与仿真程序复现思路——电力自动化设备EI\CSCD\北大核心《面向平稳氢气需求的综合制氢系统鲁棒优化配置方法》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主的专栏栏目《论文与完整程序》 这个标题涉及到针对平稳氢气需求的综合制氢系统鲁棒优化配置方法。让我们逐步解读这个标题的关键要素&#xff1a; 面向平稳氢气需求&#xff1a; 这部分指…

超实用!CSDN个人数据Chrome插件开发

插件简介 相信写过博客的都知道&#xff0c;每天会经常打开自己的主页无数次&#xff0c;尤其是写了一篇新文章&#xff0c;就为了看文章浏览量增长了多少&#xff0c;文章获得了多少个赞&#xff0c;有多少人评论&#xff08;谁不想自己写的文章成为爆款呢&#xff5e;&#…

C# WPF上位机开发(Web API联调)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 很多时候&#xff0c;客户需要开发的不仅仅是一个上位机系统&#xff0c;它还有其他很多配套的系统或设备&#xff0c;比如物流小车、立库、数字孪…

【Maven】报错合集

问题1&#xff1a;com.github.everit-org.json-schema:org.everit.json.schema:pom:1.12.1 failed to transfer from http://localhost:8081/repository/maven-public/ during a previous attempt 发现原来是maven的settings.xml文件配置出现了问题。首先是之前maven进阶学习时…

【Java】一文讲解Java类加载机制

Java 类加载机制是 Java 运行时的核心组成部分&#xff0c;负责在程序运行过程中动态加载和连接类文件&#xff0c;并将其转换为可执行代码。理解类加载机制&#xff0c;能更容易理解你一行行敲下的Java代码是如何在JVM虚拟机上运行起来。并且理解类加载机制之后&#xff0c;我…

SpringBoot整合Canal

一 linux docker compose版本 1.第一步&#xff1a;基础环境 &#xff08;1&#xff09;第1步&#xff1a;安装jak、maven、git、nodejs、npm yum install maven mvn -v 安装maven时会帮安装jdkyum install git git --version 2.27.0yum in…

提升客户体验!十大热门客户服务软件解决方案推荐

现代企业深切认识到客户关系对于成功至关重要。如今&#xff0c;顾客越来越偏向于个性化和情境化服务的企业。根据Forrester的研究&#xff0c;将优先考虑建立更好客户关系以实现长期增长将是2023年业务成功的关键。 为了评估和改善客户关系&#xff0c;您需要一个系统化的方式…

DataFunSummit:2023年数据湖架构峰会-核心PPT资料下载

一、峰会简介 现今&#xff0c;很多企业每天都有PB级的数据注入到大数据平台&#xff0c;经过离线或实时的ETL建模后&#xff0c;提供给下游的分析、推荐及预测等场景使用。面对如此大规模的数据&#xff0c;无论是分析型场景、流批一体、增量数仓都得益于湖仓一体等数据湖技术…

数据分析硬核工具Origin各版本安装指南

下载链接 https://pan.baidu.com/s/12mENFtRFdNaLzVKmE6w_Uw?pwd0531 1.鼠标右击【Origin 2022(64bit)】压缩包&#xff08;win11及以上系统需先点击显示更多“选项”&#xff09;选择【解压到 Origin 2022(64bit)】。 2.双击打开解压后的【Origin 2022(64bit)】文件夹。 3.…

【Matlab】CNN卷积神经网络时序预测算法

资源下载&#xff1a; https://download.csdn.net/download/vvoennvv/88681558 一&#xff0c;概述 CNN&#xff08;Convolutional Neural Network&#xff0c;卷积神经网络&#xff09;是一种前馈神经网络&#xff0c;主要用于处理具有类似网格结构的数据&#xff0c;例如图像…

2023十大编程语言及未来展望

2023十大编程语言及未来展望 1. 2023年十大编程语言排行榜2. 十大编程语言未来展望PythonCCJavaC#JavaScriptPHPVisual BasicSQLAssembly language 1. 2023年十大编程语言排行榜 TIOBE排行榜是根据互联网上有经验的程序员、课程和第三方厂商的数量&#xff0c;并使用搜索引擎&a…

Python中的用户交互函数详解,提升用户体验!

更多Python学习内容&#xff1a;ipengtao.com 用户进行交互的Python应用程序&#xff0c;有许多常用的用户交互函数可以帮助创建更具吸引力和友好的用户界面。本文将介绍一些常用的Python用户交互函数&#xff0c;并提供详细的示例代码&#xff0c;以帮助大家更好地理解它们的用…

数字人私人定制

数字人是什么&#xff1f; 在回答这个问题之前&#xff0c;我们先回答另一个问题&#xff0c;人如何与人工智能交流&#xff1f;目前可以通过文字、语音、电脑屏幕、手机屏幕、平板、虚拟现实设备等和人工智能交流&#xff0c;为了得到更好的交流体验&#xff0c;人工智能必然…

CANopen DS402 Homing方法分析

本文主要分析CANopen DS402中各种Homing方法。 一 装置通用结构 讲解Homing方法前&#xff0c;需要了解一下装置的通用结构&#xff0c; 装置一般左右各有一个limit switch&#xff0c;即限位开关&#xff0c;用来控制移动范围&#xff0c;分别叫negative限位开关和positive…

Flowable-升级为7.0.0.M2-第二节

目录 替换变化的类和配置把javax.servlet 替换为 jakarta.servlet修改redis的配置配置logging.level.org.springframework.boot.autoconfigureerror避免影响视听 替换变化的类和配置 把javax.servlet 替换为 jakarta.servlet import javax.servlet.ServletContext; import ja…

运行时错误‘53’文件未找到:MathPage.WLL,安装MathType后Word不能复制粘贴问题的解决

两步解决&#xff1a; 1. 打开Word-->文件-->选项-->信任中心-->信任中心设置-->受信任位置&#xff0c;解决宏问题 添加如下受信任位置&#xff0c; 我的路径&#xff1a;C:\Program Files\Microsoft Office\root\Office16\STARTUP\ 2. 找到MathType下的MathT…