OpenHarmony 标准系统HDF框架之I2C驱动开发

2023-10-27

主要内容

  • I2C 基础知识
  • I2C 调试手段
  • HDF 框架下的 I2C 设备驱动

I2C 基础知识## I2C 基础知识 —— 概念和特性

  • I2C(IIC、I2C)集成电路总线,由串行数据线 SDA 和串行时钟线 SCL 组成,对于一个 I2C 接口的器件,至少还需要电源和地线;
  • I2C 总线是双向、半双工传输
  • 支持多主机、多从机同时挂接在一条 I2C 总线上,多主机同时请求总线时,可以通过冲突检测和仲裁机制防止总线数据被破坏
  • 每一个从设备都有唯一的地址,从设备可被寻址(又称为被选中),只有被选中的从设备才能参与通信,每次通信只有一个主设备和一个从设备参与
  • 主设备发起一次通信,从设备响应:主从设备都可以发送和接收数据,SCL 时钟由主设备发出,在工程中常见 MCU 或 SOC 作为主设备,主从设备地位可以交换

在这里插入图片描述

I2C 是串行低速总线,常见传输速度如下:

  • 标准模式(standard-mode):速率高达 100kbit/s
  • 快速模式(fast-mode):速率 400kbit/s
  • 快速模式+(fast-mode plus):速率 1Mbit/s
  • 高速模式(high-speed mode):速率 3.4Mbit/s

工程中常见兼容标准模式和快速模式的 I2C 从设备

在这里插入图片描述

  • 一条 I2C 总线上的所有从设备都有一个唯一的设备地址,不能与总线上的其他设备地址重复;
  • 设备地址有 7 位和 10 位两种格式,常见 7 位格式
  • I2C 主设备对从设备可执行写操作和读操作,通过写地址和读地址区分写操作和读操作

设备地址 7 位:101000(0x50)写地址 8 位:设备地址左移一位i,末位补 0 :1010000 (0xA0)读地址 8 位:设备地址左移一位,末位补 1: 1010001 (0xA1)同一个 I2C 设备可能具有多个设备地址,通常可通过从设备的管脚配置,以 I2C 接口的 ROM 芯片 AT24C256 为例:

在这里插入图片描述

  • 如果 A1 和 A0 两个管脚接地,则 7 位设备地址为:1010000(0x50),8 位写地址:1010000(0xA0),8 位读地址:1010001(0xA1)
  • 片内地址、片内偏移、字地址:从设备内部寻址,如内部寄存器地址或 ROM 读写地址等
  • 同一个 I2C 总线上挂载的设备数量受限于总线上最大电容不超过 400pF

I2C 基础知识 —— 协议、四种信号组合

  • I2C 起始信号和停止信号由主设备发出
  • S:时钟信号 SCL 保持高电平、数据信号 SDA 由高到低跳变
  • P:时钟信号 SCL 保持高电平、数据信号 SDA 由低到高跳变
  • 写信号:主或从设备在时钟信号 SCL 为低电平时将数据写到数据线 SDA,即数据线只能在 SCL 为低电平时发生高低跳变
  • 读数据:数据线需要在 SCL 为高电平时保持稳定,同时从或主设备也会在此时从 SDA 上读取数据

在这里插入图片描述

I2C 调试手段## I2C 调试手段 —— 硬件

  • I2C 协议规定,在空闲状态下,总线为高电平:从设备工作电压 VDD,SDA 和 SCL 电压不低于 0.7VDD(低电平不高于 0.3VDD),常见的 VDD 有 1.8V、3.3V、5V 三种规格
  • 高电平通过外挂上拉电阻实现,需要确保上拉电阻有效

在这里插入图片描述

I2C 调试手段 —— 软件

  • 处理器支持多个 I2C 总线,确认 I2C 设备挂载的总线编号:Hi3516DV300 支持 8 路 I2C 总线,编号 0-7
    在这里插入图片描述

  • 开启内核选项:CONFIG_I2C_CHARDEV(make menuconfig)
    在这里插入图片描述

  • 使用 i2c_tools 工具包中的 i2c_detect 命令检测某条总线上挂载的所有设备
    在这里插入图片描述

HDF 框架下的 I2C 设备驱动## HDF 框架下的 I2C 设备驱动 —— 案例描述

  • I2C 从设备:AT24C256、EEPROM、256Kb
  • A1 和 A2 两条管脚均接地,则 7 位设备地址为:1010000(0x50),8 位写地址:1010000(0xA0),8 位读地址:1010001(0xA1)
  • 写操作:用户态程序将字地址和数据发送给驱动程序,驱动程序将数据写入设备的字地址
  • 读操作:用户程序将字地址发送给驱动程序,驱动程序从指定的设备字地址读取数据,并将数据返回给用户态程序

具体操作(写操作):

  • 写操作:32KByte 空间,按照字节寻址,需要 15bit 字地址(7bit 高位 + 8bit 低位),字地址占用两个字节

在这里插入图片描述

  • 起始信号、设备地址(bit0 = 0)、字地址(高字节)、字地址(低字节)、数据

具体操作(读操作):

  • 读操作:32KByte 空间,按照字节寻址,需要 15bit 字地址(7bit 高位 + 8bit 低位),字地址占用两个字节

在这里插入图片描述

  • 起始信号、设备地址(bit0 = 0)、字地址(高字节)、字地址(低字节)
  • 起始信号、设备地址(bit0 = 1)、接收数据
  • 读操作中包含写操作

HDF 框架下的 I2C 设备驱动 —— 用户态程序

  • 应用程序通过服务名绑定驱动程序,和驱动建立联系
#define SAMPLE_SERVICE_NAME "at24_service"

struct HdfIoService *serv = HdfIoServiceBind(SAMPLE_SERVICE_NAME);
if(serv == NULL){
    printf("fail to get service %s \n", SAMPLE_SERVICE_NAME);
    return HDF_FAILURE;
}

对应的 hcs 文件:

i2c_host :: host{
    hostName = "my_i2c_test";
    priority = 100;
    device_i2c :: device {
        device0 :: deviceNode {
            policy = 2;
            priority = 100;
            preload = 0;
            permission = 0664;
            moduleName = "at24_drv";
            serviceName = "at24_service";
            deviceMatchAttr = "at24_driver_attr";
        }
    }
}
  • 用户态程序对驱动或设备的所有操作都基于服务
  • 用户态程序以字节为单位将数据写入设备
#define I2C_RD_CMD    456
#define I2C_WR_CMD    789

static int write _data (struct HdfIoService *serv, uint16_t addr, uint8_t value)
{
    //用户态写操作
    struct HdfSBuf *data = HdfSBufObtainDefault Size();
    if(data == NULL){
        HDF_LOGE("fail to obtain sbuf data");
        ret = HDF_DEV_ERR_NO_MEMORY;
        goto out;
    }
    struct HdfSBuf *reply = HdfSBufObtainDefaultSize();
    HdfSbufWriteUint16(data, addr);
    HdfSbufWriteUint8(data, value);
    serv->dispatcher->Dispatch(&serv->object, I2C_WR_CMD, data, reply);
    HdfSbufReadString(reply);
    printf("Get reply is : %s\n", str);
}
  • 获取两个缓冲区 data 和 reply
  • 将字地址(15bit)和数据(8bit)写入 data 缓冲区
  • 调用 Dispatch 将字地址和数据发送给驱动
  • 读取驱动的返回值

用户态程序读操作:

  • 用户态程序以字节为单位从设备读取数据
#define I2C_RD_CMD    456
#define I2C_WR_CMD    789

static int write _data (struct HdfIoService *serv, uint16_t addr, uint8_t value)
{
    //用户态读操作
    struct HdfSBuf *data = HdfSBufObtainDefault Size();
    if(data == NULL){
        HDF_LOGE("fail to obtain sbuf data");
        ret = HDF_DEV_ERR_NO_MEMORY;
        goto out;
    }
    struct HdfSBuf *reply = HdfSBufObtainDefaultSize();
    HdfSbufWriteUint16(data, addr);
    serv->dispatcher->Dispatch(&serv->object,I2C_RD_CMD, data, reply);
    HdfSbufReadUint8(reply, pval);
    HdfSbufReadString(reply);
    printf("Get reply is : data 0x%hhx, str :%s\n", *pval,  str);
}
  • 获取两个缓冲区 data 和 reply
  • 将字地址(15bit)写入 data 缓冲区
  • 调用 Dispatch 将字地址发送到驱动
  • 读取驱动的返回值

HDF 框架下的 I2C 设备驱动 —— 驱动程序入口

  • 驱动程序入口:
struct HdfDriverEntry g_SensorDriverEntry = {
    .moduleVersion = 1,
    .moduleName = "at24_drv",
    .Bind = HdfSensorDriverBind,
    .Init = HdfSensorDriverInit,
    .Release = HdfSensorDriverRelease,
}

HDF_INIT(g_SensorDriverEntry);
  • device_info.hcs 定义设备节点
i2c_host :: host{
    hostName = "my_i2c_test";
    priority = 100;
    device_i2c :: device {
        device0 :: deviceNode {
            policy = 2;
            priority = 100;
            preload = 0;
            permission = 0664;
            moduleName = "at24_drv";
            serviceName = "at24_service";
            deviceMatchAttr = "at24_driver_attr";
        }
    }
}

hcs 设备节点中定义了一个设备私有属性:deviceMatchAttr = “at24_driver_attr”;

static int32_t GetAT24ConfigData(const struct DeviceResourceNode *node)
{    struct DeviceResourceIface *parser = NULL;
    const struct DeviceResourceNode *at24 = NULL;
    parser = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
    at24 = parser->GetChildNode(node, "at24Attr");
    parser->GetUint16(at24, "busId", &(tpDevice.busId), 0);
    parser->GetUint16(at24, "addr", &(tpDevice.addr), 0);
    parser->GetUint16(at24, "regLen", &(tpDevice.regLen), 0);
    return HDF_SUCCESS;
}

int32_t HdfSensorDriverInit(struct HdfDeviceObject *deviceObject)
{
    if(GetAT24ConfigData(deviceObject->property) != HDF_SUCCESS){
        HDF_LOGE("%s: get at24 config fail!", __func__);
        return HDF_FAILURE;
    }

    if(at24_init() != HDF_SUCCESS){
        HDF_LOGE("i2c at24 driver init failed!");
        return -1;
    }

    HDF_LOGD("i2c at24 driver init success.");
    return 0;
}
  • 解析 hcs 配置文件中定义的属性 at24_driver_attr, 获取设备的私有属性的值
  • 初始化 i2c 从设备

设备私有属性(i2c_test_config.hcs)

root {
    match_attr = "at24_driver_attr";
    at24Attr {    //节点名字 at24Attr
        busId = 5;    //总线编号    5
        addr = 0x50;    //设备地址    0x50
        regLen = 2;        //地址宽度    2字节
    }
}

全局配置文件(device_info.hcs)

i2c_host :: host{
    hostName = "my_i2c_test";
    priority = 100;
    device_i2c :: device {
        device0 :: deviceNode {
            policy = 2;
            priority = 100;
            preload = 0;
            permission = 0664;
            moduleName = "at24_drv";
            serviceName = "at24_service";
            deviceMatchAttr = "at24_driver_attr";
        }
    }
}

HDF 框架下的 I2C 设备驱动 —— 设备初始化

  • 设备初始化
static int32_t at24_init(void)
{
    tpDevice.i2cHandle = i2cOpen(tpDevice.busId);
    return HDF_SUCCESS;
}
功能分类 接口名 描述
I2C 控制器管理接口 I2cOpen 打开 I2C 控制器
I2cClose 关闭 I2C 控制器
i2c 消息传输接口 I2cTransfer 自定义传输

HDF 框架下的 I2C 设备驱动 —— 驱动 Dispatch

int32_t HdfSensorDriverDispatch(struct HdfDeviceIoClient *client, int id, struct HdfSBuf *data, struct HdfSBuf *reply)
{
    uint16_t addr = 0;
    uint8_t value = 0;

    if(id == I2C_WR_CMD){
        HdfSbufReadUint16(data, &addr);
        HdfSbufReadUint8(data, &value);
        TpI2cWriteReg(&tpDevice, addr, &value, 1);
        HdfSbufWriteString(reply, "write success");
    }
    else if(id == I2C_RD_CMD){
       HdfSbufReadUint16(data, &addr);
        TpI2cWriteReg(&tpDevice, addr, &value, 1);
        HdfSbufWriteUint8(reply, value);
        HdfSbufWriteString(reply, "read success");
    }
}

写数据:

  • 读取两个字节的字地址
  • 读取要写到字地址的数据
  • 执行写操作,参数 1 表示写一个字节数据
  • 返回值给用户程序

读数据:

  • 读取两个字节的字地址
  • 执行读操作,参数 1 表示读一个字节数据
  • 返回值给用户程序

HDF 框架下的 I2C 设备驱动 —— 驱动读写

struct TpI2cDevice{
    uint16_t busId;
    uint16_t addr;
    uint16_t regLen;
    DevHandle i2cHandle;
}

struct I2cMsg{
    uin16_t addr;    //i2c 设备地址
    uintt8_t *buf;    //缓存区
    uint16_t len;        //数据传输长度
    uint16_t flags;        //传输模式 flags,区分读写。
}

static struct TpI2cDevice tpDevice;

static inline int TpI2cReadReg(struct TpI2cDevice *tpDevice, uint16_t regAddr, uint8_t *regData, uint32_t dataLen)
{
    return TpI2cReadWrite()tpDevice, regAddr, regData, dataLen, 1);
}

static inline int TpI2cWriteReg(struct TpI2cDevice *tpDevice, uint16_t regAddr, uint8_t *regData, uint32_t dataLen)
{
    return TpI2cReadWrite()tpDevice, regAddr, regData, dataLen, 0);
}

static int TpI2cReadWrite(struct TpI2cDevice *tpDevice, uint16_t regAddr, uint8_t *regData, uint32_t dataLen, uint8_t flaag)
{
    int index = 0;
    unsigned char regBuf[2] = {0};
    struct I2cMsg msgs[2] = {0};

    if(tpDevice->regLen == 1){
        regBuf[index++] = regAddr & 0xFF;
    }
    else {
        regBuf[index++] = (regAddr >> 8 ) & 0xFF;
        regBuf[index++] = regAddr & 0xFF;
    }

    msgs[0].addr = tpDevice->addr;
    msgs[0].flags = 0;
    msgs[0].len = tpDevice->regLen;
    msgs[0].buf = regBuf;

    msgs[1].addr = tpDevice->addr;
    msgs[1].flags = (flag == 1) ? I2C_FLAG_READ : 0;
    msgs[1].len = dataLen;
    msgs[1].buf = regData;

    if(I2cTransfer(tpDevice->i2cHandle, msgs, 2) != 2)
        return HDF_FAILURE;

    return HDF_SUCCESS;
}
  • 总线编号:busId = 5
  • 设备地址:addr = 0x50
  • 地址宽度:2 字节

读操作:

  • 1 为读标志
  • 设备地址最低有效位为 1

写操作:

  • 0 为写标志
  • 设备地址最低有效位为 0

其中参数说明:

  • regAddr 和 regBuf 存放两个字节的字地址
  • dataLen 表示读写数据的字节长度
  • 读写操作的字地址作为数据写到从设备
  • regData 存放读写的数据
  • flags 区分读写操作
  • I2cTransfer 的返回值表示成功发送的 i2cMsg 数据包数量

总结

  • I2C 基础知识:概念和特性、4 个地址(设备地址、读地址、写地址、字地址)、波形(起始、结束、数据发送、数据接收)
  • I2C 调试手段:电压、上拉电阻、/dev/i2c-x、i2c-tools
  • HDF 框架 I2C 驱动:AT24C256 芯片按照字节寻址方式读写(按照页 64 字节寻址、连续读写)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenHarmony 标准系统HDF框架之I2C驱动开发 的相关文章

  • 在 Linux 上使用多处理时,TKinter 窗口不会出现

    我想生成另一个进程来异步显示错误消息 同时应用程序的其余部分继续 我正在使用multiprocessingPython 2 6 中的模块来创建进程 我试图用以下命令显示窗口TKinter 这段代码在Windows上运行良好 但在Linux上
  • ubuntu:升级软件(cmake)-版本消歧(本地编译)[关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我的机器上安装了 cmake 2 8 0 来自 ubuntu 软件包 二进制文件放置在 usr bin cmake 中 我需要将 cmake 版本至少
  • 如何通过保持目录结构完整来同步路径中匹配模式的文件?

    我想将所有文件从服务器 A 复制到服务器 B 这些文件在不同级别的文件系统层次结构中具有相同的父目录名称 例如 var lib data sub1 sub2 commonname filetobecopied foo var lib dat
  • 为arm构建WebRTC

    我想为我的带有arm926ej s处理器的小机器构建webrtc 安装 depot tools 后 我执行了以下步骤 gclient config http webrtc googlecode com svn trunk gclient s
  • SSE:跨页边界的未对齐加载和存储

    我在页面边界旁边执行未对齐加载或存储之前读过某处 例如使用 mm loadu si128 mm storeu si128内在函数 代码应首先检查整个向量 在本例中为 16 个字节 是否属于同一页 如果不属于同一页 则切换到非向量指令 我知道
  • 在我的 index.php 中加载 CSS 和 JS 等资源时出现错误 403

    我使用的是 Linux Elementary OS 并在 opt 中安装了 lampp My CSS and JS won t load When I inspect my page through browser The console
  • 如何确保应用程序在 Linux 上持续运行

    我试图确保脚本在开发服务器上保持运行 它会整理统计数据并提供网络服务 因此它应该会持续存在 但一天中有几次 它会因未知原因而消失 当我们注意到时 我们只需再次启动它 但这很麻烦 并且某些用户没有权限 或专有技术 来启动它 作为一名程序员 我
  • Linux 上有关 getBounds() 和 setBounds() 的 bug_id=4806603 的解决方法?

    在 Linux 平台上 Frame getBounds 和 Frame setBounds 的工作方式不一致 这在 2003 年就已经有报道了 请参见此处 http bugs java com bugdatabase view bug do
  • 删除 Git 存储库,但保留所有文件

    在我使用 Linux 的过程中的某个时刻 我决定将我的主目录中的所有内容都放入源代码管理中是个好主意 我不是在问这是否是一个好主意 我是在问如何撤销它 删除存储库的原因是我最近安装了 Oh My Zsh 而且我非常喜欢它 问题是我的主目录有
  • 如何在基于 Linux 的系统上的 C 程序中使用 mqueue?

    如何在基于 Linux 的系统上的 C 程序中使用 mqueue 消息队列 我正在寻找一些好的代码示例 可以展示如何以正确且正确的方式完成此操作 也许是一个操作指南 下面是一个服务器的简单示例 该服务器接收来自客户端的消息 直到收到告诉其停
  • 如何减去两个 gettimeofday 实例?

    我想减去两个 gettimeofday 实例 并以毫秒为单位给出答案 这个想法是 static struct timeval tv gettimeofday tv NULL static struct timeval tv2 gettime
  • 快速像素绘图库

    我的应用程序以每像素的方式生成 动画 因此我需要有效地绘制它们 我尝试过不同的策略 库 但结果并不令人满意 尤其是在更高分辨率的情况下 这是我尝试过的 SDL 好的 但是慢 OpenGL 像素操作效率低下 xlib 更好 但仍然太慢 svg
  • C++ Boost ASIO 简单的周期性定时器?

    我想要一个非常简单的周期性计时器每 50 毫秒调用我的代码 我可以创建一个始终休眠 50 毫秒的线程 但这很痛苦 我可以开始研究用于制作计时器的 Linux API 但它不可移植 I d like使用升压 我只是不确定这是否可能 boost
  • 高效的内存屏障

    我有一个多线程应用程序 其中每个线程都有一个整数类型的变量 这些变量在程序执行期间递增 在代码中的某些点 线程将其计数变量与其他线程的计数变量进行比较 现在 我们知道在多核上运行的线程可能会无序执行 一个线程可能无法读取其他线程的预期计数器
  • Mcrt1.o和Scrt1.o有什么用?

    我坚持使用以下两个文件 即 Mcrt1 o 和 Scrt1 o 谁能帮我知道这两个文件的用途 如何使用它 我们以 gcrt1 o 为例 在使用 pg 选项编译进行性能测试时非常有用 谢谢 表格的文件 crt o总是 C 运行时启动代码 大部
  • Linux 上的基准测试程序

    对于一项任务 我们需要使用不同的优化和参数来对我们的实现进行基准测试 有没有一种可行的方法可以在Linux命令行 我知道时间 上使用不同的参数对小程序进行基准测试 从而为我提供CSV或类似内容的时间数据 输出可能类似于 Implementa
  • 每个命令都返回“bash:<命令>:找不到命令...”[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我刚刚安装了 Scala 并添加了路径gedit bashrc export SCALA HOME home avijit sca
  • 如何在 GNU/Linux 上设置 Subversion (SVN) 服务器 - Ubuntu [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有一台运行 Ubuntu 的笔记本电脑 我想将其用作 Subversion 服务器 既让我自己在本地承诺 也让其他人远程承诺 要使其
  • Linux 上的 RTLD_LOCAL 和dynamic_cast

    我们有一个由应用程序中的一些共享库构成的插件 我们需要在应用程序运行时更新它 出于性能原因 我们在卸载旧插件之前加载并开始使用新插件 并且只有当所有线程都使用旧插件完成后 我们才卸载它 由于新插件和旧插件的库具有相同的符号 我们dlopen
  • 让 TeXstudio 在 linux mint 中工作:找不到文件“url.sty”。

    刚刚切换到 Linux Mint 以前的顽固 Windows 用户 我在尝试安装 TeXstudio 时遇到一些问题 Sudo apt get install texstudio 给了我一个正确的安装 至少 我是这么认为的 但是当我尝试构建

随机推荐

  • Onvif协议学习:7、鉴权认证

    Onvif协议学习 7 鉴权认证 文章目录 Onvif协议学习 7 鉴权认证 1 前言 2 ONVIF哪些接口需要认证 3 如何认证 4 安装OpenSSL 5 实现认证 6 特别注意 原文链接 https blog csdn net be
  • QT学习(十九)——用QFile读写文件

    写文件 两种方法 1 第一种使用QString获取编辑区的内容之后直接用toUtf8 转化为QByteArray 2 第二种使用QString获取编辑区的内容之后先转化成std string 再转换成char 不过最后的文件类型都是UTF
  • Zookeeper(一)简介说明

    1 1 什么是Zookeeper Zookeeper是一个高效的分布式协调服务 它暴露了一些公用服务 比如命名 配置管理 同步控制 群组服务等 我们可以使用ZK来实现比如达成共识 集群管理 leader选举等 Zookeeper是一个高可用
  • 编写高质量代码:改善Java程序的151个建议(第9章:多线程和并发___建议125~131)

    建议125 优先选择线程池 建议126 适时选择不同的线程池来实现 建议127 lock与synchronized是不一样的 建议128 预防线程死锁 建议129 适当设置阻塞队列的长度 建议130 使用CountDownLatch协调子线
  • Spring Cloud Alibaba核心组件概述

    目录 概览 Nacos 注册中心 配置中心 Sentinel 限流 熔断降级 控制台 动态规则扩展 Seata AT模式 TCC模式 Saga模式 XA模式 Spring Cloud Gateway 关键特性 核心概念 负载均衡 概览 Sp
  • fetch整个仓库 github_为开源项目做贡献的10个步骤,GitHub贡献的简短指南

    在本文中 我将给出10个简单的步骤 以确保GitHub的贡献快速而干净 贡献的生命周期 步骤 1 fork主仓库 fork主仓库会在你的帐户中创建一个副本 你可以进行更改并将任何代码推送到此fork 而不必担心会弄乱原始代码库 单击页面顶部
  • java中tip是什么意思_tip是什么意思

    tip指的是小费或者是尖端 指点的意思 tip美音可以是 t p 英音是 t p 第三人称单数可以写为tips 复数可以直接写为tips 现在分词是tipping 过去式是tipped 列句 每次给爸妈买些东西 总是能赚到小费 Every
  • IBM --AIX 常用命令

    创建组 mkgroup id 101 info 创建用户 mkuser pgrp staff home home campaign shell usr bin ksh groups staff campaign 解压 unzip campa
  • AcWing 425. 明明的随机数

    题目 明明想在学校中请一些同学一起做一项问卷调查 为了实验的客观性 他先用计算机生成了N个1到1000之间的随机整数 对于其中重复的数字 只保留一个 把其余相同的数去掉 不同的数对应着不同的学生的学号 然后再把这些数从小到大排序 按照排好的
  • golang学习demo4-goroutine并行测试

    知识点 go语言的routine的使用 通道chan的使用 想测试一下go的routine 就写了个求大量素数的程序 分别开1 99个协程进行求解 对比结果 首先是没有开协程的 下面是开了少数几个协程的程序 可以看到在 cnt 5 的时候速
  • Pytorch GPU版本简明下载安装教程

    1 根据自己的显卡型号下载显卡驱动并安装 这一步会更新你的显卡驱动 也可忽略第1步 如果第2步出现问题 返回执行第1步 点击这里下载英伟达显卡驱动 2 安装完成后 win cmd打开命令行 输入nvidia smi 查看GPU信息 右上角C
  • elementUIel-input和el-select宽度不一样

    在vue项目中 使用了element组件的 el input 和 el select组件 设置了相同的宽度 但是宽度显示不一样 给el select添加style width 100 就可以解决 没加样式之前的效果 添加样式 没加样式之后的
  • 机器学习入门教学——决策树

    1 简介 决策树算法是一种归纳分类算法 它通过对训练集的学习 挖掘出有用的规则 用于对新数据进行预测 决策树算法属于监督学习方法 决策树归纳的基本算法是贪心算法 自顶向下来构建决策树 贪心算法 在每一步选择中都采取在当前状态下最好 优的选择
  • 52类110个主流Java组件和框架

    以下排序是按照从技术组件到开发框架到代码工具 也有一些实在不好分类的 就放到最后了 WEB 容器 Tomcat https tomcat apache org Jetty https www jetty com JBoss https ww
  • JAVA命令行编译运行程序

    JAVA源程序名扩展名必须是 java 并且主文件名必须是 1 如有public类必须写public类的名 2 如没有public类则主文件名任意 编译源程序 javac d 目录名 源文件 以上命令中 d 目录名代表将编译产生的二进制码文
  • 用计算机对视频进行剪裁和编辑,Win10系统剪裁视频功能怎么用?windows10剪裁视频功能使用方法介绍...

    最近 有不少Win10正式版用户向小编咨询新系统上是否有好的视频剪切软件 答案是肯定的 我们只要利用Win10系统中的 照片 就可以快速实现剪裁视频操作 接下来 小编就向大家介绍windows10系统剪裁视频功能的使用方法 具体方法如下 1
  • HTTP GET参数的获取

    REQUEST METHOD的值一般包括POST和GET两种 GET参数的获取 在GET方法下 CGI程序无法直接从服务器的标准输入中获取数据 因为服务器把从标准输入接收到的数据编码到环境变量QUERY STRING 或PATH INFO
  • 乒乓球捡球机器人_捡球机器人

    本帖最后由 章 于 2020 12 31 08 41 编辑 27 副本 JPG 108 08 KB 下载次数 0 2020 12 24 20 17 上传 制作背景 我国的国球是乒乓球 有许多人从小开始学习打乒乓球 而在学习打乒乓的过程中 为
  • QT:在QTableView中使用各种自定义委托

    原文地址 https blog csdn net lhchen922 article details 38367719 相关文章 1 QT 在QTableView中使用各种自定义委托 https blog csdn net zgrjkflm
  • OpenHarmony 标准系统HDF框架之I2C驱动开发

    OpenHarmony 标准系统HDF框架之I2C驱动开发 主要内容 I2C 基础知识 I2C 基础知识 概念和特性 I2C 基础知识 协议 四种信号组合 I2C 调试手段 I2C 调试手段 硬件 I2C 调试手段 软件 HDF 框架下的