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

RK3566添加湿度传感器以及浅析hal层

RK3566添加一款温湿度传感器gxht3x.挂在i2c总线下。驱动部分就不多做解析。大致流程硬件接好i2c线以及vcc gnd。后看数据手册。初始化寄存器,然后要读数据的话读那个寄存器,读出来的数据要做一个转化,然后实现open read write ioctl函数就行了。本文主要讲解hal层 。直接贴驱动代码。

/* drivers/input/sensors/temperature/tmp_ms5607.c** Copyright (C) 2012-2015 ROCKCHIP.* Author: luowei <lw@rock-chips.com>** This software is licensed under the terms of the GNU General Public* License version 2, as published by the Free Software Foundation, and* may be copied, distributed, and modified under those terms.** This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the* GNU General Public License for more details.**/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/i2c.h>
#include <asm/io.h>
#include <asm/uaccess.h>#include <linux/miscdevice.h>
#include <linux/gpio.h>
#include <linux/uaccess.h>
#include <asm/atomic.h>
#include <linux/delay.h>
#include <linux/freezer.h>
#ifdef CONFIG_HAS_EARLYSUSPEND
#include <linux/earlysuspend.h>
#endif
#include <linux/sensor-dev.h>static int sensor_active(struct i2c_client *client, int enable, int rate)
{int result = 0;return result;
}static int sensor_init(struct i2c_client *client)
{int result = 0;return result;
}static int sensor_i2c_write(struct i2c_client *client,unsigned int len, unsigned char const *data)
{struct i2c_msg msgs[1];int res;msgs[0].addr = 0x44;msgs[0].flags = 0;	/* write */msgs[0].buf = (unsigned char *)data;msgs[0].len = len;res = i2c_transfer(client->adapter, msgs, 1);printk("wzf---i2c_transfer count = %d\n", res);return res;}static int senosr_i2c_read(struct i2c_client *client,unsigned int len, unsigned char *data)
{struct i2c_msg msgs[1];int res;printk("wzf:-----addr = %x-----\n",(int)client->addr);msgs[0].addr = 0x44;msgs[0].flags = I2C_M_RD;msgs[0].buf = data;msgs[0].len = len;res = i2c_transfer(client->adapter, msgs, 1);printk("wzf---i2c_transfer count = %d\n", res);return res;}static int humidity_report_value(struct input_dev *input, int data)
{//get temperature, high and temperature from register dataprintk("ms5607-----hum report data= %d\n",data);input_report_abs(input, ABS_VOLUME, data);input_sync(input);msleep(100);return 0;
}static int sensor_report_value(struct i2c_client *client)
{int ret = 0;unsigned int tem = 0,hum = 0;int Temperature=0,Humidity=0;char recvbuffer[6];char sendbuffer[2] = {0x2C,0x10};struct sensor_private_data *sensor =(struct sensor_private_data *) i2c_get_clientdata(client);printk("wzf:--------%s---------\n",__func__);memset(recvbuffer, 0, 6);ret = sensor_i2c_write(client, 2, sendbuffer);if (!ret){printk("sensor_i2c_read failed!\n");//return -1;}msleep(2);ret = senosr_i2c_read(client, 6, recvbuffer);if (!ret){printk("sensor_i2c_read failed!\n");//return -1;}printk("read recvbuffer= %s-----\n",recvbuffer);tem = ((recvbuffer[0]<<8) | recvbuffer[1]);//温度拼接hum = ((recvbuffer[3]<<8) | recvbuffer[4]);//湿度拼接printk("wzf:ms5607 hum =%d\n",hum);printk("wzf:ms5607 temp =%d\n",tem);/*转换实际温度*/Temperature= (175* tem/65535-45) ;// T = -45 + 175 * tem / (2^16-1)//Temperature =(315*tem/65535-49);Humidity= (100* hum/65535);// RH = hum*100 / (2^16-1)printk("---Temp : %d  Hum: %d ----\n",Temperature,Humidity);//Humidity=950;if(!Humidity)return 0;ret = humidity_report_value(sensor->input_dev, Humidity);return 0;
}struct sensor_operate humidity_gxht3x_ops = {.name				= "hum_gxht3x",.type				= SENSOR_TYPE_HUMIDITY,	//sensor type and it should be correct.id_i2c				= HUMIDITY_ID_GXHT3X,	//i2c id number.read_reg			= SENSOR_UNKNOW_DATA,	//read data.read_len			= 2,			//data length.id_reg				= SENSOR_UNKNOW_DATA,	//read device id from this register.id_data 			= SENSOR_UNKNOW_DATA,	//device id.precision			= 16,		//8 bits.ctrl_reg 			= SENSOR_UNKNOW_DATA,	//enable or disable.int_status_reg 		= SENSOR_UNKNOW_DATA,	//intterupt status register.range				= {0,65535},		//range.trig				= IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,.active				= sensor_active,.init				= sensor_init,.report				= sensor_report_value,
};/****************operate according to sensor chip:end************/
static int humidity_gxht3x_probe(struct i2c_client *client, const struct i2c_device_id *devid)
{printk("wzf:----%s----\n",__func__);return sensor_register_device(client, NULL, devid, &humidity_gxht3x_ops);
}static int humidity_gxht3x_remove(struct i2c_client *client)
{return sensor_unregister_device(client, NULL, &humidity_gxht3x_ops);
}static const struct i2c_device_id humidity_gxht3x_id[] = {{"hum_gxht3x", HUMIDITY_ID_GXHT3X},{}
};static struct i2c_driver humidity_ms5607_driver = {.probe = humidity_gxht3x_probe,.remove = humidity_gxht3x_remove,.shutdown = sensor_shutdown,.id_table = humidity_gxht3x_id,.driver = {.name = "humidity_gxht3x",#ifdef CONFIG_PM.pm = &sensor_pm_ops,#endif},
};module_i2c_driver(humidity_ms5607_driver);MODULE_AUTHOR("luowei <lw@rock-chips.com>");
MODULE_DESCRIPTION("ms5607 temperature driver");
MODULE_LICENSE("GPL");

接下来对hal层进行浅析hal对于驱动来说还是要会的。我也不会,在网上找资料找出来的如有错误希望各位大佬能指出。
在这里插入图片描述
在这里插入图片描述
以上资料来自博主~未来可期点击看大佬的文章
总结一下:
对于我们的湿度传感器来说:(kernel 层驱动通过i2c读取寄存器拿到湿度数据) —fileoperation---->(hardware层通过open节点,以及ioctl获取到数据,填充这些结构体.hw_device_t 填充模块ID 名称 描述 版本等信息。hw_moule_ts实现功能函数。等jni层获取到该结构体指针的时候可以调用这些功能函数)------jni-------->(framewark层注册java native interface.java本地接口,以便上层调用)------->apk.
那我们看hal层代码就先从这三个结构体入手。

hardware\libhardware\include\hardware\hardware.h
struct hw_module_t;
struct hw_module_methods_t;
struct hw_device_t;/*** Every hardware module must have a data structure named HAL_MODULE_INFO_SYM* and the fields of this data structure must begin with hw_module_t* followed by module specific information.*/
typedef struct hw_module_t {/** tag must be initialized to HARDWARE_MODULE_TAG */uint32_t tag;/*** The API version of the implemented module. The module owner is* responsible for updating the version when a module interface has* changed.** The derived modules such as gralloc and audio own and manage this field.* The module user must interpret the version field to decide whether or* not to inter-operate with the supplied module implementation.* For example, SurfaceFlinger is responsible for making sure that* it knows how to manage different versions of the gralloc-module API,* and AudioFlinger must know how to do the same for audio-module API.** The module API version should include a major and a minor component.* For example, version 1.0 could be represented as 0x0100. This format* implies that versions 0x0100-0x01ff are all API-compatible.** In the future, libhardware will expose a hw_get_module_version()* (or equivalent) function that will take minimum/maximum supported* versions as arguments and would be able to reject modules with* versions outside of the supplied range.*/uint16_t module_api_version;
#define version_major module_api_version/*** version_major/version_minor defines are supplied here for temporary* source code compatibility. They will be removed in the next version.* ALL clients must convert to the new version format.*//*** The API version of the HAL module interface. This is meant to* version the hw_module_t, hw_module_methods_t, and hw_device_t* structures and definitions.** The HAL interface owns this field. Module users/implementations* must NOT rely on this value for version information.** Presently, 0 is the only valid value.*/uint16_t hal_api_version;
#define version_minor hal_api_version/** Identifier of module */const char *id;/** Name of this module */const char *name;/** Author/owner/implementor of the module */const char *author;/** Modules methods */struct hw_module_methods_t* methods;/** module's dso */void* dso;#ifdef __LP64__uint64_t reserved[32-7];
#else/** padding to 128 bytes, reserved for future use */uint32_t reserved[32-7];
#endif} hw_module_t;typedef struct hw_module_methods_t {/** Open a specific device */int (*open)(const struct hw_module_t* module, const char* id,struct hw_device_t** device);} hw_module_methods_t;/*** Every device data structure must begin with hw_device_t* followed by module specific public methods and attributes.*/
typedef struct hw_device_t {/** tag must be initialized to HARDWARE_DEVICE_TAG */uint32_t tag;/*** Version of the module-specific device API. This value is used by* the derived-module user to manage different device implementations.** The module user is responsible for checking the module_api_version* and device version fields to ensure that the user is capable of* communicating with the specific module implementation.** One module can support multiple devices with different versions. This* can be useful when a device interface changes in an incompatible way* but it is still necessary to support older implementations at the same* time. One such example is the Camera 2.0 API.** This field is interpreted by the module user and is ignored by the* HAL interface itself.*/uint32_t version;/** reference to the module this device belongs to */struct hw_module_t* module;/** padding reserved for future use */
#ifdef __LP64__uint64_t reserved[12];
#elseuint32_t reserved[12];
#endif/** Close this device */int (*close)(struct hw_device_t* device);} hw_device_t;

然后我们在看sensor中定义的结构体

\hardware\libhardware\include\hardware\sensors.h
/*** Every hardware module must have a data structure named HAL_MODULE_INFO_SYM* and the fields of this data structure must begin with hw_module_t* followed by module specific information.*/
struct sensors_module_t {struct hw_module_t common;/*** Enumerate all available sensors. The list is returned in "list".* return number of sensors in the list*/int (*get_sensors_list)(struct sensors_module_t* module,struct sensor_t const** list);/***  Place the module in a specific mode. The following modes are defined**  0 - Normal operation. Default state of the module.*  1 - Loopback mode. Data is injected for the supported*      sensors by the sensor service in this mode.* return 0 on success*         -EINVAL if requested mode is not supported*         -EPERM if operation is not allowed*/int (*set_operation_mode)(unsigned int mode);
};/** sensors_poll_device_t is used with SENSORS_DEVICE_API_VERSION_0_1* and is present for backward binary and source compatibility.* See the Sensors HAL interface section for complete descriptions of the* following functions:* http://source.android.com/devices/sensors/index.html#hal*/
struct sensors_poll_device_t {struct hw_device_t common;int (*activate)(struct sensors_poll_device_t *dev,int sensor_handle, int enabled);int (*setDelay)(struct sensors_poll_device_t *dev,int sensor_handle, int64_t sampling_period_ns);int (*poll)(struct sensors_poll_device_t *dev,sensors_event_t* data, int count);
};

这里主要定义了俩个结构体 :struct sensors_module_t , 里面包含了 hw_module_t ; 那hw_module_t我们之前说是填充模块信息的包括ID 名称等等。但是它里面还包含了俩个函数 get_sensors_list 这个函数将返回所有可以的传感器列表。set_operation_mode:将模块设置特定模式:0 正常模式 1回环模式。第二个结构体:struct sensors_poll_device_t ,里面包含了struct hw_device_t;struct hw_device_t里面是特定的实现函数,但是我们还要增加我们自己的功能函数activate ,setDelay ,poll。
ok,我查看在libhardware下的头文件定义。接下来看具体的实现。

hardware\rockchip\sensor\st\sensors.c
/*  sensors_module_t 填充hw_module_t的 模块描述 */struct sensors_module_t HAL_MODULE_INFO_SYM = {.common = {.tag = HARDWARE_MODULE_TAG,.version_major = 1,.version_minor = 0,.id = SENSORS_HARDWARE_MODULE_ID,.name = "Rockchip Sensors Module",.author = "The RKdroid Project",.methods = &sensors_module_methods,},.get_sensors_list = sensors__get_sensors_list
};
/* hw_module_methods_t 实现open函数  */
static struct hw_module_methods_t sensors_module_methods = {.open = open_sensors
};
/* 实现sensor.h中 sensors_module_t结构体中 get_sensors_list函数  */
static int sensors__get_sensors_list(struct sensors_module_t* module,struct sensor_t const** list)
{*list = sSensorList;return ARRAY_SIZE(sSensorList);
}

那么sensors_poll_device_t的几个函数的实现都没有写???这个要看具体设备再具体实现。
直接看湿度传感器hal层结构体定义。

hardware\rockchip\sensor\st\HumiditySensor.h
class HumiditySensor : public SensorBase {int mEnabled;InputEventCircularReader mInputReader;sensors_event_t mPendingEvent;  bool mHasPendingEvent;int setInitialState();public:HumiditySensor();virtual ~HumiditySensor();virtual int setDelay(int32_t handle, int64_t ns);virtual int enable(int32_t handle, int enabled);virtual int readEvents(sensors_event_t* data, int count);   virtual bool hasPendingEvents() const;virtual int isActivated(int handle);void processEvent(int code, int value);
};/*****************************************************************************/#define HUMIDITY_IOCTL_MAGIC			'h'
#define HUMIDITY_IOCTL_GET_ENABLED	_IOR(HUMIDITY_IOCTL_MAGIC, 1, int *)
#define HUMIDITY_IOCTL_ENABLE			_IOW(HUMIDITY_IOCTL_MAGIC, 2, int *)
#define HUMIDITY_IOCTL_DISABLE		_IOW(HUMIDITY_IOCTL_MAGIC, 3, int *)
#define HUMIDITY_IOCTL_SET_DELAY		_IOW(HUMIDITY_IOCTL_MAGIC, 4, int *)

class HumiditySensor : public SensorBase ; 可以看出class HumiditySensor 继承了SensorBase,那我们看一下class SensorBase

struct sensors_event_t;class SensorBase {
protected:const char* dev_name;const char* data_name;int         dev_fd;int         data_fd;static int openInput(const char* inputName);static int64_t getTimestamp();static int64_t timevalToNano(timeval const& t) {return t.tv_sec*1000000000LL + t.tv_usec*1000;}int open_device();int close_device();public:SensorBase(const char* dev_name,const char* data_name);virtual ~SensorBase();virtual int readEvents(sensors_event_t* data, int count) = 0;virtual bool hasPendingEvents() const;virtual int getFd() const;virtual int setDelay(int32_t handle, int64_t ns);virtual int enable(int32_t handle, int enabled) = 0;virtual int isActivated(int handle);
};

这里的setdelay isActivated readEvents不就是sensors_poll_device_t里面的功能实现函数。同时在HumiditySensor类里面也实现了这几个函数。查看class HumiditySensor里面成员的实现。

/** Copyright (C) 2010 Motorola, Inc.* Copyright (C) 2008 The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**      http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/#include <fcntl.h>
#include <errno.h>
#include <math.h>
#include <poll.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/select.h>#include "HumiditySensor.h"/*****************************************************************************/HumiditySensor::HumiditySensor(): SensorBase(HUM_DEVICE_NAME, "humidity"),mEnabled(0),mInputReader(32),mHasPendingEvent(false)
{LOGD("new class humidity");mPendingEvent.version = sizeof(sensors_event_t);mPendingEvent.sensor = ID_HUM;mPendingEvent.type = SENSOR_TYPE_RELATIVE_HUMIDITY;memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));open_device();int flags = 0;if ((dev_fd > 0) && (!ioctl(dev_fd, HUMIDITY_IOCTL_GET_ENABLED, &flags))) {if (flags) {mEnabled = 1;setInitialState();}}
}HumiditySensor::~HumiditySensor() {LOGD("delete class humidity");if (dev_fd > 0) {close(dev_fd);dev_fd = -1;}
}int HumiditySensor::setInitialState() {struct input_absinfo absinfo;if ((data_fd > 0) && !ioctl(data_fd, EVIOCGABS(EVENT_TYPE_HUMIDITY), &absinfo)) {mHasPendingEvent = true;mPendingEvent.relative_humidity = CONVERT_B * absinfo.value;}return 0;
}int HumiditySensor::enable(int32_t, int en) {int flags = en ? 1 : 0;int err = 0;if (flags != mEnabled) {if (dev_fd < 0) {open_device();}err = ioctl(dev_fd, HUMIDITY_IOCTL_ENABLE, &flags);err = err<0 ? -errno : 0;LOGE_IF(err, "HUMIDITY_IOCTL_ENABLE failed (%s)", strerror(-err));if (!err) {mEnabled = en ? 1 : 0;if (en) {setInitialState();}}}return err;
}bool HumiditySensor::hasPendingEvents() const {return mHasPendingEvent;
}int HumiditySensor::setDelay(int32_t handle, int64_t ns)
{if (ns < 0)return -EINVAL;if (dev_fd < 0) {open_device();}int delay = ns / 1000000;if (ioctl(dev_fd, HUMIDITY_IOCTL_SET_DELAY, &delay)) {return -errno;}return 0;
}int HumiditySensor::isActivated(int /* handle */)
{return mEnabled;
}int HumiditySensor::readEvents(sensors_event_t* data, int count)
{if (count < 1)return -EINVAL;if (mHasPendingEvent) {mHasPendingEvent = false;mPendingEvent.timestamp = getTimestamp();*data = mPendingEvent;return mEnabled ? 1 : 0;}ssize_t n = mInputReader.fill(data_fd);if (n < 0)return n;int numEventReceived = 0;input_event const* event;while (count && mInputReader.readEvent(&event)) {int type = event->type;if (type == EV_ABS) {processEvent(event->code, event->value);} else if (type == EV_SYN) {int64_t time = timevalToNano(event->time);mPendingEvent.timestamp = time;if (mEnabled) {*data++ = mPendingEvent;count--;numEventReceived++;}} else {ALOGE("HumiditySensor: unknown event (type=%d, code=%d)",type, event->code);}mInputReader.next();}return numEventReceived;
}void HumiditySensor::processEvent(int code, int value)
{if (code == EVENT_TYPE_HUMIDITY) {//mPendingEvent.relative_humidity = value * CONVERT_B ;mPendingEvent.relative_humidity = value;LOGD("HUM---%s:value=%d\n",__FUNCTION__, value);LOGD("HUM---%s:value * CONVERT_B = %f\n",__FUNCTION__, mPendingEvent.relative_humidity);}
}

里面的核心函数就是open 然后ioctl发送不同的魔数去获取到数据。那么我们的hal层拿到数据只是完成了启下作用,即从内核驱动中获取数据。那么我们还要把数据给到JNI。由于hal层和farmware层都是运行在用户空间,jni也是由C/C++编写。并且hal层是以.so的动态库文件的形式存在。那么我们只要在jni包含该库文件就可以。调用到我们的功能函数。

相关文章:

RK3566添加湿度传感器以及浅析hal层

RK3566添加一款温湿度传感器gxht3x.挂在i2c总线下。驱动部分就不多做解析。大致流程硬件接好i2c线以及vcc gnd。后看数据手册。初始化寄存器&#xff0c;然后要读数据的话读那个寄存器&#xff0c;读出来的数据要做一个转化,然后实现open read write ioctl函数就行了。本文主要…...

看了这份Java高级笔试宝典覆盖近3年Java笔试中98%高频知识点,反打面试官

首先声明&#xff1a; 本书覆盖了近3年程序员面试笔试中超过98%Java高频知识点&#xff0c;当你细细品读完本书后&#xff0c;面试都是小问题。 一书在手/工作不愁 记住重点&#xff0c;考试要考 前言 程序员求职始终是当前社会的一个热点&#xff0c;而市面上有很多关于程…...

从0到1搭建大数据平台之监控

大家好&#xff0c;我是脚丫先生 (o^^o) 大数据平台设计中&#xff0c;监控系统尤为重要。 它时刻关乎大数据开发人员的幸福感。 试想如果半夜三更&#xff0c;被电话吵醒解决集群故障问题&#xff0c;那是多么的痛苦&#xff01;&#xff01;&#xff01; 但是不加班是不可…...

采购评标管理过程是怎样的?有哪些评标标准?

采购活动的评标是检查和比较投标的有组织的过程&#xff0c;以选择最佳报价&#xff0c;努力获得实现企业目标所需的货物、工程和服务。 评标是由一个被称为评标小组的机构负责。这个小组如何称呼&#xff0c;取决于企业的情况。同义词有报价审查小组、投标审查委员会或投标审…...

《Vue+Spring Boot前后端分离开发实战》专著累计发行上万册

杰哥的学术专著《VueSpring Boot前后端分离开发实战》由清华大学出版社于2021年3月首次出版发行&#xff0c;虽受疫情影响但热度不减&#xff0c;受到业界读者的热捧&#xff0c;截至今日加印5次&#xff0c;累计发行12000册&#xff0c;引领读者开发前后端分离项目&#xff0c…...

类与类之间的关系有哪几种?

文章目录程序设计要素1.可读性2.健壮性3.优化4.复用性5.可扩展性设计类的关系遵循的原则1、 高内聚低耦合2、面向对象开发中 “针对接口编程优于针对实现编程”&#xff0c;”组合优于继承” 的总体设计类与类之间的关系&#xff08;即事物关系&#xff09; A is-a B 泛化&…...

LeetCode 606.根据二叉树创建字符串,102.二叉树的层序遍历和牛客 二叉搜索树与双向链表

文章目录1. 根据二叉树创建字符串2. 二叉树的层序遍历3. 二叉搜索树与双向链表1. 根据二叉树创建字符串 难度 简单 题目链接 解题思路&#xff1a; 这里的意思就是&#xff1a;用前序遍历遍历这颗树。然后左子树和右子树分别在一个括号里。括号里的规则是&#xff1a; 1.左右都…...

02-18 周六 图解机器学习之SMV 第五章5-2

02-18 周六 图解机器学习之SMV 第五章5-2时间版本修改人描述2023年2月18日11:47:18V0.1宋全恒新建文档 环境 程序的基本环境&#xff0c;是使用了jupyter&#xff0c;在容器中运行的。 简介 本程序主要演示支持向量的获取&#xff0c;支持向量是距离超平面最近的点组成的。程序…...

Spring Boot系列--创建第一个Spring Boot项目

1.项目搭建 在IDEA中新建项目&#xff0c;选择Spring Initializr。 填写项目信息&#xff1a; 选择版本和Spring Web依赖&#xff1a; Spring Web插件能为项目集成Tomcat、配置dispatcherServlet和xml文件。此处选择的版本若为3.0.2的话会出现如下错误&#xff1a; java: …...

手把手教你用React Hook和TypeScript从零实现虚拟滚动列表组件

前言 k8s 全称 kubernetes&#xff0c;这个名字大家应该都不陌生&#xff0c;k8s是为容器服务而生的一个可移植容器的编排管理工具&#xff0c;集应用的部署和运维&#xff0c;负载均衡&#xff0c;服务发现和扩容&#xff0c;版本回滚于一身&#xff0c;越来越多的公司正在拥…...

界面控件DevExpress WPF Pivot Grid——拥有强大多维数据分析能力!

界面控件DevExpress WPF的Pivot Grid组件是一个类似excel的数据透视表&#xff0c;用于多维数据分析和跨选项卡报表生成。它拥有众多的布局自定义选项&#xff0c;允许开发者完全控制其UI且以用户为中心的功能使其易于部署。PS&#xff1a;DevExpress WPF拥有120个控件和库&…...

python字典及基础操作

1) 字典是没有顺序的&#xff0c;是任意对象的无序集合。 2) 字典的键是唯一的&#xff0c;不能多次出现&#xff0c;多次出现时取最后一个值。 3) 键是不可变的。 4) 字典中的元素可增删。 5) 因为没有顺序&#xff0c;所以不存在索引。 1. 字典元素的访问 >>> …...

Windows Server 2008 R2安装onlyoffice【docker】

目录 前言 准备工作 安装docker 安装onlyoffice 常见问题 前言 目前docker for windows只能在windows10/11上安装&#xff0c;其他的windows版本只能使用Docker Toolbox来安装&#xff0c;使用该工具安装的docker其实是借助了Oracle VM VirtualBox虚拟机来运行的&a…...

JVM学习笔记六:运行时数据区之堆

目录 概述 堆空间内部结构 JDK7版本 JDK8版本 堆空间的内存划分 堆空间大小设置参数 概述 Java堆是虚拟机所管理的内存中最大的一块&#xff0c;其在JVM启动时即被创建&#xff0c;并且空间大小也被确定&#xff08;这里是不考虑Java8之后以本地内存来实现的元空间&…...

usb闪存驱动器数据恢复该怎么进行?3个方法总结

“怎么办&#xff1f;我的USB驱动器不知道因为什么原因&#xff0c;里面的数据、文件都消失了。有没有什么方法在没有进行备份的情况下恢复从U盘丢失的数据&#xff1f;” USB驱动器作为最常用的存储移动设备&#xff0c;里面保存着各种文件数据。但是有时会出现损坏而导致数据…...

DAX 微信 markdown 编辑器

DAX 微信 markdown 编辑器 一、致谢 感谢开源项目&#xff1a; md wechat-format 感谢 WordPress 插件 Mine云点播 作者 mine27 的指导。 二、如何使用 打开如下地址&#xff0c;直接编辑&#xff0c;可以实时看到符合微信公众号排版的效果。 推荐访问&#xff1a;https://j…...

湖南中创教育为学员提供方便快速的退费服务

2006年&#xff0c;湖南中创教育科技有限公司创始人团队开始创业进入职业教育行业&#xff1b;2014年公司正式成立&#xff0c;组建专业团队并转型升级“互联网”&#xff0c;进入在线教育行业。 自主研发“中创网校”学习平台&#xff0c;为学员提供了集直播、视频回放复习、…...

Java 给视频添加背景音乐 | Java工具

目录 前言 Maven依赖 环境依赖 代码 总结 前言 本文提供给视频添加背景音乐的java工具&#xff0c;一如既往的实用主义。 Maven依赖 <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30.1.1…...

【JUC2022】第二章 多线程锁

【JUC2022】第二章 多线程锁 文章目录【JUC2022】第二章 多线程锁一、乐观锁与悲观锁1.悲观锁2.乐观锁二、八锁案例1.标准情况&#xff0c;有a、b两个线程&#xff0c;请问先打印邮件还是短信【结果&#xff1a;邮件】2.sendEmail方法中加入暂停3秒钟&#xff0c;请问先打印邮件…...

快学会这个技能-.NET API拦截技法

大家好&#xff0c;我是沙漠尽头的狼。 本文先抛出以下问题&#xff0c;请在文中寻找答案&#xff0c;可在评论区回答&#xff1a; 什么是API拦截&#xff1f;一个方法被很多地方调用&#xff0c;怎么在不修改这个方法源码情况下&#xff0c;记录这个方法调用的前后时间&…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄

文&#xff5c;魏琳华 编&#xff5c;王一粟 一场大会&#xff0c;聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中&#xff0c;汇集了学界、创业公司和大厂等三方的热门选手&#xff0c;关于多模态的集中讨论达到了前所未有的热度。其中&#xff0c;…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

基础测试工具使用经验

背景 vtune&#xff0c;perf, nsight system等基础测试工具&#xff0c;都是用过的&#xff0c;但是没有记录&#xff0c;都逐渐忘了。所以写这篇博客总结记录一下&#xff0c;只要以后发现新的用法&#xff0c;就记得来编辑补充一下 perf 比较基础的用法&#xff1a; 先改这…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

Robots.txt 文件

什么是robots.txt&#xff1f; robots.txt 是一个位于网站根目录下的文本文件&#xff08;如&#xff1a;https://example.com/robots.txt&#xff09;&#xff0c;它用于指导网络爬虫&#xff08;如搜索引擎的蜘蛛程序&#xff09;如何抓取该网站的内容。这个文件遵循 Robots…...

06 Deep learning神经网络编程基础 激活函数 --吴恩达

深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

C# 表达式和运算符(求值顺序)

求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如&#xff0c;已知表达式3*52&#xff0c;依照子表达式的求值顺序&#xff0c;有两种可能的结果&#xff0c;如图9-3所示。 如果乘法先执行&#xff0c;结果是17。如果5…...