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

I2C通讯

3.1. 本章节的代码仓库

1
2
3
4
5
6
#如之前有获取则可跳过
#获取仓库
git clone https://gitee.com/LubanCat/lubancat_rk_code_storage.git#代码所在的位置
lubancat_rk_code_storage/quick_start/i2c

3.2. i2c

I2C(Inter-Integrated Circuit)是一种通用的总线协议。它是由Philips(飞利浦)公司, 现NXP(恩智浦)半导体开发的一种简单的双向两线制总线协议标准。

LubanCat-RK系列板卡的 I2C 控制器支持下列功能

  • 兼容 I2C 与 SMBus 总线

  • 仅支持主模式下的 I2C 总线

  • 软件可编程时钟频率支持到 400kbps,最高可达 1000kbps

  • 支持 7 位和 10 位寻址模式

  • 一次中断或轮询至多 32 个字节的数据传输

LubanCat-RK3588系列板子的通用i2c设备有两个(如下图所示), 除此之外其他的GPIO也可以复用成I2C设备,需要自行根据引脚复用图去配置, 比如说LubanCat-4的40pin引脚最大可支持5个i2c接口使用

未找到图片

通用i2c引脚

I2C

引脚

功能

I2C-SCL

5,28

i2c的时钟信号线

I2C-SDA

3,27

i2c的数据线

3.3. IIC通信接口复用说明

在板卡的引脚复用图中,我们可能会看到

  • I2C5_SDA_M3/I2C5_SCL_M3

  • I2C5_SDA_M2/I2C5_SCL_M2

可以看到他们之间的区别是后缀名的不同,这个后缀名表示I2C设备的将自己的引脚复用到不同的GPIO引脚的编号, 可以理解成下图的样式

未找到图片

复用出来的多组引脚是不能同时使用的, 如果同时设置则会根据设备节点的加载时间所覆盖,最终只有最后配置的复用引脚可以使用。

所以在使能引脚时需要注意是否为重复复用

3.4. IIC通信接口使能

LubanCat-RK3588系列板子大多数的IIC接口在默认情况是关闭状态的,需要使能才能使用

注意

LubanCat-4的两个通用I2C接口在默认情况下被设置为I2C的功能且默认是使能状态, 所以对于LubanCat-4的板卡两个通用I2C设备是不需用使能的。

3.4.1. fire-config

1
2
3
4
5
#进入工具配置
sudo fire-config#移动光标到下图的位置
#按确认键进入配置

未找到图片

选择你要打开的I2C接口,这里以打开I2C-3为例

  1. 使用方向键移动光标到 I2C-3

  2. 按 “空格键” 选中I2C-3(出现 “*” ),如下图

  3. 按 “确认键” 进行设置

  4. 按 “Esc键” 退出到终端,运行 sudo reboot 进行重启应用

未找到图片

3.4.2. 配置文件

各型号对照表

板卡

设备树插件配置文件

说明

当前你所使用的板子

uEnv.txt

该配置软链接到你所使用的设备,修改该配置相当于修改板子实际的配置

LubanCat-4

uEnvLubanCat4.txt

适用于LubanCat-4

LubanCat-4-V1

uEnvLubanCat4-V1.txt

适用于LubanCat-4-V1

LubanCat-5

uEnvLubanCat5.txt

适用于LubanCat-5

LubanCat-5IO

uEnvLubanCat5IO.txt

适用于LubanCat-5IO

可以通过修改 /boot/uEnv/uEnv.txt 或者 /boot/uEnv/uEnvboard.txt (uEnvboard.txt为通过上面的对照表获得的配置文件)

这里以激活 I2C-3 为例,将带有 I2C-3 的那一行的注释符号去掉 如下图:

未找到图片

然后重启激活设备

注解

如果是直接拔电源的方式重启,会有可能出现文件没能做出修改 (原因:文件未能及时从内存同步到存储设备中,解决方法,在终端上输入 “sync” 再拔电关机)

3.5. 检查I2C设备

可以通过一下命令查看i2c总线有没有开启

1
ls /dev/i2c-*

如下图:

未找到图片

可以看到出现了I2C-xxx

3.6. 连接设备

将mpu6050接入到i2c-3的总线上,如下图所示

1
2
3
4
5
6
7
#板卡与mpu6050连接板子  ------  mpu6050
3.3V(1)  ------  VCC
GND(6)   ------  GND
SCL(5)   ------  SCL
SDA(3)   ------  SDA

未找到图片

3.7. i2c-tools测试

使用i2c-tools工具包提供了一些非常方便的工具来对系统的I2C总线进行调试, 在板卡的终端中可直接执行以下命令进行安装:

1
sudo apt -y install i2c-tools

安装后可使用的命令有i2cdetect、i2cdump、i2cset以及i2cget,用于扫描I2C总线上的设备、读写指定设备的寄存器等。

然后查看挂载在i2c-3上的器件情况,输出内容如下所示:

 123456789
10
11
12
13
14
15
root@lubancat:~# i2cdetect -a 3
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-3.
I will probe address range 0x00-0x7f.
Continue? [Y/n] y0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
root@lubancat:~# ^C

其中 “68” 是为MPU6050的设备地址,常用的命令还有以下几个。

 123456789
10
11
12
13
14
#检测当前系统有几组i2c总线
i2cdetect -l#查看i2c-0接口上的设备
i2cdetect -a 3#读取指定设备的全部寄存器的值。
i2cdump  -f -y 3 0x68#读取指定IIC设备的某个寄存器的值,如下读取地址为0x68器件中的0x01寄存器值。
i2cget -f -y 3 0x68 0x01#写入指定IIC设备的某个寄存器的值,如下设置地址为0x68器件中的0x01寄存器值为0x6f;
i2cset -f -y 3 0x68 0x01 0x6f

3.8. 读取陀螺仪传感器数据实验

3.8.1. 实验说明

本教程将通过IIC接口读取陀螺仪(MPU6050)的原始数据。 本次实验会以i2c-3做为示例,i2c-5的操作和i2c-3的一样, 当然,如果您没有mpu6050模块,可以通过学习操作mpu6050的方式操作您想要操作的i2c设备 在测试程序中大约每一秒读取并显示一次MPU6050的原始数据

查看IIC设备文件,确保IIC 3接口已经使能

1
2
3
root@lubancat:~# ls /dev/i2c-*
/dev/i2c-0  /dev/i2c-1  /dev/i2c-3  /dev/i2c-6
root@lubancat:~#

其中“i2c-3”就是MPU6050使用到的 IIC 3接口总线。

3.8.2. ioctl函数

在编写应用程序时需要使用ioctl函数设置i2c相关配置,其函数原型如下

1
2
3
#include <sys/ioctl.h>int ioctl(int fd, unsigned long request, ...);

其中对于终端request的值常用的有以下几种

I2C_RETRIES

设置收不到ACK时的重试次数,默认为1

I2C_TIMEOUT

设置超时时限的jiffies

I2C_SLAVE

设置从机地址

I2C_SLAVE_FORCE

强制设置从机地址

I2C_TENBIT

选择地址长度0为7位地址,非0为10位

3.8.3. 编写应用程序

根据ioctl相关参数即可编写与i2c相关的接口函数,读取mpu6050原始数据程序如下

代码位置

1
quick_start/i2c/i2c_mpu6050.c

代码较长复制粘贴容易乱序,可以下载我们提供的源码 i2c_mpu6050.c

quick_start/i2c/i2c_mpu6050.c

  123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>/*寄存器地址*/
#define SMPLRT_DIV      0x19
#define PWR_MGMT_1      0x6B
#define CONFIG          0x1A
#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 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//从机地址 MPU6050地址
#define Address         0x68//MPU6050操作相关函数
static int mpu6050_init(int fd,uint8_t addr);
static int i2c_write(int fd, uint8_t addr,uint8_t reg,uint8_t val);
static int i2c_read(int fd, uint8_t addr,uint8_t reg,uint8_t * val);
static short GetData(int fd,uint8_t addr,unsigned char REG_Address);int main(int argc,char *argv[] )
{int  fd;fd = I2C_SLAVE;if(argc < 2){printf("Wrong use !!!!\n");printf("Usage: %s [dev]\n",argv[0]);return -1;}fd = open(argv[1], O_RDWR); // open file and enable read and  writeif (fd < 0){printf("Can't open %s \n",argv[1]); // open i2c dev file failexit(1);}//初始化MPU6050mpu6050_init(fd,Address);while(1){usleep(1000 * 10);printf("ACCE_X:%6d\n ", GetData(fd,Address,ACCEL_XOUT_H));usleep(1000 * 10);printf("ACCE_Y:%6d\n ", GetData(fd,Address,ACCEL_YOUT_H));usleep(1000 * 10);printf("ACCE_Z:%6d\n ", GetData(fd,Address,ACCEL_ZOUT_H));usleep(1000 * 10);printf("GYRO_X:%6d\n ", GetData(fd,Address,GYRO_XOUT_H));usleep(1000 * 10);printf("GYRO_Y:%6d\n ", GetData(fd,Address,GYRO_YOUT_H));usleep(1000 * 10);printf("GYRO_Z:%6d\n\n ", GetData(fd,Address,GYRO_ZOUT_H));sleep(1);}close(fd);return 0;
}static int mpu6050_init(int fd,uint8_t addr)
{i2c_write(fd, addr,PWR_MGMT_1,0x00);  //配置电源管理,0x00,正常启动i2c_write(fd, addr,SMPLRT_DIV,0x07);  //设置MPU6050的输出分频既设置采样i2c_write(fd, addr,CONFIG,0x06);  //配置数字低通滤波器和帧同步引脚i2c_write(fd, addr,ACCEL_CONFIG,0x01);  //设置量程和 X、Y、Z 轴加速度自检return 0;
}static int i2c_write(int fd, uint8_t addr,uint8_t reg,uint8_t val)
{int retries;uint8_t data[2];data[0] = reg;data[1] = val;//设置地址长度:0为7位地址ioctl(fd,I2C_TENBIT,0);//设置从机地址if (ioctl(fd,I2C_SLAVE,addr) < 0){printf("fail to set i2c device slave address!\n");close(fd);return -1;}//设置收不到ACK时的重试次数ioctl(fd,I2C_RETRIES,5);if (write(fd, data, 2) == 2){return 0;}else{return -1;}}static int i2c_read(int fd, uint8_t addr,uint8_t reg,uint8_t * val)
{int retries;//设置地址长度:0为7位地址ioctl(fd,I2C_TENBIT,0);//设置从机地址if (ioctl(fd,I2C_SLAVE,addr) < 0){printf("fail to set i2c device slave address!\n");close(fd);return -1;}//设置收不到ACK时的重试次数ioctl(fd,I2C_RETRIES,5);if (write(fd, &reg, 1) == 1){if (read(fd, val, 1) == 1){return 0;}}else{return -1;}
}static short GetData(int fd,uint8_t addr,unsigned char REG_Address)
{char H, L;i2c_read(fd, addr,REG_Address, &H);usleep(1000);i2c_read(fd, addr,REG_Address + 1, &L);return (H << 8) +L;
}

保存退出,接下来再进行编译运行

1
2
3
gcc i2c_mpu6050.c -o mpu6050sudo ./mpu6050 /dev/i2c-3

效果如下图所示

未找到图片show

三次数据的采集

3.9. 更多

更多关于rk-i2c的驱动以及GPIO模拟I2C等可以查看: rk开源手册 /Common/I2C

3.10. 参考资料

本文档主要提供有一定经验的使用者快速入门使用,对于初学者可查看以下文档:

《I2C通讯》

rk开源资料(github): 《开源手册》

相关文章:

I2C通讯

3.1. 本章节的代码仓库 1 2 3 4 5 6 #如之前有获取则可跳过 #获取仓库 git clone https://gitee.com/LubanCat/lubancat_rk_code_storage.git#代码所在的位置 lubancat_rk_code_storage/quick_start/i2c3.2. i2c I2C(Inter&#xff0d;Integrated Circuit)是一种通用的总线协…...

Excel实现单元格内容拼接

一、应用场景&#xff1a; 场景A&#xff1a;将多个单元格拼接&#xff0c;比如写测试用例时&#xff0c;将多个模块拼接&#xff0c;中间用“-”隔开 场景B&#xff1a;将某单元格内容插入另一单元格固定位置&#xff08;例如在B1中添加A1的内容&#xff09; 二、实际应用&a…...

2025前端面试遇到的问题(vue+uniapp+js+css)

Vue相关面试题 vue2和vue3的区别 一、核心架构差异 特性Vue2Vue3响应式系统基于Object.defineProperty基于Proxy&#xff08;支持动态新增/删除属性&#xff09;代码组织方式Options API&#xff08;data/methods分块&#xff09;Composition API&#xff08;逻辑按功能聚合&am…...

大模型核心基础简介

大模型核心基础简介目录 一、大模型简介定义核心特征 二、大模型的发展历程1. 早期奠基&#xff08;1950s–2010s&#xff09;1950s–1980s&#xff1a;神经网络萌芽1990s–2010s&#xff1a;深度学习前夜 2. 架构革命&#xff1a;Transformer的诞生与预训练范式&#xff08;20…...

广东省省考备考(第八天5.11)—言语:逻辑填空(每日一练)

错题 解析 第一空&#xff0c;搭配“期盼”&#xff0c;且根据“生命&#xff0c;是来自上天的馈赠”&#xff0c;可知父母对孩子的出生是非常期盼的。A项“望穿秋水”&#xff0c;形容对远地亲友的殷切盼望&#xff0c;C项“望眼欲穿”&#xff0c;形容盼望殷切&#xff0c;均…...

github+ Picgo+typora

github Picgotypora 本文将介绍如何使用Picgo在typora中实现上传服务 创建github仓库以及配置token 创建仓库 注意需要Initialize 添加README 配置为public 配置token github点击头像找到setting 选择Developer setting 配置token generate 选第一个第二个都行(我这里选第…...

[网安工具] IP 信息收集工具 —— LBD · 使用手册

&#x1f31f;想了解其它网安工具&#xff1f;看看这个&#xff1a;[网安工具] 网络安全工具管理 —— 工具仓库 管理手册 lbd | Kali Linux ToolsVideolbd Usage ExampleTest to see if the target domain (example.com) is using a load balancer:rootkali:~# lbd example.c…...

本贴会成为记录贴

这几天有些心力交瘁了 一方面带着对互联网下行的伤心&#xff0c;一方面是对未来的担忧 一转眼好像就是20 21那个 可以在宿舍肆意玩手机 大学生活 可是我不小了 是个26岁的人了 时间很快 快的就好像和自己开了一个玩笑 我以为可以找到一个自己足够喜欢的 可爱的人 可是我没有 …...

说说es配置项的动态静态之分和集群配置更新API

这天因为某件工作来到了es官网某个参数配置相关的页面&#xff0c;注意到了下图圆圈里的“Dynamic”&#xff1a; 链接&#xff1a;https://www.elastic.co/guide/en/elasticsearch/reference/8.1/modules-cluster.html#misc-cluster-settings 显然这是对配置项的一个描述&am…...

LLMs之Mistral Medium 3:Mistral Medium 3的简介、安装和使用方法、案例应用之详细攻略

LLMs之Mistral Medium 3&#xff1a;Mistral Medium 3的简介、安装和使用方法、案例应用之详细攻略 目录 Mistral Medium 3 简介 1、Mistral Medium 3 特点 Mistral Medium 3 安装和使用方法 2、使用方法 (1)、创建Agent (2)、模型微调 Mistral Medium 3 案例应用 Mistr…...

并发设计模式实战系列(17):信号量(Semaphore)

&#x1f31f; 大家好&#xff0c;我是摘星&#xff01; &#x1f31f; 今天为大家带来的是并发设计模式实战系列&#xff0c;第十七章信号量&#xff08;Semaphore&#xff09;&#xff0c;废话不多说直接开始~ 目录 一、核心原理深度拆解 1. 信号量本质模型 2. 并发控制…...

RAGMCP基本原理说明和相关问题解惑

一、RAG架构原理和局限性 1.1 概念解释 RAG&#xff08;Retrieval-Augmented Generation&#xff09;&#xff1a;检索增强生成&#xff0c;让大模型接受外部输入后&#xff0c;总结输出 向量数据库&#xff1a;向量数据通常是高维空间中的点&#xff0c;代表复杂的数据结构…...

Java学习手册:服务注册与发现

一、服务注册与发现的概念 在微服务架构中&#xff0c;服务注册与发现是核心功能之一。由于微服务架构中服务实例的数量和位置是动态变化的&#xff0c;服务注册与发现机制允许服务实例在启动时自动注册到注册中心&#xff0c;并在停止时自动注销。其他服务可以通过查询注册中…...

双向Transformer:BERT(Bidirectional Encoder Representations from Transformers)

基于Transformer架构&#xff0c;通过双向上下文建模训练&#xff0c;提高完成任务的性能。 一 BERT的核心理念 1.1双向上下文建模依赖 之前讲的双向递归是用两个RNN进行&#xff0c;而BERT是通过Transformer的自注意力机制同时捕捉上下文信息。 1.1.1掩码语言模型&#xf…...

EdgeOne Pages MCP 入门教程

什么是MCP&#xff1f; MCP (Model Context Protocol) 是一个开放协议&#xff0c;允许 AI 模型安全地与本地和远程资源进行交互。通过在支持 MCP 的客户端&#xff08;如 Cline、Cursor、Claude 等&#xff09;上进行统一配置&#xff0c;可以让 AI 访问更多资源并使用更多工…...

Maven 公司内部私服中央仓库搭建 局域网仓库 资源共享 依赖包构建共享

介绍 公司内部私服搭建通常是为了更好地管理公司内部的依赖包和构建过程&#xff0c;避免直接使用外部 Maven 中央仓库。通过搭建私服&#xff0c;团队能够控制依赖的版本、提高构建速度并增强安全性。公司开发的一些公共工具库更换的提供给内部使用。 私服是一种特殊的远程仓…...

1688代采系统:技术架构与应用实践

在电商领域&#xff0c;1688 作为国内领先的 B2B 电商平台&#xff0c;拥有海量的商品信息。这些数据对于企业采购决策、市场分析、价格监控和供应链管理具有重要价值。本文将详细介绍如何使用 Python 爬虫技术&#xff0c;通过 1688 的商品详情接口&#xff08;item_search 和…...

一种混沌驱动的后门攻击检测指标

摘要 人工智能&#xff08;AI&#xff09;模型在各个领域的进步和应用已经改变了我们与技术互动的方式。然而&#xff0c;必须认识到&#xff0c;虽然人工智能模型带来了显著的进步&#xff0c;但它们也存在固有的挑战&#xff0c;例如容易受到对抗性攻击。目前的工作提出了一…...

【2025最新】为什么用ElasticSearch?和传统数据库MySQL与什么区别?

Elasticsearch 深度解析&#xff1a;从原理到实践 一、为什么选择 Elasticsearch&#xff1f; 数据模型 Elasticsearch 是基于文档的搜索引擎&#xff0c;它使用 JSON 文档来存储数据。在 Elasticsearch 中&#xff0c;相关的数据通常存储在同一个文档中&#xff0c;而不是分散…...

c++的模板和泛型编程

c的模板和泛型编程 泛型编程函数模板函数模板和模板函数函数模板的原理函数模板的隐式、显式实例化模板参数的匹配原则 类模板类模板的实例化模板的使用案例用函数模板运行不同的模板类用函数模板运行不同的STL容器 模板的缺省参数非类型模板参数模板的特化函数模板的特化类模板…...

Java从入门到精通 - 数组

数组 此笔记参考黑马教程&#xff0c;仅学习使用&#xff0c;如有侵权&#xff0c;联系必删 文章目录 数组1. 认识数组2. 数组的定义和访问2.1 静态初始化数组2.1.1 数组的访问2.1.1 定义代码实现总结 2.1.2 数组的遍历2.1.2.1 定义代码演示总结 案例代码实现 2.2 动态初始化…...

MySql事务索引

索引 1.使用 创建主键约束&#xff08;PRIMARY KEY&#xff09;、唯一约束&#xff08;UNIQUE&#xff09;、外键约束&#xff08;FOREIGN KEY&#xff09;时&#xff0c;会自动创建 对应列的索引。 2.创建索引&#xff08;普通索引&#xff09; 事务&#xff1a;要么全部…...

八股文-js篇

八股文-js篇 1. 延迟执行js的方式2. js的数据类型3. null 和 undefined的区别4. 和 的区别5. js微任务和宏任务6. js作用域7. js对象9. JS作用域this指向原型8. js判断数组9. slice作用、splice是否会改变原数组10. js数组去重11. 找出数组最大值12. 给字符串新增方法实现功能…...

DeepSeek:开启教育测评智能化新时代

目录 一、引言二、DeepSeek 技术概述2.1 DeepSeek 的发展历程与特点2.2 工作原理与技术架构 三、测评试题智能生成3.1 生成原理与技术实现3.2 生成试题的类型与应用场景3.3 优势与面临的挑战 四、学生学习评价报告4.1 评价指标体系与数据来源4.2 DeepSeek 生成评价报告的流程与…...

【2025五一数学建模竞赛B题】 矿山数据处理问题|建模过程+完整代码论文全解全析

你是否在寻找数学建模比赛的突破点&#xff1f;数学建模进阶思路&#xff01; 作为经验丰富的美赛O奖、国赛国一的数学建模团队&#xff0c;我们将为你带来本次数学建模竞赛的全面解析。这个解决方案包不仅包括完整的代码实现&#xff0c;还有详尽的建模过程和解析&#xff0c…...

智能制造环形柔性生产线实训系统JG-RR03型模块式环形柔性自动生产线实训系统

智能制造环形柔性生产线实训系统JG-RR03型模块式环形柔性自动生产线实训系统 一、产品概述 (一)组成 柔性系统须有五个分系统构成即&#xff1a;数字化设计分系统、模拟加工制造分系统、检测装配分系统、生产物分流系统和信息管理分系统。它应包含供料检测单元&#xff0c;操作…...

1.2.2.1.4 数据安全发展技术发展历程:高级公钥加密方案——同态加密

引言 在密码学领域&#xff0c;有一种技术被图灵奖得主、著名密码学家Oded Goldreich誉为"密码学圣杯"&#xff0c;那就是全同态加密&#xff08;Fully Homomorphic Encryption&#xff09;。今天我们就来聊聊这个神秘而强大的加密方案是如何从1978年的概念提出&…...

Java大师成长计划之第18天:Java Memory Model与Volatile关键字

&#x1f4e2; 友情提示&#xff1a; 本文由银河易创AI&#xff08;https://ai.eaigx.com&#xff09;平台gpt-4o-mini模型辅助创作完成&#xff0c;旨在提供灵感参考与技术分享&#xff0c;文中关键数据、代码与结论建议通过官方渠道验证。 在Java多线程编程中&#xff0c;线程…...

Lua再学习

因为实习的项目用到了Lua&#xff0c;所以再来深入学习一下 函数 函数的的多返回值 Lua中的函数可以实现多返回值&#xff0c;实现方法是再return后列出要返回的值的列表&#xff0c;返回值也可以通过变量接收到&#xff0c;变量不够也不会影响接收对应位置的返回值 Lua中传…...

GitLab搭建与使用(SSH和Docker)两种方式

前言 目前公共的代码仓库有很多&#xff0c;比如:git、gitee等等仓库但是我们在公司中&#xff0c;还是要搭建属于本公司自己的一个代码仓库&#xff0c;原因有如下几点 代码私密性&#xff0c;我们公司开发的代码保密性肯定一级重要&#xff0c;那么我们放到公网上&#xff0c…...