龙芯2K0300开发笔记(新手向:到点灯和视频图像颜色识别处理)

四天三夜的电赛,我们报名的是龙芯2K300linux嵌入式开发

在此之前是没有怎么系统的学习过linux的,啥都不懂。

这个文章是记录根据培训视频所写下的笔记

想学习的朋友也可以跟着我的脚步。面向新手哈哈哈

但是解决办法可能不是最好的。如果有歪了的欢迎回复指正

暂停更新。电赛结束,学完C语言了。去学32了

笔记源文件以及所有会用到的软件工具。在我的gitee仓库中可以看到。 大家可以克隆 ~

目录

创建VMware虚拟机部分

第一步下载VMware虚拟机

第二步创建一个linux虚拟机

创建虚拟机

配置虚拟机

配置虚拟机网络

配置系统整体环境

安装 VMware Tools(复制文字信息\代码用)

安装vim

配置软件源更新为国内的清华源

配置虚拟机与Windows的共享文件夹

配置龙芯交叉编译环境

安装gcc和make

在共享文件夹创建code文件

使用vim编辑文件

编译main.c文件

理解为什么需要配置龙芯交叉编译环境

构建龙芯交叉编译环境

MobaXterm的简单使用和对交叉编译的再理解

编译内核

[杂]7.12线下讲课录播学习笔记

PMON

2k0300的性能参数

linux系统的构成

一些简单的指令

文件的命名规则

linux安装文件的方法

虚拟机安装vs-code(以后写代码可以用到)

在内核下测试gpio控制

一、分析GPIO口对应板卡的位置

二、点灯原理

三、写一个流水灯程序

7.13线下讲课录播学习笔记

安装OpenCV和配置OpenCV环境来进行图像/视频的颜色识别与处理

什么是OpenCV

安装Anaconda

使用opencv来进行图像处理

使用opencv来进行图片颜色识别

使用opencv来进行视频颜色识别


大家如果看教程有啥不懂的可以去「龙芯2k0300官方文档资料」 链接:夸克网盘分享

写在前面!!龙芯2K0300的最好用ubuntu的20.04版本。不然会出一些奇奇怪怪的意外 我之前就用22.04弄loongson的交叉编译环境的时候,没办法用loong-gcc去编译。 所以如果有这个升级提示的话千万不要升级!!

 

分割线—————————————————

创建VMware虚拟机部分

第一步下载VMware虚拟机

虚拟机的安装文件大家可以去我的夸克网盘中下载。

现在夸克网盘去某鱼上五六块钱就能买一个年卡超级好。下载贼快

我用夸克网盘分享了「VMware-workstation-full-17.0.0-20800274.exe」 链接:夸克网盘分享

下载后安装打开就可以了。不会有人连下载安装都不会吧

安装位置最好选到C盘以外的固态盘,并新建一个文件夹来装他

第二步创建一个linux虚拟机

虚拟机在这里我们用的是unbutu20.04系统,我把unbutu的文件也共享给大家。

我用夸克网盘分享了「ubuntu-20.04.6-desktop-amd64.1.iso」 链接:夸克网盘分享

创建虚拟机

  1. 打开VM软件.创建虚拟机在左上角有文件→新建虚拟机(快捷键显示Ctrl+N)
  2. 推荐大家用自定义来新建虚拟机,不懂的也可以用典型来创建
  3. 下一步,到安装程序光盘映像文件 这里就是选择我们下载的Ubuntu系统。
  4. 然后输入我们的名字和密码。密码要记住哦。最好是全英文
  5. 再往下就是命名和选择虚拟机位置了。建议位置放到固态盘,并且空间较大的地方
  6. 再往下就是选择处理器配置,一般2-4个处理器数量就够用了,内核选1。你选的越多虚拟机就越快,当然对你电脑的负荷就越大。在填之前可以先搜索一下自己的CPU是几核的。
  7. 再往下就是选择内存 内存4G就够用,电脑差点的话可以选择2G
  8. 网络类型默认(NAT)就好
  9. I/O控制器默认(LSI Logic)就好
  10. 磁盘类型默认(SCSI)就好
  11. 选择磁盘默认(创建新的虚拟磁盘)就好
  12. 指定磁盘容量默认就好,默认将磁盘拆分成多个文件,方便管理。内存比较少的可以少分配一点,
  13. 下面一步是指定磁盘文件的位置,把他到第五步的位置就行,方便管理
  14. 然后下一步,看一下配置有没有问题,点击完成就可以了!

配置虚拟机

  1. 一直点 下一步 Continue、 安装 Iinstall Now就可以了
  2. 到选择地区就选择中国就OK
  3. 然后输入自己的名字和密码之类的
  4. 下面点继续慢慢等就OK
  5. 最后点现在重启

到这里,我们的ubuntu就安装完啦!

配置虚拟机网络

  1. 在虚拟机打开的状态下,找到左上角的编辑

  2. 点击虚拟机网络编辑器

  3. 点击右下角的更改设置

  4. 点击外部连接为Nat模式的那一行

  5. 选择,然后勾选下面的使用本地 DHCP 服务将 IP 地址分配给虚拟机

  6. 点击确定,就可以看到虚拟机有网了

    gif图附上

 

配置系统整体环境

一些开发板,他们在设计的时候往往被设计为低功耗之类的,所以龙芯2K0300他的性能没有那么好,但是编译的时候往往是很消耗资源的。所以就需要别的主机来帮助他编译一个执行文件。最好不要在本地进行编译。 所以我们用虚拟机帮助2k0300进行编译

那为什么一定要安装龙芯交叉编译环境呢? 因为你用别的编译工具编译之后,人家龙芯的linux不认识啊。 所以就需要把虚拟机的Ubuntu弄成龙芯交叉编译环境 让他生成龙芯认识的可执行程序

这就用到了交叉编译环境,交叉编译环境就是在这X86的主机上编译一个别的平台的可执行文件 比如ARM、龙芯

平时我们在Windows环境写的代码,其实都是本地编译

到时候只需要把编译后的文件转移到2K0300的板子上就可以直接运行了。

在Ubuntu系统上,有操作界面,但是在这里我都用终端来进行操作

安装 VMware Tools(复制文字信息\代码用)

安装 VMware Tools 可以方便我们在虚拟机和Windows之间文字的复制粘贴 它原本其实是可以传输文件的,但20.04版本后很多解决办法都不行了。

  1. 把虚拟机关闭在我的计算机 处,右键新建的ubuntu系统。进入设置

  2. 选择硬件,选择CD/DVD 2 右边有使用ISO映像文件

  3. 找到VMware安装目录,找到Linux.iso 文件 。然后确定

    比如我的是D:\\VMware\\linux.iso

  4. 记得勾选上已连接,不然在ubuntu里是看不到这个软盘的

  5. 然后开启虚拟机,这时点开文件管理,会有一个VMware Tools 的软盘

  6. 在左侧找到VMware Tools 的软盘,找到后缀为tar.gz的文件把他拖动到桌面上 或者右键,拷贝到桌面上

  7. 下面我们把这个文件解压一下。 在桌面右键打开终端(按Ctrl+Alt+T也可以打开)然后输入 tar -xvf VMware_Toolsxxxxxx.tar.gz(用tab可以补全指令)

  8. 然后桌面上就会多一个文件夹:vmware-tools-distrib 点进去右键开启终端(cd vmware-tools-distrib也可以)

  9. 登录管理员,准备运行安装文件(不然没权限) sudo su 注意linux在输入密码的时候是不会显示的哦~

  10. 输入指令,运行安装文件 ./vmware-install.pl 然后一路回车

  11. 完成后点击重启,或输入重启指令 sudo reboot

这样就完成了VMware Tools的安装啦!

安装vim

vim 是一个文本编辑器。当然ubuntu自带的也有,但以后不是图形化界面可就不好啦! sudo apt-get install vim -y 现在我们已经可以在windows和虚拟机之间复制信息了 你可以在Ubuntu系统的命令行窗口下按Ctrl+Shift+V粘贴或者+C复制

配置软件源更新为国内的清华源

使用国内源更稳定,还能加速下载。 官网如下: ubuntu | 镜像站使用帮助 | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror (如果你是别的系统,可以输入lsb_release -a来查看当前的系统,然后根据清华源的官网的提示来更换相应地文本) 我这里是Ubuntu 20.04 LTS (focal)

  1. 首先备份系统原有的更新源配置文件: sudo cp /etc/apt/sources.list /etc/apt/sources.list_backup
  2. 然后使用文本编辑器(如sudo vim /etc/apt/sources.list)打开sources.list文件, 将其内容替换为清华的源。以下是 **Ubuntu 22.04(Jammy)**的清华源示例:
# 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释
deb <https://mirrors.tuna.tsinghua.edu.cn/ubuntu/> focal main restricted universe multiverse
# deb-src <https://mirrors.tuna.tsinghua.edu.cn/ubuntu/> focal main restricted universe multiverse
deb <https://mirrors.tuna.tsinghua.edu.cn/ubuntu/> focal-updates main restricted universe multiverse
# deb-src <https://mirrors.tuna.tsinghua.edu.cn/ubuntu/> focal-updates main restricted universe multiverse
deb <https://mirrors.tuna.tsinghua.edu.cn/ubuntu/> focal-backports main restricted universe multiverse
# deb-src <https://mirrors.tuna.tsinghua.edu.cn/ubuntu/> focal-backports main restricted universe multiverse

# 以下安全更新软件源包含了官方源与镜像站配置,如有需要可自行修改注释切换
deb <http://security.ubuntu.com/ubuntu/> focal-security main restricted universe multiverse
# deb-src <http://security.ubuntu.com/ubuntu/> focal-security main restricted universe multiverse

# 预发布软件源,不建议启用
deb <https://mirrors.tuna.tsinghua.edu.cn/ubuntu/> focal-proposed main restricted universe multiverse
# deb-src <https://mirrors.tuna.tsinghua.edu.cn/ubuntu/> focal-proposed main restricted universe multiverse

在vi文本编辑器下,清除所有文本需要进入命令模式(按 Esc 键)。 按shift + :键开始输入命令。 输入 %d 然后按回车键。表示全部删除。 输入然后输入i 进入编辑模式,开始输入(Ctrl+Shift+V可以粘贴)。 输入完毕后按ESC键,再按shift + :输入set noreadonly取消文件只读设置 然后shift + : 输入wq 然后回车(w为保存,q为退出)

恭喜啊!!到这一步,你就成功的将软件源配置为清华源了。 可以验证一下,输入sudo apt update 系统将从清华源获取软件包信息并进行更新 并且不会出现错误提示。

配置虚拟机与Windows的共享文件夹

开启虚拟机的状态下

  1. 点击虚拟机 , 选择 设置

  2. 点击选项, 点击 共享文件夹

  3. 点击 总是启用 , 点击添加,选择windows的文件夹(建议放到虚拟机的文件夹里) 我的目录在这里:D:\\VMware_xuniji\\2K0300_loong_99p\\temp

  4. 现在我们就可以在虚拟机Ubuntu中的/mnt/hgfs/中找到我们的共享文件夹 我的文件夹是/mnt/hgfs/temp

  5. 输入指令,提升权限,准备输入指令

    sudo chmod 777 /etc/fstab

  6. 进入/etc目录打开fstab文件 vim /etc/fstab

    在文件编辑末尾添加(怎么编辑上面告诉你了): .host:/ /mnt/hgfs fuse.vmhgfs-fuse allow_other,uid=0,gid=0,umask=022 0 0


    保存成功后重启虚拟机即可,共享文件夹永久不丢失。

  7. 最后使用命令创建该文件夹的快捷方式到桌面,方便打开 ln -s /mnt/hgfs/temp/ /home/lzji/Desktop/

    注意其中的**tempDesktop** 要根据你的共享文件夹名称 或者 系统的语言来更改 (到目录前用tab补全就行)

    /mnt/hgfs/temp(共享文件夹)创建一个叫code的文件夹 为了方便和windows文件传输,我以后会把代码和编译的文件都放到共享文件夹里

配置龙芯交叉编译环境

安装gcc和make

sudo apt-get install gcc make 这是用来编译代码的

在共享文件夹创建code文件

打开我们的temp文件。右键打开终端 创建文件夹指令:mkdir 进入文件夹指令:cd 创建文件 指令:touch

为了防止有小笨蛋,我还是附上gif图吧~

使用vim编辑文件

我想让他输出Hello Word! 那么就要在我刚才创建的main.c文件中输入对应的代码

#include <stdio.h>

int main()
{
	printf("Heloo World\\n");
	return 0;
}

然后保存,离开

我们可以查看我们刚才写的内容

使用cat main.c

编译main.c文件

我们在windows上的如vscode这些软件,实际上都是一个编译器,他们把我们的代码编译成可以运行的程序。

在Linux上也是如此,我们需要把我们刚才的main.c文件编译成可执行文件! 这就需要我们刚才下载的gcc和make了!

  1. 我们输入在code文件夹下输入编译命令: gcc main.c -o test 这段代码的意思是,使用gcc编译器编译main.c文件为可执行文件 -o是指定输出文件的名称为后面的test

  2. 好啦!现在编译完了,我们就可以运行刚才编译好的test 使用./文件名

可以看到,已经编译成功了

理解为什么需要配置龙芯交叉编译环境

我们刚才使用gcc编译了一个可执行文件test。

我们可以输入file test来查看这个文件的属性

可以看到,他是一个X86-64的文件属性是X86的可执行文件。 并不是龙芯的架构

所以!!我们现在要正式进行龙芯的交叉编译环境的构建啦!!

构建龙芯交叉编译环境

 👉 一、下载和移动交叉工具链到共享文件夹

针对2K0300的龙芯的交叉编译环境,我们需要下载他的交叉编译工具链

我仍然是用夸克网盘贴到这里,大家自行下载

我用夸克网盘分享了「loongson-gnu-toolchain-8.3-x86_64-loongarch64-linux-gnu-rc1.3-1.tar.xz」 链接:夸克网盘分享

我们通过Windows下载然后,直接丢到temp(共享文件夹中)来实现传输到虚拟机 你其实可以直接在Windows上把共享文件夹的快捷方式丢到桌面上。

!!!写在前面:压缩包传输到temp(共享文件夹)后不要直接在ubuntu里直接解压一定要拖出去或者mv到桌面上 再进行解压操作。不然会解压不完全。后面的交叉编译会报错。其他类似的操作也是!!(写教程时血的教训!弄了两三次)

如图:

 👉 二、配置交叉工具链到Bash环境

先把这个文件mv到桌面上。

然后我们需要在ubuntu系统中 对他进行解压 仍然是使用sudo tar -xvf loongson……….来解压(使用Tab补全哦~)

解压完之后,我们把解压出的文件移动到根目录的**/opt/**文件下去 因为/opt/的文件夹是用来存储软件工具类的 使用mv指令:sudo mv 原地址 /opt/

现在我们打开这个目录,输入: cd /opt/loongson-gnu-toolchain-8.3-x86_64-loongarch64-linux-gnu-rc1.3-1/bin 其实就是我们解压出的文件夹的/bin文件中

输入pwd可以看到当前 的文件路径

我们复制这个路径 /opt/loongson-gnu-toolchain-8.3-x86_64-loongarch64-linux-gnu-rc1.3-1/bin

打开配置Bash环境的文件进行编辑 vim ~/.bashrc 按照export PATH=/opt/loongson-gnu-toolchain-8.3-x86_64-loongarch64-linux-gnu-rc1.3-1/bin:$PATH 的格式来写入(如果按照我的方法操作直接复制即可) 再次提示:在命令行中按Ctrl+Shift+V进行粘贴

 

然后ESC Shift+: 输入wq 回车保存退出

最后一步!!输入source ~/.bashrc来重新加载一下Bash环境然后重启一下(重启比较稳妥)

👉 三、使用龙芯交叉工具链编译code中的main.c

我们现在已经成功的把龙芯交叉编译链加入到了Bash环境中。

现在在终端中输入loongarch然后使用Tab键进行补全 想必就会出现龙芯的交叉编译工具了!! 显示如下图就代表成功啦

 

那么我们使用loongarch64中的gcc来编译一下main.c文件吧

输入loongarch64-linux-gun-gcc main.c -o loong_test 来编译main.c文件为loong_test

 

下面查看一下架构,输入file

 

他显示是unkown arch 其实正常应该是loongarch架构。但是不影响使用给我们培训的那个老师都是这样,我也不知道咋弄(但是我第一次弄的时候是可以显示出来loongarch的!!)

这时候我们可以在我们的本地环境尝试运行一下 输入./loong_test

 

它显示:哎呀,我不认识这个。

为什么呢? 因为体系结构不匹配呀,我之前不是说了嘛。 loongarch和我们ubuntu的环境、架构不一样。所以里无法运行

但是如果你现在把这个文件放到2K0300的板子上可就不一样啦!! 他是可以运行的

致此,龙芯的交叉编译环境已经弄好了

下面我们简单对MobaXterm 的使用和再深度理解一下交叉编译~

MobaXterm的简单使用和对交叉编译的再理解

下载MobaXterm,大家可以看这篇博客,我就不发网盘了 MobaXterm-Chinese中文版本安装及简单使用_mobaxterm汉化-CSDN博客

链接板子一般有三种方式,sshVNC串行连接

一般板子刚到,都需要用串行连接去配置VNC或者ssh

因为这个板子是没有图形化界面的,所以就不去配置vnc占用资源了。

而ssh一般都自己配置有

所以我们直接用去用ssh链接板子就行。ssh需要链接公网或者在一个局域网下。

写在前边:最简单的方法就是直接把板子通过网线插到路由器,然后在路由器后台查询ip然后直接ssh链接进行配置

在这里我用的是在一个局域网下, 我有一台路由器,我们几个人的电脑都是连接在我的路由器下。

然后板子通过我的电脑的共享网口 通过WLAN连的网,让用一根网线连接着的板子也有了网,并且我可以通过Windows电脑的cmd指令的arp-a 可以查询到连接到电脑网口的板子的ip地址。这时候我们有了ip地址就可以通过MobaXterm 来对板子进行ssh链接了。 后续可以通过配置板子的wifi来让他开机自动连接路由器,这时候只需要通着电就行了。不需要链接网口了。

一、使用MobaXterm

左上角有一个会话 点击之后他提供了很多的连接方式,我们选择ssh 把IP填查询到的IP、就好, ssh端口在没有修改的情况下默认是22不用动

链接上之后需要我们输入账号密码,我就不多赘述了

操作和ubuntu的终端是一样的,不过我们可以在MobaXterm上直观地查看到我们的文件树。可以在Windows上通过鼠标方便的来给予文件操作权限,删除,和移动

我们只需要把共享文件夹的文件拖动到文件树的某个文件上,他就会把文件传输到板子中

现在尝试一下。

我们把我们用gcc 编译的 test 和 用loongarch架构的gcc编译的loong_test 都传输到板子上看看直接拖动到MobaXterm中就OK

传输时遇到没有权限,就输入chmod 777 想要传输到的文件夹

二、交叉编译再理解

当我们使用./ 来运行test。可以看到 test 在龙arch架构的2K0300板子上是运行不了的

但是loong_test是可以正常输出hello world 的 。

我们使用file指令来再查看一下他们的架构。可以看到。 lonngarch已经可以有显示出来了。 而test的则是X86的结构

这就是交叉编译!!

编译内核

linux的内核编译修改定制其实是比较难的,需要懂很多东西,才能去进行修改什么的 在这里是只演示一下怎么把内核去编译出来

至于后面我们要增加什么驱动,后续再更新。或者在网上搜索一下 因为linux的内核编译很多都是通用的

下面我们再编译一下

先把内核源码压缩文件放到这里,大家自己下载

我用夸克网盘分享了「linux-4.19-0627.tar.gz」 链接:夸克网盘分享

仍然是把他移动到桌面上,然后解压。不要再共享文件夹内解压

加压完之后,打开进入到解压的文件夹内.就可以准备开始编译内核

  1. 安装编译依赖

    sudo apt-get update sudo apt-get install bison libncurses5-dev libssl-dev flex

  2. 复制文件夹内arch/loongarch/configs/loongson_2k300_defconfig的配置寄文件到根目录

    cp arch/loongarch/configs/loongson_2k300_defconfig .config

  3. 下面我们可以通过这个指令,来打开图形化的配置文件界面

    make menuconfig ARCH=loongarch

    这个没咋看懂,先不讲

  4. 编译内核 输入 make vmlinuz ARCH=loongarch CROSS_COMPILE=loongarch64-linux-gnu- -j 4

    看到代码开始滚动就代表开始了。

  5. 这个过程大概需要十分钟左右

    致此 ,编译内核完成

[杂]7.12线下讲课录播学习笔记

上面都是线上第一天学的。

PMON

一般是开发厂商做的最底层的固件,是引导系统的。 相当于电脑主板的BIOS 所以我们一般不需要去动PMON。如果你动坏了需要拿专用的编程器才能刷回去

2k0300的性能参数

linux系统的构成

  • /dev:是“Device(设备)”的缩写,存放着 Linux 的外部设备,访问设备的方式与访问文件相同。
  • /etc:“Etcetera(等等)”的缩写,用于存放所有系统管理所需的配置文件和子目录。
  • /home:这里是用户的主目录,每个用户都有一个以自己账号命名的目录。
  • /bin:“Binaries(二进制文件)”的缩写,存放着最常使用的命令,比如 ls 指令就位于此。若将 /bin 目录下的 ls mv 成 lsss ,则需输入 lsss 才能显示当前目录。
  • /boot:存放着启动 Linux 时使用的核心文件,包括连接文件以及镜像文件。
  • /lib:“Library(库)”的缩写,存放着系统最基本的动态连接共享库,类似于 Windows 里的 DLL 文件。
  • /lost+found:一般为空,当系统非法关机后,会存放一些文件。

例如,当系统启动时,会从 /boot 目录读取关键的启动文件来初始化系统。而用户在日常使用中,通过 /bin 目录中的命令来执行各种操作,如查看目录内容时会用到 ls 命令。又如,系统运行时会调用 /lib 中的库文件来支持各种程序的正常运行。

  • /media:当系统自动识别如 U 盘、光驱等设备后,会将其挂载到这个目录下。
  • /mnt:系统提供此目录以便用户临时挂载其他文件系统,例如可以将光驱挂载在 /mnt/ 上,然后进入该目录查看光驱内容。
  • /opt:“optional(可选)”的缩写,是为主机额外安装软件所设置的目录。例如安装 ORACLE 数据库可放置于此,默认情况下该目录为空。
  • /proc:“Processes(进程)”的缩写,是一种伪文件系统(虚拟文件系统),存储着当前内核运行状态的特殊文件。这是个虚拟目录,是系统内存的映射,能直接访问此目录获取系统信息。
  • /root:是系统管理员(超级权限者)的用户主目录。
  • /sbin:“s”代表“Super User”,即“超级用户的二进制文件”,这里存放着系统管理员使用的系统管理程序。

举例来说,当插入一个 U 盘时,系统会将其自动挂载到 /media 目录下,用户可以在该目录找到并访问 U 盘中的文件。而对于一些临时需要访问的外部文件系统,就可以通过挂载到 /mnt 来操作。如果要获取系统的 CPU 信息、内存使用情况等,就可以从 /proc 目录中相应的文件读取。系统管理员在进行一些关键的系统管理操作时,会使用 /sbin 目录下的程序,比如进行系统服务的启动和停止等。

一些简单的指令

chomd 777 xxx #给予运行权限
uname -a #查看系统架构
date #显示当前日期
cal #日历
df -h #显示磁盘使用情况
pwd #打印当前目录
echo #输出信息
			#比如echo $PATH
cat #查看文件
cd ..#回到上级目录
cd - #回到上个历史工作目录
cd ~ #回到当前登录用户的家目录
cd / #切换到根目录

cp #复制文件或目录
mv #移动/重命名文件和目录
mkdir #创建目录
rm #删除文件和目录
ln #创建硬链接和符号
    #类似于创建快捷方式
touch #创建文件

? #通配符
   #举个栗子
   touch main.c mian1.c main2.c
   现在使用rm 来删除
   rm mian?.c
   就指挥删除main.1.c 和  main2.c
head #查看文件的开头几行
tail #查看文件的结尾几行
more #浏览文本内容
less #浏览文本内容

文件的命名规则

在linux中, 没有Windows中“文件扩展名”的概念

在linux中,以“.“字符开头的文件是隐藏文件,需要用 ls -a才能显示出来

  • 注意不要在文件名中使用空格

linux安装文件的方法

  1. sudo apt-get install 安装 比如 sudo apt-get install gcc make #install可以安装多个软件

  2. 百度上搜索deb文件来手动安装,来实践操作一下

    虚拟机安装vs-code(以后写代码可以用到)

    我用夸克网盘分享了「软件安装包」 链接:夸克网盘分享

    这里面是vs-code的安装包

    linux安装软件的方法是 sudo dpkg -i xxx.deb

    然后可以在这里打开

    来简单配置一下,我们再左边找到插件,可以先下载一个chines和C的插件

    重启一下文件,这样就完成了基本的环境搭建。后面我们会用到这个软件

  3. ubuntu自带的商店安装

    没啥介绍的

在内核下测试gpio控制

在**「龙芯2k0300官方文档资料」**中的 2.8

有在PMON下测试gpio的,还有在内核下测试的 我们在这里只需要了解在内核下测试就OK 了!

放张原图。

我们只需要知道这些指令就OK 了

一、分析GPIO口对应板卡的位置

在「LS2K0300久久派_V1.1_板卡使用手册_20240607」的第 2.3.4 中

比如我们现在控制我们板子上的83号引脚,对于83号引脚,我们可以查看他的电路图来找到连接的是什么呢?

这就需要我们观察他的硬件原理图了

我用夸克网盘分享了「02_硬件原理图」 链接:夸克网盘分享

打开这个硬件原理图文件夹中的「LS2K0300_user_manual_v0.2_内部参考版.pdf」。 向下滑 可以看到83号GPIO口的信息是这样子的

芯片引脚 | GPIO 复用 | 主功能复用 | 第一复用 | 第二复用 TIM1_CH 3 | GPIO83 | tim1_ch3 | spi_miso[1] | i2c_sda[2]

现在打开这个硬件原理图文件夹中的「2K0300_99PAI_V1.1_0430.pdf」。 使用Ctrl+F搜索TIM1_CH3 就轻而易举的找到了这个原理图

可以看到,这是一个共阳极的二极管,所以当我们设置他的电平为低电平就可以让他灭掉

二、点灯原理

在 Linux 系统中,通过向特定文件写入内容来控制 GPIO(通用输入/输出)是一种常见的操作方式。

先把点亮这颗led作为目的把!

  1. 首先我们要确保我们的 账户权限是最高权限,也就是root权限

    在ssh连接上板子登录之后,输入sudo su 来登录root账户

    密码往往是默认密码loongson 或者root

  2. 输入以下指令

    1. echo 83 >/sys/class/gpio/export 这段话的意思是向系统注册GPIO引脚83。这时候如果我们去gpio的文件目录下使用ls指令,就会发现多了一个gpio83的文件夹。我们所谓的控制他的输入输出模式,以及高低电平。实际上就是通过修改文件的内容来进行的。

    2. echo "out"> /sys/class/gpio/gpio83/direction

      这段话的意思是向gpio83对应的direction文件写入字符串"out",将该 GPIO 引脚设置为输出模式。如果写入"in"则表示设置为输入模式。

    3. echo "1"> /sys/class/gpio/gpio83/value

      这段话的意思是向gpio83对应的value文件写入字符串"1",将 GPIO 引脚的输出值设置为高电平。如果要设置为低电平,可以写入"0"

好了!到这里我们就已经知道了如何去控制led。那么下面去造个火箭吧!

三、写一个流水灯程序

  1. 在2K0300板子上写一个bash脚本来控制io口

我们可以现在板子上利用ssh 写一个bash脚本来控制io口

我们去code文件夹中 ,用touch来创建一个后缀为.sh的文件

然后用vim打开,输入

#!/bin/bash
#应该由Bash shell解释器来执行程序

# 导入GPIO 83
echo 83 > /sys/class/gpio/export

# 设置GPIO 83为输出模式
echo "out" > /sys/class/gpio/gpio83/direction

# 循环控制GPIO 83的状态,以达到闪烁的效果
while true; do
    # 将GPIO 83设置为低电平(1)亮
    echo "0" > /sys/class/gpio/gpio83/value
    sleep 1  # 延时1秒
    
    # 将GPIO 83设置为高电平(0)灭
    echo "1" > /sys/class/gpio/gpio83/value
    sleep 1  # 再次延时1秒
done

这段代码的第一句 while true; do 是一个无限循环的开始。while 是循环结构的关键字,true 表示条件永远为真,所以这个循环会一直执行下去,直到程序被强制终止(比如通过 Ctrl + C )

执行看一下,可以看到我们的板子已经开始流水灯了

  1. 在虚拟机上编写流水灯代码,并编译到2K0300运行

    有板子的GPIO口的功能以及引脚对应图。我们可以观察来使用。在这里我们打算点亮gpio的第64 65 66 67. 对应 io插针接口的 第21 25 27 23.找到并对应起来就OK啦!

这里只是写了一个最简单的,没有考虑那么多。 正常的话要考虑错误处理、资源管理、以及逻辑的清晰和代码的可扩拓展性

  1. 我们之前下载了vscode,可以用vscode来编辑 没有的话,用touch LedWater.c 来创建文件,Vim来编辑

  2. 打开vscode在左上角找到文件打开文件夹。 然后找到根目录点击open

  3. 找到我们的的共享文件夹里的code文件 一般在home 你的名字 Desktop 你挂载到桌面的共享文件夹 code

  4. 然后可以通过右键来新建文件。命名为LedWater.c 就可以了

  5. 下面开始编写代码

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    int main() 
    {
        //注册gpio 64 65 66 67四个口
        system("echo 64 > /sys/class/gpio/export");
        system("echo 65 > /sys/class/gpio/export");
        system("echo 66 > /sys/class/gpio/export");
        system("echo 67 > /sys/class/gpio/export");
        //初始化所有口为 输出模式
    	system("echo ""out"" > /sys/class/gpio/gpio64/direction");	
    	system("echo ""out"" > /sys/class/gpio/gpio65/direction");	
    	system("echo ""out"" > /sys/class/gpio/gpio66/direction");	
    	system("echo ""out"" > /sys/class/gpio/gpio67/direction");	
    	//初始化所有gpio 为1  不亮
    	system("echo ""1"" > /sys/class/gpio/gpio64/value");
    	system("echo ""1"" > /sys/class/gpio/gpio65/value");
    	system("echo ""1"" > /sys/class/gpio/gpio66/value");
      system("echo ""1"" > /sys/class/gpio/gpio66/value");
       while (1)
        {
        	system("echo ""0"" > /sys/class/gpio/gpio64/value");
            sleep(1);
        	system("echo ""1"" > /sys/class/gpio/gpio64/value");
     
        	system("echo ""0"" > /sys/class/gpio/gpio65/value");
            sleep(1);
        	system("echo ""1"" > /sys/class/gpio/gpio65/value");
        
        	system("echo ""0"" > /sys/class/gpio/gpio66/value");
            sleep(1);
        	system("echo ""1"" > /sys/class/gpio/gpio66/value");
        
        	system("echo ""0"" > /sys/class/gpio/gpio67/value");
            sleep(1);
        	system("echo ""1"" > /sys/class/gpio/gpio67/value");
       }
       
       
        return 0;
    
    }
    
  6. 然后用龙芯的工具链进行编译 loongarch64-linux-gnu-gcc LedWater.c -o LedWater

  7. 然后把编译好的LedWater文件传输到板卡中。

  8. 然后在板卡上运行程序 ./LedWater

7.13线下讲课录播学习笔记

安装OpenCV和配置OpenCV环境来进行图像/视频的颜色识别与处理

什么是OpenCV

OpenCV(全称为Open Source Computer Vision Library)是一个开源的计算机视觉库,由英特尔公司发起并开发,支持多种编程语言(如C++、Python、Java等),旨在为计算机视觉领域的研究、开发和应用提供一组通用的工具和算法。

OpenCV可以用于处理数字图像和视频数据,其功能包括图像和视频的读取、写入、显示、变换、滤波、特征提取、目标检测、人脸识别、物体跟踪、相机标定、三维重建、机器学习等。

当今,计算机视觉在各种应用领域中都扮演着重要的角色,如自动驾驶、智能家居、医学影像、机器人视觉等,而OpenCV则作为计算机视觉领域的重要工具之一,为这些应用领域提供了丰富的功能和算法支持。

安装Anaconda

Anaconda指的是一个开源的Python发行版本,其包含了conda、Python等180多个科学包及其依赖项。因为包含了大量的科学包,Anaconda是一个开源的包、环境管理器,可以用于在同一个机器上安装不同版本的软件包及其依赖,并能够在不同的环境之间切换。总而言之,Anaconda就是可以便捷获取包且对包能够进行管理,同时对环境可以统一管理的发行版本。

在这里。我们先在Windows上调试完毕,再把文件放到linux系统中。

  1. 安装Python

安装这个之前要先确认电脑有Python环境。去官网下载即可 官网贴在这里,自己去下载Download Python | Python.org 比较慢,耐心等待(或者去下载别人提供到云盘的安装包)

安装的时候记得把PATH环境勾选上。

  1. 安装Anaconda

然后再去下载Anaconda 官网贴在这里自己去下载:下载 Anaconda 发行版 |蟒蛇 需要输入邮箱,然后在邮箱内收取文件的下载地址,在这里我们先下载Windows的

下载好之后打开程序

在这里要全部勾选上。因为要添加环境变量。这样可以通过命令行方式调用 Anaconda 程序

然后一直点下一步。

安装好之后,按win+R键打开”运行“ 然后输入cmd 打开终端 输入**conda --version** 此时如果出现conda xx.xx.x 就代表已经安装成功并且可以用命令行操作了

如果失败就重新安装。

  1. 输入conda env list

conda env list 命令列出的是 Conda 创建的所有虚拟环境及其相关信息。虚拟环境的主要作用是为不同的项目或需求搭建独立的 Python 运行环境,使得单个项目的运行环境与其他项目互不影响。

在一台电脑上开发多个不同的项目时,可能会需要用到同一个包的不同版本。如果在同一个目录下安装或更新包,新版本可能会覆盖旧版本,从而导致其他项目无法正常运行。而虚拟环境可以为每个项目提供独立的环境,允许在不同环境中安装和管理特定版本的 Python 以及相关的包。

例如,一个项目可能需要 Python 3.6 以及特定版本的一些库,而另一个项目则需要 Python 3.8 和其他版本的库。通过创建不同的虚拟环境,你可以在每个环境中安装满足相应项目需求的 Python 版本和库,从而避免版本冲突问题。

所以我们需要再创建一个虚拟的运行环境,来运行我们的OpenCV

  1. 新建一个虚拟运行环境:输入conda create -n python_opencv python=3.8

conda create -n python_opencv python=3.8 这条命令的含义如下:

conda create :这是 Conda 用于创建新环境的命令。

  • n python_opencv :n 选项用于指定要创建的环境的名称,这里将新环境命名为 python_opencv 。

python=3.8 :指定在新创建的环境中使用 Python 3.8 版本。

总的来说,这条命令的作用是创建一个名为 python_opencv 的 Conda 环境,并且在这个环境中安装 Python 3.8 。

安装好之后,他会提示你如何激活和关闭这个虚拟Python环境

这时我们再输入conda env list 就会多显示出来你创建的一个新的虚拟环境 但先别着急打开他,我们需要初始化 Conda。来正确激活它。避免出错

  1. 输入conda init powershell,来初始化 Conda

  2. 然后输入指令 set-executionpolicy -ExecutionPolicy RemoteSigned -Scope LocalMachine,修改 PowerShell 限制策略。此操作是为了允许本地脚本运行。

  3. 关闭当前的 PowerShell 窗口,然后重新打开一个新的 PowerShell 窗口

  4. 从此之后就可以直接输入 conda activate python_opencv 命令来激活虚拟环境了。如果正确打开。左边会有小括号括起来显示你当前的虚拟环境。会是这个样子的:

  5. 然后我们再opencv的虚拟环境中使用pip安装opencv的包 pip install opencv-python -i <https://pypi.tuna.tsinghua.edu.cn/simple>

    pip 是 Python 的包管理工具,用于安装、升级和卸载 Python 包。

    opencv-python 是 OpenCV 库的一个 Python 接口。OpenCV 是一个广泛使用的开源计算机视觉库,提供了许多用于图像处理、目标检测、图像识别等任务的功能和算法。 而后面的-i <https://pypi.tuna.tsinghua.edu.cn/simple> 则是通过指定清华大学的镜像源来提高下载速度。

    安装完后,就配置好我们所需要的虚拟环境以及python环境和Anaconda、OpenCV了

使用opencv来进行图像处理

安装好之后。我们新建一个文件夹。

我用夸克网盘分享了「颜色识别.zip」 链接:夸克网盘分享

下载这些文件,把这些文件解压到一个文件夹中。

我们先使用一下这个readimg.py的文件来了解一下图像识别

右键以文本的方式打开这个文件。

代码如下

#读取、显示、保存图片
#这行代码导入了 cv2 库,并将其重命名为 cv ,以便后续使用。
import cv2 as cv
#读取当前文件夹下名为test的png图片并转化为灰度图
path = "./test.png"
gray_img = cv.imread(path,cv.IMREAD_GRAYSCALE)

#新建一个名为Winname的窗口,属性设置为可手动调整大小
cv.namedWindow('Winname',cv.WINDOW_NORMAL)

#在Winname窗口上显示读取到的灰度图
cv.imshow('Winname',gray_img)

#保存灰度图为jpg类型,并设置其图像质量为100
cv.imwrite("./test_gray.jpg",gray_img,(cv.IMWRITE_JPEG_QUALITY,100))

#程序停止,一直等待按键
cv.waitKey(0)

我们在这个文件夹下打开cmd终端。 可以在文件夹路径框输入cmd。然后回车,这样可以在当前文件夹下打开cmd终端 比较方便。

然后我们激活我们的虚拟环境 conda activate <环境名称> 在这里我输入的是conda activate python_opencv

!然后用python来运行readimg.pypython ./readimg.py 这时候就会出来一张图片,然后文件夹中也会出现一张处理后的图片

 

使用opencv来进行图片颜色识别

颜色识别我们使用的是Color_Image.py 这个py文件。

用记事本打开后代码如下:

import Color
import cv2
import numpy as np

"""
color = {'red_high': [255, 255, 255], 'red_low': [0, 0, 0],
         'green_high': [255, 255, 255], 'green_low': [0, 0, 0],
         'blue_high': [255, 255, 255], 'blue_low': [0, 0, 0]}
"""
# 读取颜色阈值
color = Color.color
color_list = ['red', 'green', 'blue']
color_value = {'red': [0, 0, 255], 'green': [0, 255, 0], 'blue': [255, 0, 0]}

# 更新颜色阈值
def Update_Color(colors):
    with open('./Color.py', 'w') as f:
        temp_s = "color = {}".format(str(colors))
        print(temp_s)
        f.write(temp_s)

def nothing(x):
    pass

# 创建滑动条
cv2.namedWindow('get_color')
cv2.createTrackbar('low_L', 'get_color', 0, 255, nothing)
cv2.createTrackbar('low_A', 'get_color', 0, 255, nothing)
cv2.createTrackbar('low_B', 'get_color', 0, 255, nothing)
cv2.createTrackbar('high_L', 'get_color', 255, 255, nothing)
cv2.createTrackbar('high_A', 'get_color', 255, 255, nothing)
cv2.createTrackbar('high_B', 'get_color', 255, 255, nothing)

# 获取滑动条阈值
def get_Trackbar_color():
    low_L = cv2.getTrackbarPos('low_L', 'get_color')
    low_A = cv2.getTrackbarPos('low_A', 'get_color')
    low_B = cv2.getTrackbarPos('low_B', 'get_color')
    high_L = cv2.getTrackbarPos('high_L', 'get_color')
    high_A = cv2.getTrackbarPos('high_A', 'get_color')
    high_B = cv2.getTrackbarPos('high_B', 'get_color')
    return [low_L, low_A, low_B], [high_L, high_A, high_B]

def get_color(frame):
    while True:
        blur_image = cv2.blur(frame, (3, 3))  # 平滑图像
        lab_image = cv2.cvtColor(blur_image, cv2.COLOR_BGR2LAB)  # 转换颜色空间
        colorLow, colorHigh = get_Trackbar_color()  # 获取滑动条颜色阈值
        lab_mask = cv2.inRange(lab_image, np.array(colorLow), np.array(colorHigh))  # 颜色阈值分割
        cv2.imshow('image', lab_mask)  # 显示图像帧
        k = cv2.waitKey(25)  # 每25ms读取一次键盘按键,同时控制帧率
        if k == ord('q'):  # 当检测到键盘q键按下,程序退出
            cv2.destroyWindow('image')  # 销毁窗口
            break
        elif k == ord('r'):  # 修改颜色阈值
            color['red_high'] = colorHigh
            color['red_low'] = colorLow
        elif k == ord('g'):  # 修改颜色阈值
            color['green_high'] = colorHigh
            color['green_low'] = colorLow
        elif k == ord('b'):  # 修改颜色阈值
            color['blue_high'] = colorHigh
            color['blue_low'] = colorLow
        elif k == ord('s'):  # 更新颜色阈值
            Update_Color(color)

def color_detection(frame):
    while True:
        # state, frame = cap.read()  # 抓取每一帧图像
        lab_image = cv2.cvtColor(frame, cv2.COLOR_BGR2LAB)  # 颜色空间转换
        blur_image = cv2.blur(lab_image, (3, 3))            # 平滑滤波操作
        drawing = frame.copy()
        for col in color_list:
            # 颜色阈值分割
            lab_mask = cv2.inRange(blur_image, np.array(color[col + '_low']), np.array(color[col + '_high']))
            Kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
            lab_mask = cv2.morphologyEx(lab_mask, cv2.MORPH_OPEN, Kernel)   # 开操作,消除较小的白色噪点
            # 查找轮廓
            contours, hierarchy = cv2.findContours(lab_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[-2:]
            if len(contours) != 0:
                for cnt in contours:
                    drawing = cv2.drawContours(drawing, [cnt], -1, color_value[col], 2, 8)     # 绘制轮廓
                    rect = cv2.minAreaRect(cnt)  # 得到最小外接矩形
                    box = np.int0(cv2.boxPoints(rect))
                    print(col)
                    print(box)
                    cv2.drawContours(drawing, [box], 0, color_value[col], 2)    # 绘制矩形
                    
            cv2.imshow('image', drawing)  # 显示图像帧
        k = cv2.waitKey(25)  # 每25ms读取一次键盘按键,同时控制帧率
        if k == ord('q'):  # 当检测到键盘q键按下,程序退出
            break
        elif k == ord('c'):
            get_color(frame)  # 更新颜色阈值

if __name__ == "__main__":
    # 获取摄像头对象
    # cap = cv2.VideoCapture(0)
    img = cv2.imread('shapes.jpg')
    # 颜色识别
    color_detection(img)
    

这段代码主要实现了基于颜色阈值的图像分割和目标检测功能。

首先,定义了一些颜色的阈值范围和相关的操作函数。

Update_Color 函数用于将更新后的颜色阈值写入到 Color.py 文件中。

nothing 函数是一个空的回调函数,用于滑动条的创建。

然后,创建了一个名为 'get_color' 的窗口,并在其中创建了多个滑动条用于获取颜色阈值。

get_Trackbar_color 函数用于获取滑动条的当前值。

get_color 函数中,对输入的图像进行平滑和颜色空间转换,通过滑动条获取颜色阈值进行分割,并显示分割后的图像。 根据按下的不同按键(qrgbs)执行不同的操作,如退出、修改特定颜色的阈值、更新颜色阈值等。

color_detection 函数同样对图像进行颜色空间转换和平滑处理,针对每种颜色进行阈值分割和轮廓检测,绘制轮廓和最小外接矩形,并显示处理后的图像。通过按键 q 退出,按键 c 调用 get_color 函数更新颜色阈值。

在 if __name__ == "__main__" 部分,读取一张图片 'shapes.jpg' ,并调用 color_detection 函数进行颜色检测和处理。

例如,如果您希望对不同场景中的特定颜色物体进行检测和识别,这段代码可以作为基础,通过调整颜色阈值和图像处理参数来适应具体的需求。比如,在工业生产中检测特定颜色的零件,或者在图像分析中识别特定颜色的标志等。

在这段代码中

  • q 键:在 get_color 函数和 color_detection 函数中,按下 q 键时程序退出。
  • r 键:在 get_color 函数中,按下 r 键时修改红色的颜色阈值。
  • g 键:在 get_color 函数中,按下 g 键时修改绿色的颜色阈值。
  • b 键:在 get_color 函数中,按下 b 键时修改蓝色的颜色阈值。
  • s 键:在 get_color 函数中,按下 s 键时更新颜色阈值并保存到 Color.py 文件中。
  • c 键:在 color_detection 函数中,按下 c 键时调用 get_color 函数来更新颜色阈值。

要使用它。还是在这个文件夹下打开cmd。然后进入python_opencv的虚拟环境中然后输入python ./Color_Image.py

这时候就会打开如下三个窗口

(调成英文输入法后)我们按下按键 c 可以调用 get_color 函数来更新颜色阈值。

现在我们可以通过调节**get_col窗口**的滑块来控制颜色的阈值。我们看着imgae来查看阈值情况

通过调节这六个滑块,imgae窗口为黑底,要检测的颜色为白色的情况。才行

这里拿蓝色举例。调节完毕之后的样子是这样的。需要调好之后按L(因为这里是蓝色)(别的颜色不一样)来保存(其实把所有的r g b全按一遍也行不过会有损精度),然后按q来退出

调节的时候从上往下调。一定要精细一点。

让每个滑块位于图像要消失又要出现的临界点。 如下gif图

但是结果不太直观。下面我们来用视频来进行颜色识别

使用opencv来进行视频颜色识别

颜色识别我们使用的是Color_Video 这个py文件。

用记事本打开后代码如下:

这段代码主要实现了通过摄像头获取实时图像,并基于颜色阈值进行目标检测和轮廓绘制的功能。以下是对代码的详细解释:

  • Update_Color 函数:用于将更新后的颜色阈值字典写入到 Color.py 文件中。
  • nothing 函数:一个空的回调函数,用于创建滑动条时的占位。
  • 滑动条创建:通过 cv2.createTrackbar 创建了 6 个滑动条,分别用于调整低和高的 LAB 值。
  • get_Trackbar_color 函数:获取各个滑动条的当前位置值,即颜色阈值。
  • get_color 函数:
    • 从摄像头读取图像帧,并进行平滑和颜色空间转换。
    • 根据滑动条的阈值进行颜色分割,并显示分割后的图像。
    • 根据按下的不同按键(qrgbs)执行相应的操作,如退出、修改特定颜色的阈值、更新颜色阈值。
  • color_detection 函数:
    • 同样从摄像头读取图像帧,进行颜色空间转换和平滑处理。
    • 针对每种颜色进行阈值分割、轮廓检测和处理。
    • 绘制轮廓和最小外接矩形,并显示处理后的图像。
    • 根据按下的按键(qc)执行相应的操作,如退出、调用 get_color 函数更新颜色阈值。
  • 在 if __name__ == "__main__" 部分:
    • 获取摄像头对象。
    • 调用 color_detection 函数进行实时的颜色检测和处理。

在这个程序中,按键的作用如下:

  • q 键:在 get_color 和 color_detection 函数中,按下 q 键都将导致程序退出。
  • r 键:在 get_color 函数中,按下 r 键会修改红色的颜色阈值。
  • g 键:在 get_color 函数中,按下 g 键会修改绿色的颜色阈值。
  • b 键:在 get_color 函数中,按下 b 键会修改蓝色的颜色阈值。
  • s 键:在 get_color 函数中,按下 s 键会更新颜色阈值并保存到 Color.py 文件中。
  • c 键:在 color_detection 函数中,按下 c 键会调用 get_color 函数来更新颜色阈值。

要使用它。还是在这个文件夹下打开cmd。然后进入python_opencv的虚拟环境 然后输入python ./Color_Video

也是会出现这三个窗口

和刚才的图像处理一样,要求也是一样

先按c进入 更新颜色阈值模式

然后通过自上而下的调节这六个滑块,使imgae窗口为黑底,要检测的颜色为白色的情况。**让每个滑块位于图像要消失又要出现的临界点。**调节的时候从上往下调。一定要精细一点。 需要调好之后按L(别的颜色不一样)来保存(其实把所有的r g b全按一遍也行),然后按q来退出

比如这次我调的阈值为红色。就可以有这样的效果

关闭时可以在cmd窗口按Ctrl+C

  • 30
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值