OpenHarmony开发实战:GPIO控制器接口

 功能简介

GPIO(General-purpose input/output)即通用型输入输出。通常,GPIO控制器通过分组的方式管理所有GPIO管脚,每组GPIO有一个或多个寄存器与之关联,通过读写寄存器完成对GPIO管脚的操作。

GPIO接口定义了操作GPIO管脚的标准方法集合,包括:

  • 设置、获取管脚方向:方向可以是输入或者输出(暂不支持高阻态)。

  • 读、写管脚电平值:电平值可以是低电平或高电平。

  • 设置、取消管脚中断服务函数:设置一个管脚的中断响应函数,以及中断触发方式。取消一个管脚的中断服务函数。

  • 使能、禁止管脚中断:禁止或使能管脚中断。

基本概念

GPIO又俗称为I/O口,I指的是输入(in),O指的是输出(out)。可以通过软件来控制其输入和输出,即I/O控制。

  • GPIO输入

    输入是检测各个引脚上的电平状态,高电平或者低电平状态。常见的输入模式有:模拟输入、浮空输入、上拉输入、下拉输入。

  • GPIO输出

    输出是当需要控制引脚电平的高低时需要用到输出功能。常见的输出模式有:开漏输出、推挽输出、复用开漏输出、复用推挽输出。

运作机制

在HDF框架中,同类型设备对象较多时(可能同时存在十几个同类型配置器),若采用独立服务模式,则需要配置更多的设备节点,且相关服务会占据更多的内存资源。相反,采用统一服务模式可以使用一个设备服务作为管理器,统一处理所有同类型对象的外部访问(这会在配置文件中有所体现),实现便捷管理和节约资源的目的。GPIO模块接口适配模式采用统一服务模式(如图1所示)。

在统一模式下,所有的控制器都被核心层统一管理,并由核心层统一发布一个服务供接口层,因此这种模式下驱动无需再为每个控制器发布服务。

GPIO模块各分层作用:

  • 接口层提供操作GPIO管脚的标准方法。

  • 核心层主要提供GPIO管脚资源匹配,GPIO管脚控制器的添加、移除以及管理的能力,通过钩子函数与适配层交互,供芯片厂家快速接入HDF框架。

  • 适配层主要是将钩子函数的功能实例化,实现具体的功能。

图 1 GPIO统一服务模式结构图

GPIO统一服务模式结构图

使用指导

场景介绍

GPIO主要是对GPIO管脚资源进行管理。开发者可以使用提供的GPIO操作接口,实现对管脚控制的具体控制。

接口说明

GPIO模块提供的主要接口如表1所示。具体API详见//drivers/hdf_core/framework/include/platform/gpio_if.h。

表 1 GPIO驱动API接口功能介绍

接口名描述
GpioGetByName(const char *gpioName)获取GPIO管脚ID
int32_t GpioRead(uint16_t gpio, uint16_t *val)读GPIO管脚电平值
int32_t GpioWrite(uint16_t gpio, uint16_t val)写GPIO管脚电平值
int32_t GpioGetDir(uint16_t gpio, uint16_t *dir)获取GPIO管脚方向
int32_t GpioSetDir(uint16_t gpio, uint16_t dir)设置GPIO管脚方向
int32_t GpioUnsetIrq(uint16_t gpio, void *arg)取消GPIO管脚对应的中断服务函数
int32_t GpioSetIrq(uint16_t gpio, uint16_t mode, GpioIrqFunc func, void *arg)设置GPIO管脚对应的中断服务函数
int32_t GpioEnableIrq(uint16_t gpio)使能GPIO管脚中断
int32_t GpioDisableIrq(uint16_t gpio)禁止GPIO管脚中断

说明:
本文涉及GPIO的所有接口,支持内核态及用户态使用。

开发步骤

GPIO标准API通过GPIO管脚号来操作指定管脚,使用GPIO的一般流程如图2所示。

图 2 GPIO使用流程图

GPIO使用流程图

确定GPIO管脚号

两种方式获取管脚号:根据SOC芯片规则进行计算、通过管脚别名获取

  • 根据SOC芯片规则进行计算

    不同SOC芯片由于其GPIO控制器型号、参数、以及控制器驱动的不同,GPIO管脚号的换算方式不一样。

    • Hi3516DV300

      控制器管理12组GPIO管脚,每组8个。

      GPIO号 = GPIO组索引 (0~11) * 每组GPIO管脚数(8) + 组内偏移

      举例:GPIO10_3的GPIO号 = 10 * 8 + 3 = 83

    • Hi3518EV300

      控制器管理10组GPIO管脚,每组10个。

      GPIO号 = GPIO组索引 (0~9) * 每组GPIO管脚数(10) + 组内偏移

      举例:GPIO7_3的GPIO管脚号 = 7 * 10 + 3 = 73

  • 通过管脚别名获取

    调用接口GpioGetByName进行获取,入参是该管脚的别名,接口返回值是管脚的全局ID。

    GpioGetByName(const char *gpioName);
设置GPIO管脚方向

在进行GPIO管脚读写前,需要先通过如下函数设置GPIO管脚方向:

int32_t GpioSetDir(uint16_t gpio, uint16_t dir);

表 2 GpioSetDir参数和返回值描述

参数参数描述
gpiouint16_t类型,GPIO管脚号
diruint16_t类型,待设置的方向值
返回值返回值描述
HDF_SUCCESS设置GPIO管脚方向成功
负数设置GPIO管脚方向失败

假设需要将GPIO管脚3的方向配置为输出,其使用示例如下:

int32_t ret;

ret = GpioSetDir(3, GPIO_DIR_OUT);    // 将3号GPIO管脚配置为输出
if (ret != HDF_SUCCESS) {
    HDF_LOGE("GpioSetDir: gpio set dir fail, ret:%d\n", ret);
    return ret;
}
获取GPIO管脚方向

可以通过如下函数获取GPIO管脚方向:

int32_t GpioGetDir(uint16_t gpio, uint16_t *dir);

表 3 GpioGetDir参数和返回值描述

参数参数描述
gpiouint16_t类型,GPIO管脚号
diruint16_t类型指针,获取到的方向值
返回值返回值描述
HDF_SUCCESS获取GPIO管脚方向成功
负数获取GPIO管脚方向失败

假设需要获取GPIO管脚3的方向,其使用示例如下:

int32_t ret;
uin16_t dir;

ret = GpioGetDir(3, &dir);    // 获取3号GPIO管脚方向
if (ret != HDF_SUCCESS) {
    HDF_LOGE("GpioGetDir: gpio get dir fail, ret:%d\n", ret);
    return ret;
}
读取GPIO管脚电平值

如果要读取一个GPIO管脚电平,通过以下函数完成:

int32_t GpioRead(uint16_t gpio, uint16_t *val);

表 4 GpioRead参数和返回值描述

参数参数描述
gpiouint16_t类型,GPIO管脚号
valuint16_t类型指针,接收读取电平值
返回值返回值描述
HDF_SUCCESS读取GPIO管脚电平值成功
负数读取GPIO管脚电平值失败

假设需要读取GPIO管脚3的电平值,其使用示例如下:

int32_t ret;
uint16_t val;

ret = GpioRead(3, &val);    // 读取3号GPIO管脚电平值
if (ret != HDF_SUCCESS) {
    HDF_LOGE("GpioRead: gpio read fail, ret:%d\n", ret);
    return ret;
}
写入GPIO管脚电平值

如果要向GPIO管脚写入电平值,通过以下函数完成:

int32_t GpioWrite(uint16_t gpio, uint16_t val);

表 5 GpioWrite参数和返回值描述

参数参数描述
gpiouint16_t类型,GPIO管脚号
valuint16_t类型,待写入的电平值
返回值返回值描述
HDF_SUCCESS写入GPIO管脚电平值成功
负数写入GPIO管脚电平值失败

假设需要给GPIO管脚3写入低电平值,其使用示例如下:

int32_t ret;

ret = GpioWrite(3, GPIO_VAL_LOW);    // 给3号GPIO管脚写入低电平值
if (ret != HDF_SUCCESS) {
    HDF_LOGE("GpioWrite: gpio write fail, ret:%d\n", ret);
    return ret;
}
设置GPIO管脚中断

如果要为一个GPIO管脚设置中断响应程序,使用如下函数:

int32_t GpioSetIrq(uint16_t gpio, uint16_t mode, GpioIrqFunc func, void *arg);

表 6 GpioSetIrq参数和返回值描述

参数参数描述
gpiouint16_t类型,GPIO管脚号
modeuint16_t类型,中断触发模式
func函数指针,中断服务程序
arg无类型指针,传递给中断服务程序的入参
返回值返回值描述
HDF_SUCCESS设置GPIO管脚中断成功
负数设置GPIO管脚中断失败

注意:
同一时间,只能为某个GPIO管脚设置一个中断服务函数,如果重复调用GpioSetIrq函数,则之前设置的中断服务函数会被取代。

取消GPIO管脚中断

当不再需要响应中断服务函数时,使用如下函数取消中断设置:

int32_t GpioUnsetIrq(uint16_t gpio, void *arg);

表 7 GpioUnsetIrq参数和返回值描述

参数参数描述
gpiouint16_t类型,GPIO管脚号
arg无类型指针,GPIO中断数据
返回值返回值描述
HDF_SUCCESS取消GPIO管脚中断成功
负数取消GPIO管脚中断失败
使能GPIO管脚中断

在中断服务程序设置完成后,还需要先通过如下函数使能GPIO管脚的中断:

int32_t GpioEnableIrq(uint16_t gpio);

表 8 GpioEnableIrq参数和返回值描述

参数参数描述
gpiouint16_t类型,GPIO管脚号
返回值返回值描述
HDF_SUCCESS使能GPIO管脚中断成功
负数使能GPIO管脚中断失败

注意:
必须通过此函数使能管脚中断,之前设置的中断服务函数才能被正确响应。

禁止GPIO管脚中断

如果要临时屏蔽此中断,可以通过如下函数禁止GPIO管脚中断:

int32_t GpioDisableIrq(uint16_t gpio);

表 9 GpioDisableIrq参数和返回值描述

参数参数描述
gpiouint16_t类型,GPIO管脚号
返回值返回值描述
HDF_SUCCESS禁止GPIO管脚中断成功
负数禁止GPIO管脚中断失败

中断相关操作示例:

// 中断服务函数
int32_t MyCallBackFunc(uint16_t gpio, void *data)
{
    HDF_LOGI("MyCallBackFunc: gpio:%u interrupt service in data.\n", gpio);
    return HDF_SUCCESS;
}

int32_t ret;
// 设置中断服务程序为MyCallBackFunc,入参为NULL,中断触发模式为上升沿触发
ret = GpioSetIrq(3, OSAL_IRQF_TRIGGER_RISING, MyCallBackFunc, NULL);
if (ret != HDF_SUCCESS) {
    HDF_LOGE("GpioSetIrq: gpio set irq fail, ret:%d\n", ret);
    return ret;
}

// 使能3号GPIO管脚中断
ret = GpioEnableIrq(3);
if (ret != HDF_SUCCESS) {
    HDF_LOGE("GpioEnableIrq: gpio enable irq fail, ret:%d\n", ret);
    return ret;
}

// 禁止3号GPIO管脚中断
ret = GpioDisableIrq(3);
if (ret != HDF_SUCCESS) {
    HDF_LOGE("GpioDisableIrq: gpio disable irqfail, ret:%d\n", ret);
    return ret;
}

// 取消3号GPIO管脚中断服务程序
ret = GpioUnsetIrq(3, NULL);
if (ret != HDF_SUCCESS) {
    HDF_LOGE("GpioUnSetIrq: gpio unset irq fail, ret:%d\n", ret);
    return ret;
}

使用实例

本实例程序中,我们将测试一个GPIO管脚的中断触发:为管脚设置中断服务函数,触发方式为边沿触发,然后通过交替写高低电平到管脚,产生电平波动,制造触发条件,观察中断服务函数的执行。

首先需要选取一个空闲的GPIO管脚,本例程基于Hi3516DV300开发板,GPIO管脚选择GPIO10_3,换算成GPIO号为83。

读者可以根据自己使用的开发板,参考其原理图,选择一个空闲的GPIO管脚即可。

#include "gpio_if.h"
#include "hdf_log.h"
#include "osal_irq.h"
#include "osal_time.h"

static uint32_t g_irqCnt;

// 中断服务函数
static int32_t TestCaseGpioIrqHandler(uint16_t gpio, void *data)
{
    HDF_LOGE("TestCaseGpioIrqHandler: irq triggered! on gpio:%u, in data", gpio);
    g_irqCnt++;          // 如果中断服务函数触发执行,则将全局中断计数加1
    return GpioDisableIrq(gpio);
}

// 测试用例函数
static int32_t TestCaseGpioIrqEdge(void)
{
    int32_t ret;
    uint16_t valRead;
    uint16_t mode;
    uint16_t gpio = 84;  // 待测试的GPIO管脚号
    uint32_t timeout;

    // 将管脚方向设置为输出
    ret = GpioSetDir(gpio, GPIO_DIR_OUT);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("TestCaseGpioIrqEdge: set dir fail! ret:%d\n", ret);
        return ret;
    }

    // 先禁止该管脚中断
    ret = GpioDisableIrq(gpio);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("TestCaseGpioIrqEdge: disable irq fail! ret:%d\n", ret);
        return ret;
    }

    // 为管脚设置中断服务函数,触发模式为上升沿和下降沿共同触发
    mode = OSAL_IRQF_TRIGGER_RISING | OSAL_IRQF_TRIGGER_FALLING;
    HDF_LOGE("TestCaseGpioIrqEdge: mode:%0x\n", mode);
    ret = GpioSetIrq(gpio, mode, TestCaseGpioIrqHandler, NULL);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("TestCaseGpioIrqEdge: set irq fail! ret:%d\n", ret);
        return ret;
    }

    // 使能此管脚中断
    ret = GpioEnableIrq(gpio);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("TestCaseGpioIrqEdge: enable irq fail! ret:%d\n", ret);
        (void)GpioUnsetIrq(gpio, NULL);
        return ret;
    }

    g_irqCnt = 0;        // 清除全局计数器
    timeout = 0;         // 等待时间清零
    // 等待此管脚中断服务函数触发,等待超时时间为1000毫秒
    while (g_irqCnt <= 0 && timeout < 1000) {
        (void)GpioRead(gpio, &valRead);
        (void)GpioWrite(gpio, (valRead == GPIO_VAL_LOW) ? GPIO_VAL_HIGH : GPIO_VAL_LOW);
        HDF_LOGE("TestCaseGpioIrqEdge: wait irq timeout:%u\n", timeout);
        OsalMDelay(200); // 等待中断触发
        timeout += 200;
    }
    (void)GpioUnsetIrq(gpio, NULL);
    HDF_LOGI("TestCaseGpioIrqEdge: function tests end, g_irqCnt:%u", g_irqCnt);
    return (g_irqCnt > 0) ? HDF_SUCCESS : HDF_FAILURE;
}


最后

有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?但是又不知道从哪里下手,而且学习时频繁踩坑,最终浪费大量时间。所以本人整理了一些比较合适的鸿蒙(HarmonyOS NEXT)学习路径和一些资料的整理供小伙伴学习

点击领取→纯血鸿蒙Next全套最新学习资料(安全链接,放心点击

希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!

一、鸿蒙(HarmonyOS NEXT)最新学习路线

有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,内容包含:(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)…等技术知识点。

获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料

二、HarmonyOS Next 最新全套视频教程

三、《鸿蒙 (OpenHarmony)开发基础到实战手册》

OpenHarmony北向、南向开发环境搭建

《鸿蒙开发基础》

  • ArkTS语言
  • 安装DevEco Studio
  • 运用你的第一个ArkTS应用
  • ArkUI声明式UI开发
  • .……

《鸿蒙开发进阶》

  • Stage模型入门
  • 网络管理
  • 数据管理
  • 电话服务
  • 分布式应用开发
  • 通知与窗口管理
  • 多媒体技术
  • 安全技能
  • 任务管理
  • WebGL
  • 国际化开发
  • 应用测试
  • DFX面向未来设计
  • 鸿蒙系统移植和裁剪定制
  • ……

《鸿蒙进阶实战》

  • ArkTS实践
  • UIAbility应用
  • 网络案例
  • ……

四、大厂面试必问面试题

五、鸿蒙南向开发技术

六、鸿蒙APP开发必备

七、鸿蒙生态应用开发白皮书V2.0PDF


完整鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料

总结
总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。 

                        

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

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

相关文章

Echarts 问题集锦

最近公司集中做统计图表&#xff0c;新手小白&#xff0c;真被Echarts折腾地不轻&#xff0c;怕自己年老记忆衰退&#xff0c;特地做一些记录。以备后面查阅。 1、X轴的 数据显示不全&#xff0c;间或不显示 很奇葩&#xff0c;我发现数据里有一个值为0.0&#xff0c;当这条记…

液压件工厂的MES解决方案:智能生产,高效未来

一、引言 虽然我国液压件行业发展迅速&#xff0c;但是大多数液压件生产企业规模小、自主创新能力不足&#xff0c;大部分液压产品处于价值链中低端。且由于技术、工艺、设备及管理等多方面的限制&#xff0c;高端液压件产品研发生产水平不足&#xff0c;无法形成有效的供给&a…

【linux】虚拟机安装 BCLinux-R8-U4-Server-x86_64

目录 一、概述 1.1移动云Linux系统订阅服务 CLS 1.2 大云天元操作系统BC-Linux 二、安装 一、概述 1.1移动云Linux系统订阅服务 CLS 移动云Linux系统订阅服务 CLS &#xff08;Cloud Linux Service&#xff09;为使用BC-Linux操作系统的用户提供标准维保服务以及高级技术支…

生物墨水的重要特性

生物打印技术正以前所未有的速度发展&#xff0c;为组织工程和再生医学领域带来了革命性的变革。然而&#xff0c;成功打印出功能性的三维结构&#xff0c;并将其应用于人体&#xff0c;离不开生物墨水这一关键材料。主要特性包括&#xff1a; 物理性质 表面张力: 表面张力影…

基于java+springboot+vue实现的社团管理系统(文末源码+Lw)270

摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对信息管理混乱&#xff0c;出错率高&#xff0c;信息安全性差&#…

Linux4(Docker)

目录 一、Docker介绍 二、Docker结构 三、Docker安装 四、Docker 镜像 五、Docker 容器 六、Docker 安装nginx 七、Docker 中的MySQL部署 一、Docker介绍 Docker&#xff1a;是给予Go语言实现的开源项目。 Docker的主要目标是“Build,Ship and Run Any App,Anywhere” 也…

LangChain入门学习笔记(七)—— 使用检索提高生成内容质量

大模型训练使用的数据是开放的、广泛的&#xff0c;因此它显得更加的通用。然而在有些应用场景下&#xff0c;用户需要使用自己的数据使得大模型生成的内容更加贴切&#xff0c;也有时候用户的数据是敏感的&#xff0c;无法提供出来给大模型进行通用性的训练。RAG技术就是一种解…

HarmonyOS APP应用开发项目- MCA助手(Day02持续更新中~)

简言&#xff1a; gitee地址&#xff1a;https://gitee.com/whltaoin_admin/money-controller-app.git端云一体化开发在线文档&#xff1a;https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/agc-harmonyos-clouddev-view-0000001700053733-V5注&#xff1a;…

Java Lambda语法介绍

目录 一、概述 二、Lambda语法的历史 2.1 Lambda名字的含义 2.2 Lambda的历史 三、Lambda语法的核心接口 3.1 Lambda的四大核心接口 3.1.1 概述 3.1.2 Consumer 接口 3.1.3 Supplier 接口 3.1.4 Function 接口,> 3.1.5 Predicate 接口 四、Lambda的引用 4.1 概…

启航IT世界:高考后假期的科技探索之旅

随着高考的落幕&#xff0c;新世界的大门已经为你们敞开。这个假期&#xff0c;不仅是放松身心的时光&#xff0c;更是为即将到来的IT学习之旅打下坚实基础的黄金时期。以下是一份专为你们准备的IT专业入门预习指南&#xff0c;希望能助你们一臂之力。 一&#xff1a;筑基篇&a…

(18)GPS/指南针(一)

文章目录 前言 1 GPS/指南针 2 RTK GPS 3 GPS驱动程序选项 4 GPS自动切换 5 高级用途 前言 Copter/Plane/Rover 支持与 GPS、指南针和其他定位技术的整合&#xff1a; 1 GPS/指南针 Avionics Anonymous GNSS CompassAvionics Anonymous CompassBeitain BN-220 GPS / B…

昇思MindSpore学习入门-模型训练

模型训练 模型训练一般分为四个步骤&#xff1a; 构建数据集。定义神经网络模型。定义超参、损失函数及优化器。输入数据集进行训练与评估。 现在我们有了数据集和模型后&#xff0c;可以进行模型的训练与评估。 构建数据集 首先从数据集 Dataset加载代码&#xff0c;构建…

RT-Thread Studio与CubeMX联合编程之rtthread stm32h743的使用(十一)spi设备SFUD驱动的使用

我们要在rtthread studio 开发环境中建立stm32h743xih6芯片的工程。我们使用一块stm32h743及fpga的核心板完成相关实验&#xff0c;核心板如图&#xff1a; 1.建立新工程&#xff0c;选择相应的芯片型号及debug引脚及调试器 2.编译下载&#xff0c;可以看到串口打印正常 3.…

超实用的80个网络基础知识!(非常详细)零基础入门到精通,收藏这一篇就够了

点击上方 网络技术干货圈&#xff0c;选择 设为星标 优质文章&#xff0c;及时送达 转载请注明以下内容&#xff1a; 来源&#xff1a;公众号【网络技术干货圈】 作者&#xff1a;圈圈 ID&#xff1a;wljsghq 基础网络概念 1. 网络基础概述 什么是计算机网络 计算机网络是一…

全自动封箱机:如何助力企业实现智能化升级

在飞速发展的工业自动化时代&#xff0c;全自动封箱机以其高效、精准、稳定的特点&#xff0c;成为了生产线上的不可或缺的一员。它不仅大大地提高了生产效率&#xff0c;降低了人工成本&#xff0c;更在产品质量控制、安全性等方面发挥了重要作用。星派将深入探讨全自动封箱机…

基于SpringBoot民宿管理系统设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;…

华为云物联网的使用

这里我们设置三个属性 1.温度DHT11_T 上传 2.湿度DHT11_H 上传 3.风扇motor 远程控制&#xff08;云平台控制设备端&#xff09; 发布主题&#xff1a; $oc/devices/{device_id}/sys/properties/report 发布主题时&#xff0c;需要上传数据&#xff0c;这个数据格式是JSON格式…

充气膜羽毛球馆投资需要多少钱—轻空间

充气膜羽毛球馆是一种现代化的运动设施&#xff0c;以其灵活的结构设计和高效的能耗管理受到广泛关注。投资建设一个充气膜羽毛球馆&#xff0c;涉及多个方面的成本&#xff0c;包括基础建设、膜材选择、系统配置以及运营维护费用。轻空间将详细分析投资建设充气膜羽毛球馆的成…

【C++知识点总结全系列 (06)】:STL六大组件详细介绍与总结(配置器、容器、迭代器、适配器、算法、仿函数)

STL六大组件目录 前言1、配置器(1)What(2)Why(3)HowA.调用new和delete实现内存分配与销毁B.STL Allocator (4)allocator类A.WhatB.HowC.allocator的算法 2、容器(1)What(2)Which&#xff08;有哪些容器&#xff09;(3)序列容器&#xff08;顺序容器&#xff09;A.WhichB.array&…

Langchain-Chatchat本地部署记录,三分钟学会!

1.前言&#xff1a; 最近AI爆发式的火&#xff0c;忆往昔尤记得16,17那会移动互联网是特别火热的&#xff0c;也造富了一批公司和个人&#xff0c;出来了很多精妙的app应用。现在轮到AI发力了&#xff0c;想想自己也应该参与到这场时代的浪潮之中&#xff0c;所以就找了开源的…